JubethSB/dodo-payments-devsecops-assessment
GitHub: JubethSB/dodo-payments-devsecops-assessment
一个支付微服务的 DevSecOps 全流程加固评估项目,涵盖工作负载加固、供应链签名、Istio 零信任网络及渗透测试验证,全部在本地 k3d 集群上运行通过。
Stars: 0 | Forks: 0
# Dodo Payments:安全与 DevOps 工程师技术评估
[](https://github.com/JubethSB/dodo-payments-devsecops-assessment/actions/workflows/ci-cd.yml)





`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, 上游代理, 子域名突变, 逆向工具, 零信任网络