JubethSB/dodo-payments-devsecops-assessment

GitHub: JubethSB/dodo-payments-devsecops-assessment

一个支付微服务的 DevSecOps 全流程加固评估项目,涵盖工作负载加固、供应链签名、Istio 零信任网络及渗透测试验证,全部在本地 k3d 集群上运行通过。

Stars: 0 | Forks: 0

# Dodo Payments:安全与 DevOps 工程师技术评估 [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/23/233b9a1843e3cfe66a132113afea392917910bfbd5b6da5cc3c6dd1b7ccb3064.svg)](https://github.com/JubethSB/dodo-payments-devsecops-assessment/actions/workflows/ci-cd.yml) ![Kubernetes](https://img.shields.io/badge/Kubernetes-k3d-326CE5?logo=kubernetes&logoColor=white) ![Istio](https://img.shields.io/badge/Istio-mTLS%20STRICT-466BB0?logo=istio&logoColor=white) ![供应链](https://img.shields.io/badge/Supply%20chain-cosign%20keyless%20%2B%20SBOM-F97316?logo=sigstore&logoColor=white) ![策略](https://img.shields.io/badge/Admission-PSS%20restricted%20%2B%20Kyverno-6E56CF) ![范围](https://img.shields.io/badge/Scope-PCI%20DSS%20CDE-2EA043) `starter repo` 中的 `ledger-api`,将其从初始交付状态转变为 能够通过 PCI 审计的状态。Workload 加固、具备实质性拦截能力的交付 pipeline,接着是零信任网络和渗透测试。 在本地 k3d 上运行。无需云账号。 | 任务 | 状态 | 详情 | |---|---|---| | [1: Workload 加固](./task-1-workload-hardening/README.md) | 完成 | 17/17 项检查;起始 Deployment 在 admission 阶段被拒绝| | [2: CI/CD 与供应链](./task-2-cicd-supply-chain/README.md) | 完成 | 7/7 个 job;镜像进行 keyless 签名,验证了 drift self-heal | | [3: 服务网格与零信任](./task-3-service-mesh-zero-trust/README.md) | 完成 | Istio mTLS STRICT;SPIFFE authz (200 vs 403);NetworkPolicy;gateway + canary | | [4: 侦察与渗透测试](./task-4-recon-pentest/README.md) | 完成 | 对 dodopayments.tech 进行被动 OSINT;在本地目标上发现 4 个可利用漏洞,附带 CVSS 评分 | 每个任务文件夹都有自己的 README,涵盖了实现方法、设计决策、 复现和验证步骤,并在各自的 `evidence/` 目录下提供了相关证据。 ## 技术栈及原因 选用 **k3d/k3s** 而不是 kind。kind 无法在这台机器的 3.7 GB Docker 虚拟机上创建集群;即使单节点,该 node 也从未达到 systemd 的 multi-user target。 k3s 启动大约只需要两分钟。评估要求允许两者选其一。 同时使用 PSS `restricted` 和 Kyverno。它们的失败表现不同:PSS 位于 API server 中,即便有人删除了 webhook 它依然生效,而 Kyverno 可以表达 PSS 无法实现的规则(如 registry、`:latest` 标签、签名等)。 选用 **Sealed Secrets** 而非 SOPS+age 或 External Secrets。SOPS 需要将私钥 分发给运维人员和 CI 流程;而 Sealed Secrets 使用一对永远不会离开集群的密钥进行加密。External Secrets 在规模化场景下表现更好,但它需要一个后端。 选用 **GitHub Actions + GHCR**,主要是因为 OIDC token 是 cosign 实现 keyless 签名的基础前提。 选用 **ArgoCD**,这样 CI 就不需要持有任何集群凭证。Pipeline 只负责提交 digest 并 到此为止。 ## 运行方式 ``` # Task 1 - hardened workload cd task-1-workload-hardening ./scripts/deploy.sh ./scripts/verify.sh # 17 passed, 0 failed # Task 2 - pipeline gates + GitOps ./task-2-cicd-supply-chain/scripts/verify-gates.sh # scanners + negative tests ./task-2-cicd-supply-chain/scripts/finish-gitops.sh # ArgoCD + drift demo # Task 3 - Istio mesh (需要先运行 Task 1) cd ../task-3-service-mesh-zero-trust ./scripts/restore-baseline.sh # reporting + 2 replicas ./scripts/install-istio.sh # istioctl + CNI path guard + inject kubectl apply -f istio/ -f networkpolicy/ ./scripts/verify-mesh.sh # mTLS + authz assertions # Task 4 - 对捆绑的 vulnerable app 进行 local pentest (authorised target) cd ../task-4-recon-pentest ./scripts/recon-passive.sh # Part A: passive OSINT ./scripts/pentest-all.sh # Part B: build target, exploit, evidence ``` 需要 Docker、k3d、kubectl、kubeseal 和 istioctl。脚本会自动寻找各自的工具 路径。任务 4 的侦察需要访问外部网络以查询 CT logs / DNS。 ## 预期会被问到的决策 **应用程序本身的漏洞依然存在。** `app.py` 在 `/import` 上存在 `yaml.load` RCE, 在 `/fetch` 上存在 SSRF,以及在 `/transactions` 上存在明文 PAN。那是任务 4 的 目标。任务 1 负责对它们进行隔离:RCE 最终只能以 uid 10001 身份运行在只读 文件系统上,没有 capabilities,也没有 ServiceAccount token。 **任何 RBAC 角色(包括 admin)都不能读取 Secrets 或 exec 进入 pod。** 如果 开发者可以直接从集群中读取解密后的值,那么在 git 中加密 secrets 就毫无意义。管理员管理 SealedSecrets;exec 权限属于一个 未绑定给任何人的破窗(break-glass)角色。 **CVE 拦截机制对可修复漏洞进行阻断,对未修复漏洞仅作警告。** 此镜像包含 182 个 CRITICAL/HIGH 级别漏洞, 其中 149 个可修复,33 个不可修复。如果直接拦截这 33 个,会导致 pipeline 永远处于红色状态且没有任何操作能让它变绿,最终人们会将其关闭,导致那 149 个漏洞也被发布。`.trivyignore` 中的 21 个抑制项均按 CVE id、负责人和复核日期列出,而不是按路径列出,因此同一 文件中出现的新漏洞依然会中断构建。 ## 环境信息 7.3 GB 内存笔记本,Docker 虚拟机分配约 3.7 GB。因此脚本中内置了以下应对措施: - BuildKit 无法穿透 OneDrive reparse points 读取内容,因此构建上下文 (build contexts) 会先被 复制到临时目录。 - k3d 将 `host.docker.internal` 写入 kubeconfig,在 Windows 上这会解析为 局域网 IP 并导致超时。已将其重写为 loopback,并在每次 集群重启时重新执行(因为 API 端口会发生变化)。 - 两个并发的 Trivy 扫描耗尽了 API server 资源。`verify-gates.sh` 扫描一次 即可得出两种计数值。 - 在 PowerShell 中执行 `bash script.sh` 会调用 WSL 的 bash,而不是 Git Bash。这会导致不同的 `$HOME`, 不同的挂载点。脚本已实现对两者的兼容。 ## 关于 AI 的使用 评估要求允许使用 AI,因此:我在整个过程中使用了 Claude Code 来起草 manifest 和 workflow,更重要的是用它来运行验证循环。 有必要说明清楚,因为真正有用的部分并不是代码生成。通过实际运行而非仅仅阅读代码,暴露出了几个 真实的缺陷: - 一条 `.gitignore` 规则 (`**/secrets/*.yaml`) 本会将 SealedSecret 排除在 git 之外,从而悄无声息地破坏部署和 ArgoCD 同步。 - 一个 `.gitleaks.toml` 代码块在重新声明内置规则时未指定 `regex`, 这会用空规则覆盖原规则,从而在报告依然显示通过 (green) 的同时关闭了检测功能。 - 一个 secrets-gate 测试夹具 (fixture) 将其探测 token 作为字面量嵌入,因此它 未能通过其旨在验证的拦截机制。 - 一个 drift 演示在无条件地扩展副本数并打印成功消息,尽管其对应的 Application 被配置为忽略副本差异。它断言某个控制措施 正在生效,而上方的运行记录却显示什么都没发生。 共同点在于:一个报告通过 (green) 的检查毫无意义,除非你 亲眼看到它失败 (red) 过。这就是为什么 `verify-gates.sh` 会植入一个已知的错误输入,并且 drift 演示会根据观测到的状态来计算其结果。 这里的所有内容都经过了实际运行和验证,而不仅仅是写出来而已。每个 任务 README 中的推理过程均出自本人。 ## 提交说明 - [x] Repository 已公开 - [x] 顶层 README 链接了每个任务 - [x] 包含方法、复现和验证步骤的各任务 README - [x] 架构图(按任务划分,位于各自的 README 中) - [x] 各任务在对应的 `evidence/` 目录下捕获的证据 - [x] 任务 4 报告为独立的 Markdown 文件 ([task-4-recon-pentest/pentest-report.md](./task-4-recon-pentest/pentest-report.md)) - [x] Pipeline 截图 ([task-2-cicd-supply-chain/screenshots/](./task-2-cicd-supply-chain/screenshots/)) + 实时的 GitHub Actions 运行记录
标签:DevSecOps, StruQ, 上游代理, 子域名突变, 逆向工具, 零信任网络