rajawajahat/opsrunbook-copilot

GitHub: rajawajahat/opsrunbook-copilot

一个运行在 AWS 上的智能事件响应流水线,自动采集故障证据、用 LLM 分析根因并执行 Jira 工单创建、通知推送和代码修复 PR 等响应动作。

Stars: 0 | Forks: 0

# OpsRunbook Copilot [![Python](https://img.shields.io/badge/Python-3.11+-3776AB?style=flat&logo=python&logoColor=white)](https://python.org) [![LangGraph](https://img.shields.io/badge/LangGraph-agentic-1C3C3C?style=flat)](https://github.com/langchain-ai/langgraph) [![AWS](https://img.shields.io/badge/AWS-Lambda%20%7C%20EventBridge%20%7C%20Step%20Functions-232F3E?style=flat&logo=amazonaws&logoColor=white)](https://aws.amazon.com) [![Terraform](https://img.shields.io/badge/Terraform-IaC-7B42BC?style=flat&logo=terraform&logoColor=white)](https://terraform.io) [![License: MIT](https://img.shields.io/badge/License-MIT-green?style=flat)](LICENSE) **一个开源的智能事件响应管道,可监控您的 AWS 服务,使用 LLM 分析错误,并自动执行以下操作:** - 创建包含结构化发现的 **Jira 工单** - 发送 **Teams / Slack 通知** - 提交包含建议代码修复的 **GitHub Pull Request** — 然后根据审查者的反馈自主进行迭代 所有操作均在您自己的 AWS 账户中运行。除 LLM API 调用(Groq 或 Google Gemini — 可灵活替换)外,没有任何数据会离开您的基础设施。 ## 工作原理 ``` Alert / manual trigger │ ▼ ┌─────────────────────┐ │ FastAPI (local │ POST /v1/incidents │ or Lambda+APIGW) │ └──────────┬──────────┘ │ starts ▼ ┌─────────────────────────────────────────────────────┐ │ Step Functions Orchestrator │ │ ┌──────────────┐ ┌───────────┐ ┌───────────────┐ │ │ │ collector_ │ │collector_ │ │ collector_ │ │ │ │ logs │ │ metrics │ │ stepfn │ │ │ └──────────────┘ └───────────┘ └───────────────┘ │ │ └──────────┬──────────┘ │ │ ▼ │ │ snapshot_persist Lambda │ └─────────────────────────┬───────────────────────────┘ │ EventBridge ▼ ┌───────────────────────┐ │ Analyzer Lambda │ LLM → IncidentPacket │ (Groq / Gemini) │ findings, hypotheses, └───────────┬───────────┘ suspected_owners │ EventBridge ▼ ┌───────────────────────┐ │ Actions Runner Lambda│ → Jira ticket │ │ → Teams notification └───────────┬───────────┘ → GitHub PR (simple) │ EventBridge ▼ ┌───────────────────────┐ │ Coding Agent Lambda │ LangGraph ReAct agent │ (LangGraph + Groq) │ → GitHub PR (code fix) └───────────────────────┘ GitHub PR review comment → pr_review_cycle → LLM fix → commit ``` ## 前置条件 | 需求 | 说明 | |---|---| | AWS 账户 | 具有下列权限的 IAM 用户/角色 | | Terraform ≥ 1.5 | [安装](https://developer.hashicorp.com/terraform/install) | | Python 3.11+ | 用于在本地运行 API 和测试 | | Groq API 密钥 **或** Google Gemini API 密钥 | 免费套餐即可。或使用 `llm_provider = "stub"`,通过确定性启发式算法在无 LLM 的情况下运行 | | Jira Cloud 账户 | 用于创建工单(可选 — 可通过 `ACTIONS_DRY_RUN=true` 禁用) | | GitHub App 或 PAT | 用于开启修复 PR(可选) | | Teams 入站 Webhook | 用于发送通知(可选) | ## 快速入门(5 步) ### 1. 克隆并配置 Python 环境 ``` git clone https://github.com/rajawajahat/opsrunbook-copilot.git cd opsrunbook-copilot python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -e "packages/contracts" pip install -r services/api/src/../../../requirements.txt 2>/dev/null || true pip install fastapi uvicorn boto3 pydantic python-dotenv ``` ### 2. 配置 Terraform ``` cd infra/terraform/envs/dev # 复制示例并填入您的值 cp terraform.tfvars.example terraform.tfvars # 编辑 terraform.tfvars — 设置 aws_profile、github_owner 等 ``` ### 3. 部署 AWS 基础设施 ``` # 从 infra/terraform/envs/dev/ terraform init terraform plan # review what will be created terraform apply ``` 这将创建:S3 存储桶、DynamoDB 表、Lambda 函数、Step Functions 状态机、EventBridge 总线、IAM 角色以及 SSM 参数容器。 ### 4. 在 SSM 中设置密钥值 Terraform 创建了带有占位符值的 SSM 参数**容器**。 您必须手动设置真实值(切勿通过 Terraform 设置): ``` # LLM API key(选择一个) aws ssm put-parameter --name /opsrunbook/dev/groq/api_key \ --value "YOUR_GROQ_KEY" --type SecureString --overwrite # 或用于 Gemini aws ssm put-parameter --name /opsrunbook/dev/google/api_key \ --value "YOUR_GOOGLE_KEY" --type SecureString --overwrite # GitHub PAT(需要 repo + pull_requests 权限) aws ssm put-parameter --name /opsrunbook/dev/github/token \ --value "ghp_yourtoken" --type SecureString --overwrite # Jira 凭据 aws ssm put-parameter --name /opsrunbook/dev/jira/base_url \ --value "https://your-org.atlassian.net" --type String --overwrite aws ssm put-parameter --name /opsrunbook/dev/jira/email \ --value "your@email.com" --type String --overwrite aws ssm put-parameter --name /opsrunbook/dev/jira/api_token \ --value "YOUR_JIRA_TOKEN" --type SecureString --overwrite aws ssm put-parameter --name /opsrunbook/dev/jira/project_key \ --value "OPS" --type String --overwrite # Teams webhook(可选) aws ssm put-parameter --name /opsrunbook/dev/teams/webhook_url \ --value "https://your-org.webhook.office.com/..." --type SecureString --overwrite # GitHub webhook secret(用于 PR 审查周期) aws ssm put-parameter --name /opsrunbook/dev/github/webhook_secret \ --value "$(openssl rand -hex 32)" --type SecureString --overwrite ``` ### 5. 配置并启动 API ``` cd services/api # 复制 .env.example 并填入来自 terraform output 的值 cp .env.example .env # 获取 Terraform 输出 cd ../../infra/terraform/envs/dev terraform output # 将这些填入 services/api/.env: # EVIDENCE_BUCKET、INCIDENTS_TABLE、SNAPSHOTS_TABLE、PACKETS_TABLE # STATE_MACHINE_ARN、EVENT_BUS_NAME # 生成 API key 并添加到 .env python -c "import secrets; print(secrets.token_urlsafe(32))" # 添加:API_KEY=<生成的值> # 启动 API cd ../../services/api aws-vault exec -- bash -c \ 'PYTHONPATH=src:../../packages/contracts/src \ PLAN_GENERATOR_PATH=$(pwd)/../../infra/terraform/modules/actions_runner/src \ ../../.venv/bin/uvicorn src.app:app --port 8100 --log-level info' ``` ### 运行冒烟测试 ``` cd /path/to/opsrunbook-copilot export GITHUB_OWNER=your-github-org API_URL=http://127.0.0.1:8100 bash scripts/smoke_it5.sh ``` ## 所需的 AWS IAM 权限 Terraform 和运行中的 Lambda 所使用的 IAM 主体(用户或角色)需要以下权限。请为 Terraform 部署和 Lambda 执行使用独立的角色(最小权限原则)。 ### Terraform 部署角色 ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:*"], "Resource": "arn:aws:s3:::opsrunbook-copilot-*" }, { "Effect": "Allow", "Action": ["dynamodb:*"], "Resource": "arn:aws:dynamodb:*:*:table/opsrunbook-copilot-*" }, { "Effect": "Allow", "Action": ["lambda:*"], "Resource": "arn:aws:lambda:*:*:function:opsrunbook-copilot-*" }, { "Effect": "Allow", "Action": ["states:*"], "Resource": "arn:aws:states:*:*:stateMachine:opsrunbook-copilot-*" }, { "Effect": "Allow", "Action": ["events:*"], "Resource": "*" }, { "Effect": "Allow", "Action": ["iam:*"], "Resource": "arn:aws:iam::*:role/opsrunbook-copilot-*" }, { "Effect": "Allow", "Action": ["ssm:PutParameter","ssm:GetParameter","ssm:DeleteParameter","ssm:DescribeParameters"], "Resource": "arn:aws:ssm:*:*:parameter/opsrunbook/*" }, { "Effect": "Allow", "Action": ["logs:*"], "Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/opsrunbook-copilot-*" } ] } ``` ### Lambda 执行角色(由 Terraform 自动创建) 每个 Lambda 仅被授予其所需的权限: | Lambda | 主要权限 | |---|---| | `collector_logs` | `logs:StartQuery`, `logs:GetQueryResults`, `s3:PutObject`, `events:PutEvents` | | `collector_metrics` | `cloudwatch:GetMetricData`, `s3:PutObject`, `events:PutEvents` | | `collector_stepfn` | `states:DescribeExecution`, `states:ListExecutions`, `s3:PutObject`, `events:PutEvents` | | `snapshot_persist` | `s3:GetObject`, `s3:PutObject`, `dynamodb:PutItem`, `events:PutEvents` | | `analyzer` | `s3:GetObject`, `s3:PutObject`, `dynamodb:PutItem`, `events:PutEvents`, `ssm:GetParameter` | | `actions_runner` | `s3:GetObject`, `dynamodb:PutItem`, `dynamodb:Query`, `events:PutEvents`, `ssm:GetParameter` | | `coding_agent` | `s3:GetObject`, `dynamodb:PutItem`, `events:PutEvents`, `ssm:GetParameter` | | `pr_review_cycle` | `s3:GetObject`, `s3:PutObject`, `dynamodb:PutItem`, `ssm:GetParameter` | ## 配置参考 ### `services/api/.env` | 变量 | 必填 | 描述 | |---|---|---| | `API_KEY` | 是 | 用于 `X-API-Key` 请求头认证的随机密钥。生成方式:`python -c "import secrets; print(secrets.token_urlsafe(32))"` | | `AWS_REGION` | 是 | AWS 区域(例如 `us-east-1`) | | `EVIDENCE_BUCKET` | 是 | S3 存储桶名称(来自 `terraform output evidence_bucket`) | | `INCIDENTS_TABLE` | 是 | DynamoDB 表(来自 `terraform output incidents_table`) | | `SNAPSHOTS_TABLE` | 是 | DynamoDB 表(来自 `terraform output snapshots_table`) | | `PACKETS_TABLE` | 是 | DynamoDB 表(来自 `terraform output packets_table`) | | `STATE_MACHINE_ARN` | 是 | Step Functions ARN(来自 `terraform output state_machine_arn`) | | `EVENT_BUS_NAME` | 是 | EventBridge 总线名称(来自 `terraform output event_bus_name`) | | `GITHUB_WEBHOOK_SECRET` | 用于 PR 审查 | 必须与 SSM `/opsrunbook/dev/github/webhook_secret` 中的值相匹配 | | `GITHUB_APP_SLUG` | 用于 PR 审查 | 您的 GitHub App slug(例如 `opsrunbook-copilot-bot`) | | `PR_REVIEW_STATE_MACHINE_ARN` | 用于 PR 审查 | 来自 `terraform output pr_review_state_machine_arn` | | `PLAN_GENERATOR_PATH` | 本地开发 | 用于 replay 端点的 `infra/terraform/modules/actions_runner/src` 路径 | | `MAX_ROWS_PER_QUERY` | 否 | CloudWatch Insights 行预算(默认:`100`) | | `MAX_BYTES_TOTAL` | 否 | 证据字节预算(默认:`200000`) | | `MAX_TIME_WINDOW_MINUTES` | 否 | 最大分析时间窗口(默认:`15`) | ### SSM 参数(手动设置 — 切勿通过 Terraform 设置) | SSM 路径 | 类型 | 描述 | |---|---|---| | `/opsrunbook/dev/groq/api_key` | SecureString | Groq API 密钥 | | `/opsrunbook/dev/google/api_key` | SecureString | Google Gemini API 密钥 | | `/opsrunbook/dev/github/token` | SecureString | GitHub PAT(需要 `repo` + `pull_requests` 权限范围) | | `/opsrunbook/dev/github/webhook_secret` | SecureString | 在您的 GitHub App 中注册的 HMAC 密钥 | | `/opsrunbook/dev/jira/base_url` | String | `https://your-org.atlassian.net` | | `/opsrunbook/dev/jira/email` | String | Jira 用户邮箱 | | `/opsrunbook/dev/jira/api_token` | SecureString | Jira API token | | `/opsrunbook/dev/jira/project_key` | String | Jira 项目键(例如 `OPS`) | | `/opsrunbook/dev/jira/issue_type` | String | 问题类型(默认:`Bug`) | | `/opsrunbook/dev/teams/webhook_url` | SecureString | Teams 入站 Webhook URL | ### `infra/terraform/envs/dev/terraform.tfvars` | 变量 | 描述 | |---|---| | `aws_region` | AWS 区域 | | `aws_profile` | AWS CLI 配置文件名称 | | `github_owner` | 拥有目标仓库的 GitHub 组织或用户名 | | `github_default_branch` | 用于修复 PR 的默认分支(默认:`main`) | | `github_app_slug` | 用于自身事件过滤的 GitHub App slug | | `llm_provider` | `groq` \| `gemini` \| `stub` | | `evidence_retention_days` | S3 对象保留期(默认:`7`) | ## 调用 API 所有端点(`GET /health` 除外)均需要 `X-API-Key` 请求头。 ``` export API=http://127.0.0.1:8100 export API_KEY=your-api-key-here # 触发 incident 分析 curl -X POST "$API/v1/incidents" \ -H "X-API-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "schema_version": "incident_event.v1", "event_id": "evt-unique-id-001", "service": "payment-service", "environment": "prod", "severity": "critical", "time_window": { "start": "2026-04-06T20:00:00Z", "end": "2026-04-06T20:15:00Z" }, "hints": { "log_groups": ["/aws/lambda/payment-service"] } }' # 轮询 orchestrator 状态 curl -H "X-API-Key: $API_KEY" \ "$API/v1/incidents/{incident_id}/runs/{collector_run_id}" # 获取 LLM 分析 curl -H "X-API-Key: $API_KEY" \ "$API/v1/incidents/{incident_id}/packet/latest" # 获取 Jira/Teams/PR 操作结果 curl -H "X-API-Key: $API_KEY" \ "$API/v1/incidents/{incident_id}/actions/latest" ``` ## 适配您的服务 ### 将其指向您自己的 CloudWatch 日志组 在 `POST /v1/incidents` 请求体中,将 `hints.log_groups` 设置为您应用程序的日志组: ``` "hints": { "log_groups": [ "/aws/lambda/my-payment-service", "/aws/ecs/my-payment-processor", "/aws/rds/my-db-errors" ] } ``` ### 添加 CloudWatch 指标查询 ``` "hints": { "log_groups": ["/aws/lambda/my-service"], "metric_queries": [ { "namespace": "AWS/Lambda", "metric_name": "Errors", "dimensions": {"FunctionName": "my-service"}, "period": 300, "stat": "Sum" } ] } ``` ### 将服务映射到 GitHub 仓库 创建 `infra/terraform/modules/analyzer/src/resource_repo_map.json`: ``` { "payment-service": "your-org/payment-service", "auth-service": "your-org/auth-service", "order-processor": "your-org/order-processor" } ``` 这会告知 analyzer 哪个仓库拥有哪个服务,以便 coding agent 能够向正确的仓库提交修复 PR。 ### 禁用您不需要的自动化操作 ``` # Dry-run 模式:分析并创建 Jira,但不打开 GitHub PR ACTIONS_DRY_RUN=true # Kill switch:仅分析,完全不进行外部操作 AUTOMATION_ENABLED=false # 使用 stub LLM(无需 API key,确定性启发式) # 在 terraform.tfvars 中设置: llm_provider = "stub" ``` ## 本地开发 ``` # 运行所有测试 bash scripts/test.sh # Lint bash scripts/lint.sh # Smoke test:完整流水线(需要 AWS + API 运行中) export GITHUB_OWNER=your-github-org API_URL=http://127.0.0.1:8100 bash scripts/smoke_it5.sh # Smoke test:webhook → PR 审查周期 GITHUB_WEBHOOK_SECRET= GITHUB_REPO=owner/repo PR_NUMBER=17 \ API_URL=http://127.0.0.1:8100 bash scripts/smoke_it6.sh ``` ### 在本地运行 coding agent(不使用 Lambda) ``` cd /path/to/opsrunbook-copilot export GROQ_API_KEY=your-key export GITHUB_TOKEN=ghp_yourtoken python -m packages.agent.runner \ --packet-file tests/fixtures/sample_packet.json \ --repo your-org/your-repo \ --dry-run # omit --dry-run to actually open a PR ``` ## 安全说明 - **密钥**:所有 API 密钥和令牌均存储在 AWS SSM Parameter Store(SecureString)中。它们绝不会出现在 Terraform 状态、环境文件或源代码中。 - **API 认证**:FastAPI 层要求在所有路由(`GET /health` 除外)上提供 `X-API-Key` 请求头。在生产环境中,请将其部署在 VPC 或带有额外网络控制措施的 API Gateway 之后。 - **GitHub webhooks**:使用 `hmac.compare_digest`(时间安全)通过 HMAC-SHA256 进行验证。 - **证据脱敏**:日志在持久化之前,会扫描其中是否包含令牌、API 密钥、密码、AWS 凭证和连接字符串。 - **LLM 数据**:仅将经过脱敏处理的证据文本发送给 LLM 提供商。绝不应转发包含机密的原始日志行。 - **IAM**:Lambda 执行角色遵循最小权限原则(参见上方权限表)。绝不授予宽泛的 `*` 操作权限。 ## 项目结构 ``` opsrunbook-copilot/ ├── packages/ │ ├── agent/ # LangGraph ReAct coding agent │ ├── contracts/ # Pydantic v2 shared schemas (installable package) │ └── llm/ # Shared LLM client (Groq / Gemini / stub) ├── services/ │ ├── api/ # FastAPI entry point + routers + stores │ └── collectors/ # CloudWatch / Step Functions collector library ├── infra/terraform/ │ ├── envs/dev/ # Dev environment wiring (main.tf, variables.tf) │ └── modules/ # One module per Lambda function │ ├── actions_runner/ │ ├── analyzer/ │ ├── coding_agent/ │ ├── collector_logs/ │ ├── collector_metrics/ │ ├── collector_stepfn/ │ ├── orchestrator/ │ ├── pr_review_cycle/ │ ├── snapshot_persist/ │ └── storage/ ├── tests/ # Integration tests + fixtures └── scripts/ # smoke_it*.sh, lint.sh, test.sh ``` ## 许可证 MIT
标签:AIOps, AV绕过, AWS, ChatOps, DevSecOps, DPI, ECS, FastAPI, GitHub自动修复, Jira集成, LangGraph, PB级数据处理, Python, Serverless, Slack通知, SRE, Step Functions, Terraform, 上游代理, 代码审查自动化, 偏差过滤, 基于证据的响应, 多云管理, 安全运维, 报警聚合, 无后门, 模块化设计, 自动化修复, 自动化运维, 逆向工具