mohidev-tech/secure-supply-chain
GitHub: mohidev-tech/secure-supply-chain
一个参考级 DevSecOps 供应链流水线,通过安全扫描、镜像签名、SBOM 证明与 Kubernetes 准入验证,确保仅部署经过密码学验证的可信容器镜像。
Stars: 0 | Forks: 0
# secure-supply-chain 🛰️
一个参考 CI/CD pipeline,用于证明镜像中包含**什么**以及**谁**构建了它——并拒绝部署除此之外的任何内容。
[](https://github.com/mohidev-tech/secure-supply-chain/actions/workflows/release.yml)
[](LICENSE)
## 证明内容
| 能力 | 方式 |
|---|---|
| **SAST** | 对 Go 源码运行 gosec,结果以 SARIF 格式上传至 GitHub Security |
| **SCA** | 对 Go modules 运行 govulncheck;Trivy 文件系统扫描遇到 CRITICAL/HIGH 则失败 |
| **加固镜像** | Distroless nonroot,静态二进制文件,`-trimpath`,多阶段构建 |
| **生成 SBOM** | 以 SPDX + CycloneDX 格式使用 syft 生成,并作为已签名的 attestation 附加到镜像 |
| **镜像已签名** | cosign keyless — 签名固定在*此 commit 的此 workflow* 上,并记录在 Rekor 中 |
| **自我验证** | pipeline 的最后一个 job 会拉取它刚刚推送的内容,并运行与 admission controller 相同的 `cosign verify` |
| **准入验证** | Kyverno `ClusterPolicy` 拒绝未签名的镜像和没有 SBOM attestation 的镜像(也包含 sigstore policy-controller 变体) |
| **对已发布镜像运行 Trivy** | 最后一个 job 会在对应的 digest 处重新扫描镜像 — 捕获任何混过 layer 缓存的内容 |
## Pipeline 结构
```
flowchart LR
PR[PR / push] --> SA[static-analysis
gosec • govulncheck • trivy fs • tests] SA -->|push only| B[build & push
buildx → GHCR] B --> S[syft SBOM
SPDX + CycloneDX] S --> C[cosign sign
keyless OIDC] C --> A[cosign attest
SBOM as predicate] A --> V[verify
pull & re-verify] V --> T[trivy on published image] A --> R[(Rekor log)] ``` ## 快速入门 — 验证我们发布的镜像 ``` ./scripts/verify.sh ghcr.io/mohidev-tech/secure-supply-chain-app:main ``` 这会运行与集群 admission controller 完全相同的 `cosign verify`。如果输出指明了 workflow 路径 + issuer,你就拥有了来源的密码学证明 — 无需密钥信任,签名在构建时绑定到 GitHub 的 OIDC token。 ## 快速入门 — 查看 admission 拒绝未签名镜像 在任何 kind/EKS 集群上: ``` bash scripts/demo.sh ``` 该演示会安装 Kyverno,应用策略,尝试部署 `nginx`(未签名 — 被拒绝),然后部署已签名的应用(被准入)。一个脚本,呈现完整过程。 ## 仓库结构 ``` app/ Tiny Go service. The point of the repo is around it cmd/app/main.go Two endpoints, build-time vars injected via -ldflags Dockerfile Distroless, nonroot, COMMIT/TAG via build-args .github/workflows/ release.yml The centerpiece — SAST → build → SBOM → sign → attest → verify deploy/ helm/app/ Helm chart that pins image by DIGEST, not tag policy/ kyverno-verify-signatures.yaml Kyverno verifyImages policy (default) sigstore-policy-controller.yaml Sigstore policy-controller alternative scripts/ verify.sh What admission does — for humans download-sbom.sh Decode the SBOM attestation demo.sh Full positive + negative path against a real cluster docs/ slsa-mapping.md Which SLSA requirements are met and how adr/0001-keyless-cosign-over-static-keys.md ``` ## 如何融入作品集 [devsecops-platform](https://github.com/mohidev-tech/devsecops-platform) 拥有一条 Kyverno `trusted-registry` 策略,规定“镜像必须来自 `ghcr.io/mohidev-tech/*`。”这个仓库正是使该约束变得*有意义*的原因 — registry 路径仅由此 pipeline 填充,每个镜像都针对已知的 workflow identity 进行签名,并且每个镜像都带有可验证的 SBOM。旗舰项目的 admission policy 可以替换为该仓库的 `verify-signatures` 策略,以实现完整的 SLSA 门控。 ## 许可证 Apache 2.0 — 详见 [LICENSE](LICENSE)。
gosec • govulncheck • trivy fs • tests] SA -->|push only| B[build & push
buildx → GHCR] B --> S[syft SBOM
SPDX + CycloneDX] S --> C[cosign sign
keyless OIDC] C --> A[cosign attest
SBOM as predicate] A --> V[verify
pull & re-verify] V --> T[trivy on published image] A --> R[(Rekor log)] ``` ## 快速入门 — 验证我们发布的镜像 ``` ./scripts/verify.sh ghcr.io/mohidev-tech/secure-supply-chain-app:main ``` 这会运行与集群 admission controller 完全相同的 `cosign verify`。如果输出指明了 workflow 路径 + issuer,你就拥有了来源的密码学证明 — 无需密钥信任,签名在构建时绑定到 GitHub 的 OIDC token。 ## 快速入门 — 查看 admission 拒绝未签名镜像 在任何 kind/EKS 集群上: ``` bash scripts/demo.sh ``` 该演示会安装 Kyverno,应用策略,尝试部署 `nginx`(未签名 — 被拒绝),然后部署已签名的应用(被准入)。一个脚本,呈现完整过程。 ## 仓库结构 ``` app/ Tiny Go service. The point of the repo is around it cmd/app/main.go Two endpoints, build-time vars injected via -ldflags Dockerfile Distroless, nonroot, COMMIT/TAG via build-args .github/workflows/ release.yml The centerpiece — SAST → build → SBOM → sign → attest → verify deploy/ helm/app/ Helm chart that pins image by DIGEST, not tag policy/ kyverno-verify-signatures.yaml Kyverno verifyImages policy (default) sigstore-policy-controller.yaml Sigstore policy-controller alternative scripts/ verify.sh What admission does — for humans download-sbom.sh Decode the SBOM attestation demo.sh Full positive + negative path against a real cluster docs/ slsa-mapping.md Which SLSA requirements are met and how adr/0001-keyless-cosign-over-static-keys.md ``` ## 如何融入作品集 [devsecops-platform](https://github.com/mohidev-tech/devsecops-platform) 拥有一条 Kyverno `trusted-registry` 策略,规定“镜像必须来自 `ghcr.io/mohidev-tech/*`。”这个仓库正是使该约束变得*有意义*的原因 — registry 路径仅由此 pipeline 填充,每个镜像都针对已知的 workflow identity 进行签名,并且每个镜像都带有可验证的 SBOM。旗舰项目的 admission policy 可以替换为该仓库的 `verify-signatures` 策略,以实现完整的 SLSA 门控。 ## 许可证 Apache 2.0 — 详见 [LICENSE](LICENSE)。
标签:DevSecOps, SAST, SBOM, 上游代理, 日志审计, 盲注攻击, 硬件无关, 请求拦截, 软件供应链安全, 远程方法调用, 镜像签名