#Image Signature Verification Policy
本指南演示如何配置 Kyverno,以验证容器镜像在 Kubernetes 集群中运行前是否已正确签名。可以将其类比为检查身份证——只有带有有效“签名”的镜像才被允许使用。
#目录
#什么是镜像签名验证?
镜像签名验证就像门口的保安检查身份证。它确保:
- 镜像真实可信:来源确实是其声称的发布者
- 镜像未被篡改:签名后没有人修改过镜像
- 仅允许可信镜像运行:阻止未签名或签名不正确的镜像
- 审计追踪:记录哪些镜像何时被验证过
#快速开始
#1. 生成密钥
# 创建签名密钥对(类似创建身份证系统)
cosign generate-key-pair
# 这会生成:cosign.key(私钥,需保密)和 cosign.pub(公钥,可自由分享)#2. 签名镜像
# 签名镜像(类似盖上官方印章)
cosign sign --key cosign.key registry.company.com/app:v1.0.0#3. 创建基础验证策略
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images
spec:
validationFailureAction: Enforce # 阻止未签名镜像
background: false
rules:
- name: check-signatures
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "registry.company.com/*" # 检查公司镜像仓库的镜像
attestors:
- count: 1
entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
# 在此粘贴 cosign.pub 内容
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM
5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==
-----END PUBLIC KEY-----
mutateDigest: true # 将标签转换为安全的摘要格式#4. 测试
# 应用策略
kubectl apply -f signature-policy.yaml
# 尝试运行未签名镜像(应失败)
kubectl run test --image=nginx:latest
# 尝试运行已签名镜像(应成功)
kubectl run test --image=registry.company.com/app:v1.0.0#常见用例
#场景 1:多个团队需要签署关键镜像
对于关键应用,开发团队和安全团队都可能需要对镜像进行签名:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-dual-signatures
spec:
validationFailureAction: Enforce
background: false
rules:
- name: critical-app-signatures
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "registry.company.com/critical/*"
attestors:
# 两个团队都必须签名
- count: 1 # 安全团队签名
entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
# 安全团队公钥
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM
5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==
-----END PUBLIC KEY-----
- count: 1 # 开发团队签名
entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
# 开发团队公钥
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyctVd7iEcnessRQjU917hmKO6JWV
GHpDguIyakZA8nXRh950IZbRj8Ra/N9sbqOPZrfM5/KAQN0/KjHcorm/J5==
-----END PUBLIC KEY-----
mutateDigest: true#场景 2:不同环境使用不同规则
生产环境需要严格验证,开发环境可以更宽松:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: environment-specific-verification
spec:
validationFailureAction: Enforce
background: false
rules:
# 生产环境严格规则
- name: production-must-be-signed
match:
any:
- resources:
kinds:
- Pod
namespaces:
- production
verifyImages:
- imageReferences:
- "*" # 所有镜像必须签名
failureAction: Enforce # 未签名时阻止
attestors:
- count: 1
entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
# 生产签名密钥
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM
5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==
-----END PUBLIC KEY-----
mutateDigest: true
# 开发环境宽松规则
- name: development-warn-unsigned
match:
any:
- resources:
kinds:
- Pod
namespaces:
- development
- staging
verifyImages:
- imageReferences:
- "registry.company.com/*" # 仅检查公司镜像
failureAction: Audit # 审计但允许未签名镜像
attestors:
- count: 1
entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
# 开发签名密钥
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyctVd7iEcnessRQjU917hmKO6JWV
GHpDguIyakZA8nXRh950IZbRj8Ra/N9sbqOPZrfM5/KAQN0/KjHcorm/J5==
-----END PUBLIC KEY-----
mutateDigest: true#场景 3:使用证书代替密钥
在企业环境中,可能使用 X.509 证书:
# 使用证书签名
cosign sign --cert company-cert.pem --cert-chain ca-chain.pem \
registry.company.com/myapp:v1.0.0apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: certificate-verification
spec:
validationFailureAction: Enforce
background: false
rules:
- name: verify-with-certificates
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "registry.company.com/*"
attestors:
- count: 1
entries:
- certificates:
cert: |-
-----BEGIN CERTIFICATE-----
# 公司的签名证书(请替换为真实证书)
MIIDXTCCAkWgAwIBAgIJAKoK/heBjcOuMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTcwODI4MTExNzQwWhcNMTgwODI4MTExNzQwWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuuExVilGcXIZ3ulNuL7wLrA7VkqJoGpB1YPmYnlS7sobTggOGSqMUvqU
BdLXcAo3ZCOXuKrBHBlltvcNdFHynfxOtkAOCZjirD6uQBrNPiQDlgMYMy14QIDAQAB
o1AwTjAdBgNVHQ4EFgQUhKs8VQFhVLp5J4W1sFVLOVgnQxwwHwYDVR0jBBgwFoAU
hKs8VQFhVLp5J4W1sFVLOVgnQxwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUF
AAOCAQEAuuExVilGcXIZ3ulNuL7wLrA7VkqJoGpB1YPmYnlS7sobTggOGSqMUvqU
-----END CERTIFICATE-----
rekor:
url: https://rekor.sigstore.dev
mutateDigest: true