dbnz-io/opencdr

GitHub: dbnz-io/opencdr

OpenCDR 是一款开源的 AWS 云检测与响应平台,通过事件驱动架构实时接收 CloudTrail 和 GuardDuty 事件,运行可配置的检测与关联规则,并将安全告警分发给多种通知渠道,同时支持自动化事件响应。

Stars: 0 | Forks: 0

# OpenCDR [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/c1/c11f533ffe6ed7c2a82eccb36e137fa4b52a1e19bef3a69687f8f42064db4fc5.svg)](https://github.com/dbnz-io/opencdr/actions/workflows/ci.yml) ![覆盖率](https://static.pigsec.cn/wp-content/uploads/repos/cas/8b/8bb17f4028b580240439a2462f7602539a9465a376885bd7af11370382b8f0c8.svg) [![License: MPL 2.0](https://img.shields.io/badge/License-MPL_2.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0) 针对 AWS 的开源事件驱动云检测与响应。OpenCDR 接收 CloudTrail 和 GuardDuty 事件,根据可配置的检测规则对其进行评估,关联相关活动,并将警报发送到 Slack、Discord、电子邮件、AWS Security Hub、Jira 或任何 HTTPS webhook——并支持可选的自动化事件响应。 📚 本 README 是快速入门概述和复制粘贴命令参考。如需深度参考文档——包括架构、安全模型以及“查找所需内容”的索引——请参阅 **[`docs/`](docs/README.md)**。 ## 目录 - [工作原理](#how-it-works) - [架构](#architecture) - [完整设置](#complete-setup) - [前置条件](#prerequisites) - [必须启用 CloudTrail](#cloudtrail-must-be-enabled) - [组织级部署](#organization-level-deployment) - [安装依赖项](#install-dependencies) - [部署](#deployment) - [CloudWatch 警报](#cloudwatch-alarms) - [可观测性](#observability) - [成本追踪](#cost-tracking) - [多区域覆盖](#multi-region-coverage) - [环境变量](#environment-variables) - [CI/CD 部署(OIDC,无长期密钥)](#cicd-deployment-oidc-no-long-lived-keys) - [OpenCDR CLI](#opencdr-cli) - [快速开始](#quick-start) - [命令](#commands) - [开箱即用 — 检测规则](#batteries-included--detection-rules) - [信号规则](#signal-rules) - [关联规则](#correlation-rules) - [本地测试规则](#testing-rules-locally) - [集成测试(已部署的 stack)](#integration-testing-deployed-stack) - [编写检测规则](#writing-detection-rules) - [信号规则](#signal-rule) - [关联规则](#correlation-rule) - [自动化事件响应](#automated-incident-response) - [responder 如何进行授权](#how-the-responder-authorizes-itself) - [通知](#notifications) - [Slack 和 Discord](#slack-and-discord) - [通过 SNS 发送电子邮件通知](#email-notifications-via-sns) - [AWS Security Hub](#aws-security-hub) - [Jira](#jira) - [自定义 webhook](#custom-webhook) - [通过 SNS 进行自定义集成](#custom-integrations-via-sns) - [SIEM 集成](#siem-integrations) - [API](#api) - [项目结构](#project-structure) - [运行测试](#running-tests) - [许可证](#license) ## 工作原理 ``` EventBridge (CloudTrail / GuardDuty) └─► processor — normalizes events, runs detection rules → writes signals └─► alerter — runs correlation rules → writes alerts + outbox └─► publisher — drains outbox → SQS ├─► notifier — sends alerts to Slack / Discord / Email / Security Hub / Jira / custom webhook └─► responder — executes automated IR actions (disable user, isolate EC2, block S3…) ``` REST API 允许您在运行时查询信号、日志和规则,并管理配置。 ## 架构 | 组件 | 触发器 | 职责 | |---|---|---| | **processor** | EventBridge rule | 解析事件 → 规范化 → 运行信号检测 → 存储信号 | | **alerter** | DynamoDB stream (signals) | 运行关联规则 → 存储警报 → 写入发件箱 | | **publisher** | DynamoDB stream (outbox) | 认领发件箱记录 → 发布到 SQS 队列 | | **notifier** | SQS (notifications) | 格式化并将警报发送到 Slack / Discord / 电子邮件 (SNS) / Security Hub / Jira / 自定义 webhook | | **responder** | SQS (responses) | 通过 IAM / EC2 / S3 执行事件响应操作 | | **api** | API Gateway (HTTP) | 查询信号、日志、规则;管理设置 | 所有状态都保存在 DynamoDB 中(按需计费)。发件箱模式保证了从 alerter 到 SQS 的至少一次交付,且无需直接耦合。 ## 完整设置 以下部分深入介绍了每个步骤。依次进行,从一个干净的 AWS 账户到一个完全正常运行的部署: 1. **前置条件** — Node.js、Serverless Framework、Python 3.12、AWS 凭证、已启用 CloudTrail。 2. **部署 stack** — `serverless deploy --stage dev`。 3. **加载内置检测规则** — `./scripts/load_rules.sh --stage dev`。 4. **配置通知渠道** — `python3 scripts/opencdr.py setup`(交互式;也会执行第 3 步)。 5. **设置警报交付** — 关于运营健康状况,而非安全警报;`alarmEmail` 参数或 Slack SSM 参数。 6. **启用成本追踪** — 两个手动的 AWS 控制台步骤,然后运行 `./scripts/cost_report.sh`。 7. **接入其他区域** — 仅当您的账户在多个区域运行时;否则在部署区域之外将处于盲目状态。运行 `./scripts/setup_region_forwarding.sh`。 8. **接入其他账户** — 仅当您需要跨账户事件响应时;单账户无需此操作。在另一个账户中创建同名 IR 角色,然后注册它:`curl -X POST "$OPENCDR_API_URL/ir-roles" -H "x-api-key: $OPENCDR_API_KEY" -d '{"aws_account_id": "", "role_arn": ""}'` — 完整演练(信任策略、终止开关)请见 [`docs/ir-role.md`](docs/ir-role.md#multi-account-onboard-each-additional-account)。 9. **设置 CI/CD** — 可选,建议在一次性评估之外使用。在 [`ci-bootstrap/`](ci-bootstrap/README.md) 中进行一次性引导,然后每次推送到 `main` 分支都会自动部署。 10. **端到端验证** — `./scripts/test_deployed.sh`。 对于单账户、单区域评估,步骤 7–9 是可选且可跳过的。完整细节、确切命令以及每个步骤的实际作用:**[`docs/setup.md`](docs/setup.md)**。 ## 前置条件 - [Node.js](https://nodejs.org/) >= 18(CI 本身运行 Node 20) - [Serverless Framework](https://www.serverless.com/) v3 - Python 3.12(与 `serverless.yml` 中的 `provider.runtime` 匹配) - 已配置 AWS 凭证(`aws configure` 或环境变量) - `jq`(用于加载/测试脚本) ### 必须启用 CloudTrail OpenCDR 通过 EventBridge 接收事件。只有当您的账户和区域中激活了 CloudTrail 时,CloudTrail 管理事件才会被交付到 EventBridge。 在部署前启用它: ``` # 创建 trail(一次性设置) aws cloudtrail create-trail \ --name opencdr-trail \ --s3-bucket-name \ --is-multi-region-trail # 开始日志记录 aws cloudtrail start-logging --name opencdr-trail ``` 或者在 AWS 控制台的 **CloudTrail → Trails → Create trail** 下启用。必须启用管理事件(读取 + 写入)——数据事件是可选的。 ### 组织级部署 对于多账户 AWS Organizations 设置,您可以将每个成员账户的所有 CloudTrail 和 GuardDuty 事件路由到一个单一的中央 EventBridge 总线,并在一个专门的安全账户中部署一次 OpenCDR。 ``` Member Account A ─┐ Member Account B ─┼─► EventBridge cross-account rules ─► Central Security Account Member Account C ─┘ EventBridge default bus │ OpenCDR processor Lambda ``` **设置步骤:** 1. 在管理账户中**启用组织追踪**——这会创建一个自动覆盖所有成员账户的 CloudTrail: aws cloudtrail create-trail \ --name org-trail \ --s3-bucket-name \ --is-organization-trail \ --is-multi-region-trail aws cloudtrail start-logging --name org-trail 2. **允许成员账户将事件发送到中央总线。** 在中央安全账户中,向默认的 EventBridge 总线添加资源策略: aws events put-permission \ --action events:PutEvents \ --principal "*" \ --statement-id AllowOrgAccounts \ --condition '{"Type":"StringEquals","Key":"aws:PrincipalOrgID","Value":"o-XXXXXXXXXX"}' 3. **在每个成员账户中创建转发规则**(或通过 CloudFormation StackSets 在整个组织中进行部署),以匹配 CloudTrail 和 GuardDuty 事件并将它们转发到中央总线: aws events put-rule \ --name forward-to-central-opencdr \ --event-pattern '{"source":["aws.cloudtrail","aws.guardduty"]}' \ --state ENABLED aws events put-targets \ --rule forward-to-central-opencdr \ --targets '[{ "Id": "CentralBus", "Arn": "arn:aws:events:::event-bus/default", "RoleArn": "arn:aws:iam:::role/EventBridgeForwardRole" }]' 4. 在中央安全账户中**正常部署 OpenCDR**。processor Lambda 将通过中央总线接收来自所有成员账户的事件,并且信号将包含来源 `aws_account_id` 以便进行分类。 ### 安装依赖项 ``` npm install -g serverless npm install # installs serverless-python-requirements and serverless-iam-roles-per-function ``` ## 部署 ``` # 部署到 dev(默认) serverless deploy # 部署到特定 stage / region serverless deploy --stage prod --region us-west-2 # 使用电子邮件订阅部署 serverless deploy \ --param="alarmEmail=ops@example.com" \ --param="alertEmail=security@example.com" ``` `alarmEmail` 订阅基础设施警报(Lambda 错误、DLQ 深度)。`alertEmail` 订阅安全检测警报。两者都是可选的——您可以稍后通过 SNS topic ARN 进行订阅。 这将创建: - 7 个 Lambda 函数(每个都有自己最小权限的 IAM 角色):processor、alerter、publisher、notifier、responder、api、alarmNotifier - 7 个 DynamoDB 表(signals、alerts、outbox、logs、detection-rules、settings、ir-account-roles) - 2 个带有死信队列的 SQS 队列(notifications、responses) - 1 个流失败队列(捕获来自 DynamoDB streams 的有害记录) - 带有 API key 身份验证的 API Gateway(每月 1 万次请求,100 RPS) - 2 个 SNS topic:基础设施警报(`opencdr--alarms`)和安全警报(`opencdr--alerts`) - 11 个 CloudWatch 警报 + 1 个控制面板(Lambda 错误、DLQ 深度、流迭代器年龄——请参阅 [CloudWatch 警报](#cloudwatch-alarms)) - 1 个月度成本预算,通过与上述警报相同的 Slack pipeline 发出警报(请参阅 [成本追踪](#cost-tracking)) - X-Ray 追踪和用于检测健康状况的自定义 CloudWatch 指标(请参阅 [可观测性](#observability)) - 跨区域事件转发的接收端(一个 IAM 角色 + 总线策略)——发送端需要针对每个额外区域执行单独的可选步骤(请参阅 [多区域覆盖](#multi-region-coverage)) ### CloudWatch 警报 OpenCDR 开箱即用提供了 11 个警报: | 警报 | 指标 | 阈值 | |---|---|---| | `processor`/`alerter`/`publisher`/`notifier`/`responder`/`api` 错误(各一个警报——特意排除了 `alarmNotifier` 本身,以避免出现警报通知循环) | `AWS/Lambda Errors` | > 0 | | 通知 DLQ 深度 | `AWS/SQS ApproximateNumberOfMessagesVisible` | > 0 | | 响应 DLQ 深度 | `AWS/SQS ApproximateNumberOfMessagesVisible` | > 0 | | 流失败队列深度 | `AWS/SQS ApproximateNumberOfMessagesVisible` | > 0 | | Alerter 流迭代器年龄 | `AWS/Lambda IteratorAge` | > 5 分钟 | | Publisher 流迭代器年龄 | `AWS/Lambda IteratorAge` | > 5 分钟 | 所有警报都会交付到 `opencdr--alarms` SNS topic,`alarmNotifier` 会将其转发到 Slack(🔴 ALARM / ✅ OK、名称、描述、原因)——与下方 [成本预算](#cost-tracking) 重用的交付路径相同。在部署时传入 `--param="alarmEmail=you@example.com"`,即可将电子邮件地址直接订阅到该 topic。AWS 将发送一封确认电子邮件——只需点击一次链接即可激活。 一个 CloudWatch Dashboard(`OpsDashboard`,部署后会在 stack 的输出中提供链接)将所有 7 个函数的 Lambda 健康/持续时间/调用情况、所有三个队列深度以及下方的自定义检测健康指标结合在一起。 ### 可观测性 X-Ray 追踪、四个自定义检测健康指标和 `OpsDashboard` CloudWatch 控制面板都是自动配置的,无需任何配置。完整细节——包括 X-Ray 服务映射的节点覆盖范围如何工作——请见 [`docs/observability.md`](docs/observability.md)。 ### 成本追踪 此 stack 创建的每个资源都带有 `Project=opencdr` / `Stage=` 标签,并且每个月度 `AWS::Budgets::Budget`(`serverless.yml` 中的 `CostBudget`)会在达到 80% 实际、100 实际和 100% 预测支出时,通过与上述 CloudWatch 警报相同的 Slack pipeline 发出警报。在部署时传入 `--param="monthlyBudgetUsd="` 来设置阈值(默认为 `50`)。 在其中的任何一项报告真实数据之前,需要在 AWS 账户中进行两个一次性步骤——这两者都是 CloudFormation 无法为您完成的: 1. 启用一次 Cost Explorer(账单控制台 → Cost Explorer)。 2. 激活 `Project`/`Stage` 标签作为成本分配标签(账单控制台 → 成本分配标签)——最多需要 24 小时才会开始显示,并且仅涵盖激活后的支出,而非追溯涵盖。 完成这两步后,使用以下命令获取阶段的支出明细: ``` ./scripts/cost_report.sh --stage dev ./scripts/cost_report.sh --stage prod --granularity MONTHLY --start 2026-07-01 --end 2026-08-01 ``` ### 多区域覆盖 **全新的部署仅覆盖其所在区域。** CloudTrail 将事件交付到发生 API 调用的任何区域的默认 EventBridge 总线——即使对于多区域追踪也是如此——并且 GuardDuty 检测器是按区域划分的。如果您的账户在多个区域中运行,那么在您明确接入每个额外区域之前,部署区域之外的活动将被默默忽略: ``` ./scripts/setup_region_forwarding.sh --stage dev --region eu-west-1 # one region ./scripts/setup_region_forwarding.sh --stage dev --regions eu-west-1,ap-southeast-1 # several ./scripts/setup_region_forwarding.sh --stage dev --region eu-west-1 --remove # tear one down ``` 这会独立地在每个区域上执行,并在遇到失败时继续运行而不是中止整个过程——受限于批准区域列表(AWS Control Tower、SCP)的账户会在被阻止的区域中合理地拒绝此操作,这是预期的,而不是 bug。完整细节(包括确切受影响的信号规则)请见 [`docs/region-forwarding.md`](docs/region-forwarding.md)。 ### 环境变量 | 变量 | 默认值 | 描述 | |---|---|---| | `OPENCDR_IR_ROLE_ARN` | 自动创建的本账户角色 | 当检测到的 AWS 账户在 `irAccountRolesTable` 中没有记录时,responder 假定的备用 IAM 角色——请参阅 [docs/ir-role.md](docs/ir-role.md)。由 `serverless.yml` 自动配置;仅设置此项以覆盖它。 | | `DREDGE_DRY_RUN` | `false` | 设置为 `true` 以模拟 IR 操作而不实际执行它们 | | `RESPONDER_RATE_LIMIT_WINDOW_MINUTES` | `5` | responder 操作速率断路器的滚动窗口 | | `RESPONDER_RATE_LIMIT_MAX_ACTIONS` | `20` | 断路器跳闸前每个窗口的最大破坏性操作数 | | `RESPONDER_ROLE_CACHE_TTL_SECONDS` | `60` | 重新检查 `irAccountRolesTable` 之前,已解析的账户→角色查找的缓存时间 | | `CORRELATION_QUERY_LIMIT` | `300` | 每次关联评估查询的最大信号数 | ### CI/CD 部署(OIDC,无长期密钥) `.github/workflows/ci.yml` 会在每次推送到 `main` 时自动部署到 `dev` 阶段, 使用通过 GitHub 的 OIDC 提供商联合的短期凭证, 而不是长期的 AWS 访问密钥。为您自己的账户(或客户的账户)进行的一次性设置在 [`ci-bootstrap/`](ci-bootstrap/README.md) 中——对于希望使用此方法而非上述手动 `serverless deploy` 流程的采用者,同一模板也可用作参考工作流。请参阅 [`docs/stack-protection.md`](docs/stack-protection.md) 以了解随附的终止保护和漂移检测。 每次 CI 部署还会将阶段的真实 API key 作为 SecureString 写入 SSM Parameter Store (`/opencdr-/api-key`)——使用以下命令检索它: ``` aws ssm get-parameter --name /opencdr-dev/api-key --with-decryption \ --query Parameter.Value --output text ``` 而不是手动将其拉取到本地文件中——这正是之前导致真实密钥被提交到此仓库的原因(请参阅 git 历史记录中的 `.opencdr.json`,现已被移除)。 ## OpenCDR CLI `scripts/opencdr.py` 是一个用于与已部署的 OpenCDR stack 交互的管理 CLI。它包装了 REST API 并提供了一个交互式设置向导。 ### 快速开始 ``` # 交互式设置向导 — 配置 API 连接,加载 rules,并设置通知 python3 scripts/opencdr.py setup # 或手动配置 python3 scripts/opencdr.py config set --url https://.execute-api..amazonaws.com/dev --key ``` 您的 API URL 和密钥会在 `serverless deploy` 的 endpoints 和 API Keys 部分中打印出来。 ### 命令 ``` # 检查 API 健康状态 python3 scripts/opencdr.py status # Rules python3 scripts/opencdr.py rules load # load all rules from support_files/ python3 scripts/opencdr.py rules list --kind signal python3 scripts/opencdr.py rules get --kind signal python3 scripts/opencdr.py rules delete --kind signal # 通知设置 python3 scripts/opencdr.py settings get python3 scripts/opencdr.py settings set --slack-webhook https://hooks.slack.com/... python3 scripts/opencdr.py settings set --discord-webhook https://discord.com/api/webhooks/... python3 scripts/opencdr.py settings set --email-topic-arn arn:aws:sns:::opencdr-dev-alerts python3 scripts/opencdr.py settings set --enable-securityhub python3 scripts/opencdr.py settings set \ --jira-url https://yourco.atlassian.net \ --jira-project SEC \ --jira-email soc@yourco.com \ --jira-token python3 scripts/opencdr.py settings set \ --webhook-url https://events.pagerduty.com/v2/enqueue \ --webhook-name pagerduty python3 scripts/opencdr.py settings set \ --webhook-url https://api.opsgenie.com/v2/alerts \ --webhook-name opsgenie \ --webhook-header "Authorization=GenieKey " python3 scripts/opencdr.py settings set --file support_files/settings/settings.json # full payload # 查询 signals 和日志 python3 scripts/opencdr.py signals list --severity HIGH python3 scripts/opencdr.py logs list --service OCDR-PROCESSOR # 运行测试 python3 scripts/opencdr.py test local python3 scripts/opencdr.py test deployed --stage dev ``` ## 开箱即用 — 检测规则 OpenCDR 内置了 19 条信号规则和 4 条关联规则,涵盖了最常见的 AWS 攻击模式。使用以下命令加载它们: ``` # 将所有 rules 加载到 DynamoDB(dev stage) ./scripts/load_rules.sh # 加载到特定 stage / region ./scripts/load_rules.sh --stage prod --region us-west-2 # 预览而不写入 ./scripts/load_rules.sh --dry-run ``` ### 信号规则 | 规则 | 严重程度 | 战术 | |---|---|---| | `001` 不使用 MFA 的控制台登录 | HIGH | 初始访问 | | `002` Root 账户用于任何操作 | CRITICAL | 权限提升 | | `003` Root 账户控制台登录 | CRITICAL | 初始访问 | | `004` 创建 Root 访问密钥 | CRITICAL | 持久性 | | `005` 创建 IAM 用户 | MEDIUM | 持久性 | | `006` 创建访问密钥 | MEDIUM | 持久性 | | `007` 创建 IAM 角色 | MEDIUM | 持久性 | | `008` 创建或更新 Lambda 函数 | MEDIUM | 持久性 | | `009` 附加 AdministratorAccess 策略 | CRITICAL | 权限提升 | | `010` 创建通配符内联策略 | HIGH | 权限提升 | | `011` 添加安全组入口规则 | MEDIUM | 防御规避 | | `012` CloudTrail 停止、删除或更新 | CRITICAL | 防御规避 | | `013` GuardDuty 检测器被删除或禁用 | CRITICAL | 防御规避 | | `014` AWS Config 记录器被停止或删除 | HIGH | 防御规避 | | `015` 禁用 Security Hub | HIGH | 防御规避 | | `016` 访问 Secrets Manager 密钥 | HIGH | 凭证访问 | | `017` 访问 SSM 参数 | MEDIUM | 凭证访问 | | `018` S3 存储桶被公开 | HIGH | 数据泄露 | | `019` RDS 快照被公开 | HIGH | 数据泄露 | ### 关联规则 | 规则 | 严重程度 | 描述 | |---|---|---| | `020` 控制台登录暴力破解 | CRITICAL | 15 分钟内同一用户进行 5 次以上无 MFA 登录 | | `021` IAM 活动突发 | CRITICAL | 5 分钟内来自同一执行者的 5 个以上 IAM 信号 | | `022` 防御规避激增 | CRITICAL | 10 分钟内禁用 2 个或更多日志/检测服务 | | `023` 凭证收集 | CRITICAL | 5 分钟内来自同一执行者的 3 次或更多密钥/SSM 访问 | ## 本地测试规则 无需部署到 AWS 即可根据样本事件测试所有规则: ``` python3 scripts/test_rules_local.py # 按 event 筛选 python3 scripts/test_rules_local.py --event 012 # 按 rule 筛选 python3 scripts/test_rules_local.py --rule cloudtrail ``` 所有 19 条信号规则的样本事件位于 `support_files/test_events/` 中。 ### 集成测试(已部署的 stack) ``` # 针对已部署的 processor Lambda 测试所有 events ./scripts/test_deployed.sh # 测试单个 event ./scripts/test_deployed.sh --event 009 # 针对 prod 测试 ./scripts/test_deployed.sh --stage prod --region us-west-2 ``` ## 编写检测规则 规则存储在 DynamoDB 中。您可以将它们编写为 JSON 并使用 `load_rules.sh` 加载,或者在运行时通过 API 管理它们。 ### 信号规则 匹配单个规范化事件。当所有条件都通过时,会将信号写入信号表。 ``` { "rule_id": "001_console_login_no_mfa", "rule_kind": "signal", "description": "Console login without MFA.", "enabled": true, "severity": "HIGH", "notify": true, "response_module": "", "playbook": "Verify user and source IP. If suspicious, revoke sessions and enforce MFA.", "conditions": [ { "field": "activity_name", "op": "equals", "value": "ConsoleLogin" }, { "field": "raw_event.detail.additionalEventData.MFAUsed", "op": "equals", "value": "No" } ] } ``` **支持的运算符:** `exists`、`not_exists`、`equals`、`not_equals`、`in`、`not_in`、`contains`、`not_contains`、`prefix`、`suffix`、`matches`(正则表达式)、`wildcard`(匹配任何事件) **条件中可用的规范化字段:** | 字段 | 描述 | |---|---| | `activity_name` | CloudTrail 事件名称(例如 `ConsoleLogin`、`CreateUser`) | | `category` | 从服务派生的事件类别(例如 `iam`、`s3`、`ec2`、`authn`) | | `class_name` | 事件类(`api_activity`、`authentication`、`security_finding`) | | `source` | 事件来源(`cloudtrail`、`guardduty`) | | `severity` | 规范化的严重程度(`CRITICAL`、`HIGH`、`MEDIUM`、`LOW`、`UNKNOWN`) | | `actor.type` | 身份类型(`Root`、`IAMUser`、`AssumedRole`、`FederatedUser`) | | `actor.user_name` | IAM 主体名称 | | `actor.account_id` | 执行者的 AWS 账户 ID | | `actor.arn` | 执行者的完整 ARN | | `network.source_ip` | 源 IP 地址 | | `network.user_agent` | User agent 字符串 | | `api.service` | AWS 服务端点(例如 `iam.amazonaws.com`) | | `api.operation` | API 操作名称 | | `api.error_code` | 如果调用失败,则为 CloudTrail 错误代码 | | `raw_event.detail.*` | 原始 EventBridge 事件 payload 中的任何字段 | ### 关联规则 按字段对信号进行分组,在时间窗口内对其进行计数,并在达到阈值时触发警报。`signal_conditions` 可选择性地过滤哪些信号会计入阈值。 ``` { "rule_id": "020_correlation_console_login_bruteforce", "rule_kind": "correlation", "description": "Multiple MFA-less logins from the same user.", "enabled": true, "severity": "CRITICAL", "group_by": "actor.user_name", "time_window_seconds": 900, "threshold": 5, "signal_conditions": [ { "field": "rule_id", "op": "equals", "value": "001_console_login_no_mfa" } ], "notify": true, "response_module": "disable_user", "playbook": "Disable the user and investigate source IPs." } ``` ## 自动化事件响应 在任何规则上设置 `response_module`,以便在触发时执行自动操作。 | 模块 | 操作 | |---|---| | `disable_user` | 禁用执行者的所有 IAM 访问密钥 | | `delete_user` | 删除 IAM 用户 | | `disable_access_key` | 禁用特定的访问密钥 | | `disable_role` | 向角色附加拒绝所有操作的内联策略 | | `block_s3_public_access` | 启用账户级别的 S3 公共访问阻止 | | `block_s3_bucket_public_access` | 阻止对特定存储桶的公共访问 | | `block_s3_object_public_access` | 将单个 S3 对象设为私有(`ACL=private`) | | `isolate_ec2_instances` | 将实例安全组替换为隔离组 | 设置 `DREDGE_DRY_RUN=true` 以模拟所有 IR 操作而不进行任何更改。 破坏性操作还受到滚动窗口断路器的限制 (每个 `RESPONDER_RATE_LIMIT_WINDOW_MINUTES` 中的 `RESPONDER_RATE_LIMIT_MAX_ACTIONS`,默认为 5 分钟内 20 次)——一旦跳闸,在窗口滚动之前,进一步的匹配检测将被记录并跳过,而不是被执行。 成功的操作不仅仅是记录——它还会通知。`responder` 会将第二个、绿色样式的 Slack/Discord/电子邮件通知加入队列,它与触发它的警报是分开的(此通知类型尚不支持 Security Hub/Jira/webhook),因此“这已被修复”与“这已被检测到”一样可见。请参阅[通知](#notifications)。 ### responder 如何进行授权 responder 自身的 Lambda 执行角色没有任何破坏性的 AWS 权限——它在自己的凭证上唯一能做的就是在*任何* AWS 账户中对名为 `${self:service}-${self:provider.stage}-ir-role`(例如 `opencdr-dev-ir-role`)的角色执行 `sts:AssumeRole`,而不是一揽子授权。响应模块实际执行的所有操作(禁用用户、阻止 S3 公共访问、隔离 EC2 实例等)都是通过假定其中一个角色返回的临时凭证来运行的。 假定哪个角色是**按检测**解析的,基于检测来源的 AWS 账户(`src/handlers/responder.py` 中的 `_resolve_role_arn`): 1. 该账户在 `irAccountRolesTable` DynamoDB 表中有一条已启用的记录 → 假定该记录的 `role_arn`。 2. 该账户有一条记录但已禁用 → 完全跳过操作(记录为 `IR_ACCOUNT_DISABLED`)——**不会**回退到(3)。 3. 该账户没有记录,或者根本无法确定该账户 → `OPENCDR_IR_ROLE_ARN`。 **单账户部署无需为此进行任何设置。** `serverless.yml` 会自动创建本账户的 IR 角色作为 CloudFormation 资源,并自动将 `OPENCDR_IR_ROLE_ARN` 连接到它——仅凭 `serverless deploy` 就足够了;没有手动的 `aws iam create-role` 步骤,也不需要设置环境变量。 **其他账户**(多账户 / 跨账户 IR)的接入方法是在其中手动创建同名角色,并通过 `POST /ir-roles` 添加一行记录: ``` aws iam create-role --role-name opencdr-dev-ir-role \ --assume-role-policy-document file:///tmp/trust-policy.json # see docs/ir-role.md aws iam put-role-policy --role-name opencdr-dev-ir-role \ --policy-name opencdr-ir-permissions \ --policy-document file://docs/ir-role-permissions.json curl -X POST "$OPENCDR_API_URL/ir-roles" -H "x-api-key: $OPENCDR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"aws_account_id": "", "role_arn": "arn:aws:iam:::role/opencdr-dev-ir-role"}' ``` 完整演练(信任策略示例、终止开关/禁用、缓存 TTL、保持权限策略同步)请见 [docs/ir-role.md](docs/ir-role.md)。 ## 通知 通过 CLI 或 API 在设置表中配置渠道和路由。完整示例位于 `support_files/settings/settings.json` 中。 ``` { "setting_id": "global", "notifications_enabled": true, "channels": { "slack": { "enabled": true, "webhook_url": "https://hooks.slack.com/services/..." }, "discord": { "enabled": false, "webhook_url": "https://discord.com/api/webhooks/..." }, "email": { "enabled": false, "topic_arn": "arn:aws:sns:us-east-1:123456789012:opencdr-dev-alerts" }, "securityhub": { "enabled": false }, "jira": { "enabled": false, "base_url": "https://yourco.atlassian.net", "project_key": "SEC", "user_email": "soc@yourco.com", "api_token": "", "issue_type": "Bug" }, "webhook": { "enabled": false, "targets": [ { "name": "pagerduty", "url": "https://events.pagerduty.com/v2/enqueue", "headers": {} }, { "name": "opsgenie", "url": "https://api.opsgenie.com/v2/alerts", "headers": { "Authorization": "GenieKey " } } ] } }, "routing": { "CRITICAL": ["slack", "email", "jira"], "HIGH": ["slack", "securityhub"], "MEDIUM": ["discord"], "LOW": ["webhook"] } } ``` 路由是按严重程度进行的。如果没有匹配的路由条目,所有具有足够配置的已启用渠道都会收到警报。 ### Slack 和 Discord 在 Slack 应用或 Discord 服务器设置中生成传入的 webhook URL,并将其传递给 CLI: ``` python3 scripts/opencdr.py settings set --slack-webhook https://hooks.slack.com/services/... python3 scripts/opencdr.py settings set --discord-webhook https://discord.com/api/webhooks/... ``` webhook URL 是这两个平台的唯一身份验证机制——请将其视为机密。 ### 通过 SNS 发送电子邮件通知 电子邮件通知是通过 stack 创建的 `opencdr--alerts` SNS topic 交付的。 **获取 topic ARN:** ``` aws sns list-topics \ --query "Topics[?contains(TopicArn, 'opencdr') && contains(TopicArn, 'alerts')]" \ --output text ``` **订阅您的电子邮件地址:** ``` aws sns subscribe \ --topic-arn arn:aws:sns:::opencdr--alerts \ --protocol email \ --notification-endpoint you@example.com ``` AWS 将发送一封确认电子邮件——在交付警报之前,请单击链接以激活订阅。 或者,在部署时传入 `--param="alertEmail=you@example.com"`,订阅将自动创建。 **在设置中启用电子邮件:** ``` python3 scripts/opencdr.py settings set \ --email-topic-arn arn:aws:sns:::opencdr--alerts ``` ### AWS Security Hub OpenCDR 可以将发现结果以 [ASFF 格式](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format.html)推送到 Security Hub。发现结果会显示在 Security Hub 控制台中您账户的自定义产品下。 **前提条件:** 必须在您的账户和区域中启用 Security Hub。 ``` # 验证 Security Hub 是否活跃 aws securityhub describe-hub # 启用 channel python3 scripts/opencdr.py settings set --enable-securityhub ``` 无需额外配置——notifier Lambda 会在运行时从其自身的执行上下文中派生出产品 ARN。 ### Jira OpenCDR 通过 [Jira REST API v3](https://developer.atlassian.com/cloud/jira/platform/rest/v3/) 创建 Jira issue。创建的 issue 包含 ADF 格式的描述、按严重程度映射的优先级以及一个 `opencdr` 标签。 **严重程度 → Jira 优先级映射:** | OpenCDR 严重程度 | Jira 优先级 | |---|---| | CRITICAL | Highest | | HIGH | High | | MEDIUM | Medium | | LOW | Low | | INFORMATIONAL | Lowest | **设置:** 1. 在 [id.atlassian.com/manage-profile/security/api-tokens](https://id.atlassian.com/manage-profile/security/api-tokens) 生成 Jira API token 2. 配置渠道: ``` python3 scripts/opencdr.py settings set \ --jira-url https://yourco.atlassian.net \ --jira-project SEC \ --jira-email soc@yourco.com \ --jira-token # 可选:使用不同的 issue type(默认:Bug) python3 scripts/opencdr.py settings set \ --jira-url https://yourco.atlassian.net \ --jira-project SEC \ --jira-email soc@yourco.com \ --jira-token \ --jira-issue-type Task ``` 所有四个 Jira 标志(`--jira-url`、`--jira-project`、`--jira-email`、`--jira-token`)必须一起提供。 ### 自定义 webhook 自定义 webhook 渠道将原始 OpenCDR 警报 JSON POST 到一个或多个 HTTPS 端点。配置任意数量的命名目标,每个目标都有自己的 URL 和可选标头。这涵盖了接受通用 webhook 的平台——PagerDuty、OpsGenie、Microsoft Teams 等——而无需专门的 第一方 集成。 **单个目标(无身份验证):** ``` python3 scripts/opencdr.py settings set \ --webhook-url https://events.pagerduty.com/v2/enqueue \ --webhook-name pagerduty ``` **带有 authorization header:** ``` python3 scripts/opencdr.py settings set \ --webhook-url https://api.opsgenie.com/v2/alerts \ --webhook-name opsgenie \ --webhook-header "Authorization=GenieKey " ``` **多个标头:** ``` python3 scripts/opencdr.py settings set \ --webhook-url https://example.com/hook \ --webhook-name my-hook \ --webhook-header "Authorization=Bearer " \ --webhook-header "X-Source=opencdr" ``` 要配置多个目标,请使用带有完整设置 JSON 的 `--file`。 每个目标都是独立尝试的——如果一个目标失败,其他目标仍会运行,发送/失败计数反映了各个目标的结果。 ### 通过 SNS 进行自定义集成 对于内置渠道之外的任何需求——自定义 payload 格式、条件路由、多步骤工作流——请将一个 Lambda 订阅到 `opencdr--alerts` SNS topic。OpenCDR 会将每个警报发布到那里;您的 Lambda 会执行您需要的任何操作。 **架构:** ``` OpenCDR notifier └─► SNS topic (opencdr--alerts) └─► Your Lambda ├─► PagerDuty (with custom payload) ├─► ServiceNow ├─► Datadog └─► Anything else ``` **设置:** 1. 部署您的集成 Lambda(任何 runtime) 2. 将其订阅到 SNS topic: ``` aws sns subscribe \ --topic-arn arn:aws:sns:::opencdr--alerts \ --protocol lambda \ --notification-endpoint arn:aws:lambda:::function: ``` 3. 授予 SNS 调用您的 Lambda 的权限: ``` aws lambda add-permission \ --function-name \ --statement-id opencdr-sns-invoke \ --action lambda:InvokeFunction \ --principal sns.amazonaws.com \ --source-arn arn:aws:sns:::opencdr--alerts ``` 您的 Lambda 会在 `event["Records"][0]["Sns"]["Message"]` 中以 JSON 字符串的形式接收完整的 OpenCDR 警报 payload。无需对 OpenCDR 进行任何更改。 ## SIEM 集成 OpenCDR 警报可以使用内置的自定义 webhook 渠道或 SNS 扇出模式发送到 SIEM——通过 HTTP 发送原始 JSON,或者将一个 Lambda 订阅到警报 topic 以进行 payload 转换。针对 Datadog、Splunk、Microsoft Sentinel、Elastic/OpenSearch、Chronicle、IBM QRadar 和 Sumo Logic 的完整演练位于 [`docs/siem-integrations.md`](docs/siem-integrations.md) 中。 ## API 所有端点都需要 `x-api-key` 标头。该密钥由 Serverless 自动创建,并在部署后在 API Gateway 中可用。 | 方法 | 路径 | 描述 | |---|---|---| | `GET` | `/status` | 健康检查 | | `GET` | `/help` | 端点参考 | | `GET` | `/signals` | 按 `severity`、`event_id` 或 `category` 查询信号 | | `GET` | `/logs` | 按 `service`、`event_id` 或 `event_name` 查询日志 | | `GET` | `/rules` | 列出规则(按 `rule_kind=signal\|correlation` 过滤) | | `GET` | `/settings` | 获取全局通知设置 | | `GET` | `/ir-roles` | 列出 AWS 账户 → IR 角色映射(请参阅 [docs/ir-role.md](docs/ir-role.md)) | 所有列表端点都支持 `page_size`、`order`(`asc`/`desc`),以及通过 `next_token` 进行基于游标的分页。 ## 项目结构 ``` src/ domain/ # Cloud-agnostic detection & correlation logic handlers/ # Lambda entry points (processor, alerter, publisher, notifier, responder, api, alarm_notifier) infra/ # AWS adapters (DynamoDB, SQS, logging, metrics, X-Ray) config/ # Env/config loading shared across handlers notifier/ # Shared HTTP transport used by notification delivery docs/ # Deep-reference documentation — see docs/README.md support_files/ detection_rules/ # Production rules (load with scripts/load_rules.sh) test_events/ # Sample EventBridge events for local rule testing settings/ # Example notification settings scripts/ opencdr.py # Management CLI (setup wizard, rules, settings, signals, logs) test_rules_local.py # Test rules locally without AWS load_rules.sh # Seed rules into DynamoDB test_deployed.sh # Integration test against deployed stack cost_report.sh # Query Cost Explorer spend for a stage setup_region_forwarding.sh # Onboard additional AWS regions (see docs/region-forwarding.md) tests/ domain/ # Unit tests for detection, correlation, and parser handlers/ # Unit tests for Lambda handlers (notifier channels, etc.) infra/ # Unit tests for AWS adapter layer scripts/ # Unit tests for the CLI ci-bootstrap/ # Standalone CFN template for the OIDC deploy role (see docs/deployment.md) region-forwarding/ # Standalone CFN template for cross-region event forwarding (see docs/region-forwarding.md) serverless.yml # Infrastructure definition openapi.yml # API spec (see docs/api-reference.md for known drift) ``` 注意:`dredge`(`responder` 通过其运行操作的事件响应操作库)是一个单独的固定依赖项(`requirements.txt`),并未包含在此仓库中——请参阅 [事件响应](docs/incident-response.md)。 ## 运行测试 ``` pip install pytest pytest-cov pytest tests/ -v # With coverage pytest tests/ --cov=src --cov=scripts --cov-report=term-missing ``` ## 许可证 [MPL 2.0](LICENSE)
标签:AMSI绕过, AWS, DPI, FOFA, MITM代理, SIoC, 威胁检测, 安全运营, 扫描框架, 构建工具, 逆向工具