eumel8/cosignwebhook

GitHub: eumel8/cosignwebhook

用于验证 Cosign 镜像签名的 Kubernetes 验证准入控制器,保障运行时镜像来源可信。

Stars: 12 | Forks: 3

[![项目状态:活跃](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) [![Go Report Card](https://goreportcard.com/badge/github.com/eumel8/cosignwebhook)](https://goreportcard.com/report/github.com/eumel8/cosignwebhook) [![发布版本](https://img.shields.io/github/v/release/eumel8/cosignwebhook?display_name=tag)](https://github.com/eumel8/cosignwebhook/releases) [![Codacy 徽章](https://app.codacy.com/project/badge/Grade/78288de2f8eb403fa8249293b2155dca)](https://app.codacy.com/gh/eumel8/cosignwebhook/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![流水线](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/04e9963299231620.svg)](https://github.com/eumel8/cosignwebhook/actions/workflows/gotest.yaml) [![流水线](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/c57cd9d367231621.svg)](https://github.com/eumel8/cosignwebhook/actions/workflows/end2end.yaml) [![流水线](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/6fa94dced0231622.svg)]([https://github.com/eumel8/cosignwebhook/actions/workflows/build.yaml) [![流水线](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/b6a341dbde231623.svg)]([https://github.com/eumel8/cosignwebhook/actions/workflows/trivy.yaml) # Cosign Webhook 用于验证 Cosign 镜像签名的 Kubernetes 验证准入控制器。 cosignwebhook 此准入控制器会监听 Pod 创建事件,并验证找到的所有容器镜像是否具有现有的 RSA 公钥(如果存在)。 # Helm 安装 ``` helm -n cosignwebhook upgrade -i cosignwebhook oci://ghcr.io/eumel8/charts/cosignwebhook --versi on 5.0.0 --create-namespace ``` 此安装方式具有以下优势: * 自动生成 TLS 密钥对 * 自动设置 ServiceMonitor 和 Grafana 仪表盘 如果你使用自己的镜像,你需要先对其进行签名。不要忘记修改 `cosign.scwebhook.key` 值为你的 公钥,用于签名镜像。 # 清单文件安装 作为集群管理员,创建一个命名空间并安装准入控制器: ``` kubectl create namespace cosignwebhook kubectl -n cosignwebhook apply -f manifests/rbac.yaml kubectl -n cosignwebhook apply -f manifests/manifest.yaml ``` 该清单包含一个自签名的示例 CA、TLS 证书和密钥。这仅用于演示效果,你应该生成自己的证书,参见下文: ## 证书生成 运行 `hack` 文件夹中的生成证书脚本,以生成 TLS 密钥对和准入控制器的 CA 证书: ``` generate-certs.sh --service cosignwebhook --webhook cosignwebhook --namespace cosignwebhook --secret cosignwebhook ``` ## 验证容器镜像 要使用此准入控制器,你需要先用 `cosign` 签名你的镜像,然后使用以下 **一种** 验证方式: - [公钥作为环境变量](#public-key-as-environment-variable) - [公钥作为密钥引用](#public-key-as-secret-reference) - [公钥作为命名空间的默认密钥](#public-key-as-default-secret-for-namespace) 此外,如果你尝试验证的镜像签名 **不在** 与镜像相同的仓库中,你需要向容器的环境变量添加 `COSIGN_REPOSITORY`: ``` # 工作负载容器规范中的 env: - name: COSIGN_REPOSITORY value: myregistry.io/signatures ``` 此选项类似于 `cosign verify` 和 `cosign sign` 命令行工具中使用的 `COSIGN_REPOSITORY` 环境变量,用于指定镜像签名所在的仓库(如果不在与镜像相同的仓库中)。 ### 公钥作为环境变量 在第一个容器的容器规范中添加你的 Cosign 公钥作为环境变量: ``` env: - name: COSIGNPUBKEY value: | -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGOrnlJ1lFxAFTY2LF1vCuVHNZr9H QryRDinn+JhPrDYR2wqCP+BUkeWja+RWrRdmskA0AffxBzaQrN/SwZI6fA== -----END PUBLIC KEY----- ``` ### 公钥作为密钥引用 不要在部署中硬编码公钥,你可以使用密钥引用。只要密钥包含有效的公钥,密钥和密钥名称可以自由命名: ``` apiVersion: v1 kind: Secret data: COSIGNPUBKEY: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFS1BhWUhnZEVEQ3ltcGx5emlIdkJ5UjNxRkhZdgppaWxlMCtFMEtzVzFqWkhJa1p4UWN3aGsySjNqSm5VdTdmcjcrd05DeENkVEdYQmhBSTJveE1LbWx3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0t metadata: name: cosign_secret # Can be choosen freely type: Opaque ``` ``` env: - name: COSIGNPUBKEY valueFrom: secretKeyRef: name: cosign_secret # Must be equal to metadata.name of the secrect key: COSIGNPUBKEY ``` ### 公钥作为命名空间的默认密钥 为命名空间中的所有镜像创建一个默认密钥,准入控制器在验证此命名空间中的镜像时会始终查找该密钥: ``` apiVersion: v1 kind: Secret data: COSIGNPUBKEY: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFS1BhWUhnZEVEQ3ltcGx5emlIdkJ5UjNxRkhZdgppaWxlMCtFMEtzVzFqWkhJa1p4UWN3aGsySjNqSm5VdTdmcjcrd05DeENkVEdYQmhBSTJveE1LbWx3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0t metadata: name: cosignwebhook type: Opaque ``` 密钥名称必须为 `cosignwebhook`,密钥键为 `COSIGNPUBKEY`。`COSIGNPUBKEY` 的值必须与用于签名镜像的公钥匹配。 ## ## 测试 要测试准入控制器,可以运行以下命令: ``` # 单元测试 make test-unit # E2E 测试 make e2e-prep make test-e2e ``` ### E2E 测试 E2E 测试需要一个正在运行的 Kubernetes 集群。目前,命名空间和准入控制器是通过辅助的 Makefile 目标进行部署的。要仅运行测试,需要以下条件: * Docker * cosign (v3) 要运行完整的 E2E 测试,需要按顺序执行以下步骤: * 创建用于测试的 k3d 本地集群和本地镜像仓库 (`make e2e-cluster`) * 生成签名密钥 (`make e2e-keys`) * 构建并签名一个新的 `cosignwebhook` 镜像(使用临时密钥)(`make e2e-images`) * 将镜像推送到本地注册表并部署到测试集群 (`make e2e-deploy`) 要执行以上所有操作,只需运行 `make e2e-prep`。每个步骤也可以单独执行。要清理 E2E 环境,运行 `make e2e-cleanup`。 这将删除 E2E 准备过程中创建的所有内容。如果已经创建了集群和密钥,并且你正在积极测试新代码,可以运行 `make e2e-images e2e-deploy test-e2e` 来测试你的更改。 如果你在 Apple 设备上运行测试,可能需要停用 k3s DNS 修复(已在 Makefile 中实现)。如果集群中的容器因跳过修复而无法启动,可以将 `K3S_FIX_DNS` 设置回 `1`(在 `e2e-cluster` 目标中)。 ## 本地构建 ``` CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o cosignwebhook ``` ## 致谢 * Bruno Bressi * Frank Kloeker 分享即关怀。如果你对代码有问题或希望改进,欢迎打开 Issue 或 Pull 请求。 该控制器的灵感来源于 [@pipo02mix](https://github.com/pipo02mix/grumpy),这是学习准入控制器基础知识的好地方
标签:APT组织, CI/CD 安全, Cosign, EVTX分析, Go, Grafana, Helm, PyVis, RSA, Ruby工具, SLSA, TLS, Webhook, Web截图, 代码签名, 公钥, 准入控制器, 力导向图, 子域名突变, 容器安全, 数据投毒防御, 日志审计, 服务监控, 特权提升, 签名验证, 自动化部署, 镜像签名, 防御工具, 验证准入控制器