ChrisInvictus/CloudCanary

GitHub: ChrisInvictus/CloudCanary

CloudCanary 是一款无 agent 的 GCP 资产与身份漂移检测工具,通过定期快照对比将所有云资源配置变更在 30 分钟内推送至 Slack,帮助安全团队在没有 SIEM 的阶段以接近零成本建立检测能力。

Stars: 0 | Forks: 0

# CloudCanary 🐤 ![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/73/73ccbf4580efb36d6c888b7f4803d5e82c229071ca2fd1a481dac1a7a20547dc.svg) ![License](https://img.shields.io/github/license/ChrisInvictus/CloudCanary) **针对 GCP 的身份漂移检测 —— 谁创建了密钥,谁获取了角色,发生了什么变更。30 分钟内呈现在你的 Slack 中。** **概览:** 身份漂移、service-account 密钥创建、权限变更、公开暴露以及 AI/ML 服务启用 —— 以 30 分钟为周期进行无 agent 检测,并向 Slack 发送警报,成本几乎为零 · 架构上坚持最小权限原则(canary 本身通过 WIF 实现无密钥运行) · 防御部分:[paved-org](https://github.com/ChrisInvictus/paved-org)。 用于 Google Cloud 的轻量级、无 agent 变更检测 canary。CloudCanary 定期扫描你的 GCP 组织,将实时的资源清单与 上次已知状态进行对比,并将所有差异发布到 Slack —— 这样你的安全团队就能在 新 VM、防火墙规则、存储桶、service account、**service-account 密钥** 和 **IAM 权限变更**发生几分钟后看到它们。 这是我作为第一位安全雇员在生产环境中运行的工具:在 组织拥有 SIEM 预算之前,它就是检测层。作为 零成本、零 agent 的绊线,它在与更重型的工具并行(或超前)使用时依然非常有用。 CloudCanary 是一对工具中的检测部分:paved-org 是防御部分。 这个组织基线使得大多数此类恶劣事件从一开始就无法发生。 ## 监控内容 | 信号 | 重要性 | |---|---| | 项目创建/删除(全组织) | 影子基础设施,未经授权的环境 | | Compute 实例 | 挖矿劫持,恶意工作负载 | | 防火墙规则 | 暴露变更,数据外泄路径 | | 预留地址 | 新的入口/出口攻击面 | | GCS 存储桶 | 数据暴露面 | | Service account | 进入资产范围的新身份 | | **用户管理的 SA 密钥** | 长效凭证创建 —— 顶级的 GCP 凭证泄露途径 | | **针对每个 SA 的 IAM 角色绑定** | 每个身份的权限提升 / 漂移 | | **针对所有 principal 的 IAM 绑定** | 某个人或组悄无声息地获得了 Editor/Owner 权限 | | **已启用的 API** | 作为早期持久化 / 侦察信号的服务启用 | | **对互联网开放的防火墙规则** | `0.0.0.0/0` 入站 —— 资产安全态势警报,而不仅仅是漂移 | | **公开的存储桶** | 授予 `allUsers` / `allAuthenticatedUsers` 权限 —— 数据暴露 | | **AI/ML API 启用** | 启用了 Vertex / Gemini —— 每一种其他 AI 风险前的 AI 采用先兆 | | **`aiplatform.*` 角色授权** | Agent 身份权限(Excessive Agency, LLM06)—— AI 工作负载能做什么 | | **公开的模型 endpoint** | Vertex endpoint 上的 `allUsers` 权限 —— 模型服务暴露在组织之外 | 最后两点是关键所在:大多数“云 canary”监控的是计算资源。CloudCanary 将**身份视为主要的攻击面**。 AI 工作负载也是通过同样的身份视角进行监控的:AI API 是一个 启用事件,`aiplatform.*` 授权是一个权限事件,而公开的 endpoint 是一个暴露事件。请参阅 [paved-org](https://github.com/ChrisInvictus/paved-org/blob/main/docs/threat-models/mcp-trust-boundaries.md) 中的相关威胁模型。 ## 工作原理 ``` Jenkins (every 30 min) └── cloudcanary.sh ├── gcloud enumerates projects → resources → identities ├── diff vs. state dir (last-known inventory) └── deltas → Slack webhook (security channel) ``` 除了纯文本状态目录外,设计上无状态 —— 没有数据库, 没有 agent,除了只读 API 调用外,云端没有任何痕迹。 ## 设置 1. **Canary 的身份。** 创建一个专用的 service account 并赋予 只读角色 —— `roles/browser`、`roles/compute.viewer`、 `roles/iam.securityReviewer`、`roles/storage.objectViewer`(存储桶 列表)和 `roles/aiplatform.viewer`(Vertex endpoint / IAM 读取)。在 runner 上首选使用 Workload Identity / 附加的 SA,而不是 导出的密钥文件。(如果一个用于检测的工具本身需要长效密钥, 那它就是在暴露自身。) 2. **Slack webhook。** 为你的安全频道创建一个传入的 webhook 并将其存储为 secret —— 在提供的 pipeline 中作为 Jenkins Secret Text 凭证 `cloudcanary-slack-webhook`。它永远不会被 提交到代码库中。 3. **配置。** 复制 `config.example.env`,进行调整,或者在你的调度器中设置相同的 变量: | 变量 | 默认值 | 用途 | |---|---|---| | `SLACK_WEBHOOK_URL` | *(必填)* | 差异通知 | | `STATE_DIR` | `~/.cloudcanary/state` | 上次已知的清单 | | `PROJECT_INCLUDE_FILTER` | *(所有可见项)* | `gcloud --filter` 作用域 | | `PROJECT_EXCLUDE_REGEX` | *(无)* | 跳过嘈杂/沙箱项目 | | `WATCH_SA_KEYS` | `true` | 密钥创建检测 | | `WATCH_SA_ROLES` | `true` | 权限漂移检测 | | `DRY_RUN` | `false` | 仅记录差异但不发送 | 4. **调度它。** `Jenkinsfile` 每 30 分钟运行一次 (`cron('H/30 * * * *')`),并禁用并发(状态文件不支持 并发安全)。原生的 cron 或 Cloud Scheduler + Cloud Run 任务的工作方式 完全相同。 首次运行会播种状态并保持静默;从第二次运行开始才会发送漂移警报。 ## 本仓库的安全实践 - **代码中无 secret。** Webhook 在运行时从凭证 存储中注入;如果没有它,脚本将拒绝启动。 - **防注入通知。** Slack payload 使用 `jq` 构建,而不是 字符串插值。 - **最小权限。** 只读查看者角色;canary 无法 对资产进行任何修改。 - **高调报错。** Pipeline 失败时会发布自己的警报 —— 死掉的 canary 就是 检测盲区,并且它会明确告诉你这一点。 - **`set -euo pipefail`**,加引号的变量展开,以及单次调用隔离错误, 这样一个抖动的 API 就不会悄无声息地跳过某个项目。 ## 为什么不用 Security Command Center / CNAPP? 如果你能负担得起,就去用它们。SCC Premium 和 Wiz 级别的平台是预算充足时的正确 选择。CloudCanary 的存在是为了填补它们未覆盖的阶段和缺口: - **预算建立前:** 它最初是一个没有 SIEM 或 CNAPP 支出的组织的检测层。免费,无 agent,30 分钟内即可运行。 - **独立的故障模式:** 一个不与你的主要工具共享凭证、 pipeline 或供应商的绊线,当那些 工具配置错误、欠费或被入侵时,它依然会触发。 - **演进路径:** 当 CNAPP 上线后,canary 并不会退役 —— 它会变成监控那些监控者的工具。 - **防御部分:paved-org** 最强烈的警报是永远不会触发的警报。paved-org 是本仓库的姊妹项目 - 一个以代码形式实现的 GCP 组织基线,其 第一个组织策略 iam.disableServiceAccountKeyCreation 就阻止了 CloudCanary 最想检测的确切事件。 两者都用:用防御应对已知风险,用检测应对配置漂移。 护栏拦截你能预测到的; canary 抓住你未能预测到的。 ## 局限性(坦诚说明) - 轮询,而非事件驱动:检测延迟 = 调度间隔。如果需要 实时性,请配合使用 Cloud Asset Inventory feeds / Audit Log sinks;将 CloudCanary 保留为不共享它们故障 模式的独立绊线。 - 基于名称级别的对比:重命名会显示为删除+创建。 - 状态保存在 runner 上:请将任务固定在单个 agent 上,或将状态迁移到 存储桶中。 ## 按你的方式进行部署 - **Jenkins** —— 包含 `Jenkinsfile`(30 分钟 cron,绑定凭证的 webhook) - **GitHub Actions** —— `.github/workflows/canary.yml`,通过 Workload Identity Federation (OIDC) 进行无密钥认证,状态通过缓存持久化 - **Terraform** —— `terraform/` 将 canary 自身的身份配置为 安全默认的蓝图:专用的只读 service account,仅限组织级 查看者角色,可选的 WIF 绑定,因此**永远不会导出密钥**。 检测工具永远不应依赖于它旨在检测的凭证类型。 CI 会在每次推送时运行 shellcheck(`.github/workflows/lint.yml`)。 ## License MIT
标签:GCP, HTTP/HTTPS抓包, 告警通知, 态势感知, 漂移检测