License Compliance Verification
在 ACP (Alauda Container Platform) 中,您可以使用 Tekton Pipeline 中的 trivy
或 syft
任务为镜像生成 SBOM。
SBOM 包含镜像中每个组件的许可证信息。
我们可以使用 Kyverno 策略拒绝包含特定许可证的镜像。
由于在基础镜像和 SBOM 验证中已经为镜像生成了 SBOM,这里不再创建流水线,而是直接使用已有镜像来验证此功能。
目录
功能概述
此方法与基础镜像和 SBOM 验证类似,仅更改 Kyverno 规则以验证许可证合规性。
- 配置 Kyverno 规则以验证 SBOM。
- 使用镜像创建 Pod 以验证许可证合规性。
使用场景
以下场景需要参考本文档的指导:
- 在 Kubernetes 集群中使用 Kyverno 实现许可证合规性验证
- 强制执行安全策略,阻止包含特定许可证(如 GPL)的镜像
- 在 CI/CD 流水线中设置自动许可证验证
- 确保生产环境中的许可证合规性
- 通过验证容器镜像中组件的许可证,实现供应链安全控制
前提条件
流程概览
步骤 | 操作 | 说明 |
---|
1 | 验证许可证信息 | 创建并应用 Kyverno 策略以验证组件许可证 |
2 | (可选)验证 CVE 检查 | 在策略中添加条件检查特定漏洞 |
3 | 清理 | 删除测试资源和策略 |
详细步骤
步骤 1:验证镜像的许可证信息
步骤 1.1:创建 Kyverno 策略以验证基础镜像信息
策略如下:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-component-licenses
spec:
webhookConfiguration:
failurePolicy: Fail
timeoutSeconds: 30
background: false
rules:
- name: check-image
match:
any:
- resources:
kinds:
- Pod
namespaces:
- policy
verifyImages:
- imageReferences:
- "*"
# - "<registry>/test/*"
skipImageReferences:
- "ghcr.io/trusted/*"
failureAction: Enforce
verifyDigest: false
required: false
useCache: false
imageRegistryCredentials:
allowInsecureRegistry: true
secrets:
# 凭证需存在于 kyverno 部署所在的命名空间
- registry-credentials
attestations:
- type: https://cyclonedx.org/bom
attestors:
- entries:
- attestor:
keys:
publicKeys: |- # <- 签名者的公钥
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFZNGfYwn7+b4uSdEYLKjxWi3xtP3
UkR8hQvGrG25r0Ikoq0hI3/tr0m7ecvfM75TKh5jGAlLKSZUJpmCGaTToQ==
-----END PUBLIC KEY-----
ctlog:
ignoreSCT: true
rekor:
ignoreTlog: true
conditions:
- any:
# 检查镜像是否包含特定许可证
- key: "{{ components[].licenses[].license.id }}"
operator: AllNotIn
value: ["GPL-3.0-only", "GPL-3.0-or-later"]
message: |
镜像包含不允许的 GPL 许可证。
发现的许可证:{{ components[].licenses[].license.id }}
# 检查镜像是否包含特定许可证名称
- key: "{{ components[].licenses[].license.name }}"
operator: AllNotIn
value: ["GPL"]
message: |
镜像包含不允许的 Expat 许可证。
发现的许可证:{{ components[].licenses[].license.name }}
YAML 字段说明
- 此策略与镜像签名验证中的策略大致相同
spec.rules[0].verifyImages[].attestations[0].conditions
type
:cyclonedx SBOM 认证类型为 https://cyclonedx.org/bom
attestors
:同上。
conditions
:需要验证的条件。
any
:满足任一条件即可。
key: "{{ components[].licenses[].license.id }}"
:镜像包含不允许的 GPL 许可证。
key: "{{ components[].licenses[].license.name }}"
:镜像包含不允许的 Expat 许可证。
将策略保存为 kyverno.verify-component-licenses.yaml
文件,并使用以下命令应用:
$ kubectl create -f kyverno.verify-component-licenses.yaml
clusterpolicy.kyverno.io/verify-component-licenses created
步骤 1.2:验证策略
在定义策略的 policy
命名空间中,创建 Pod 以验证策略。
使用构建好的镜像创建 Pod。
$ export NAMESPACE=<policy>
$ export IMAGE=<<registry>/test/chains/demo-5:latest@sha256:a6c727554be7f9496e413a789663060cd2e62b3be083954188470a94b66239c7>
$ kubectl run -n $NAMESPACE component-licenses --image=${IMAGE} -- sleep 3600
如果镜像包含 GPL 许可证,Pod 创建将失败。
会收到如下输出:
Error from server: admission webhook "mutate.kyverno.svc-fail" denied the request:
resource Pod/policy/high-risk was blocked due to the following policies
verify-component-licenses:
check-image: |
image attestations verification failed, verifiedCount: 0, requiredCount: 1, error: .attestations[0].attestors[0].entries[0].keys: attestation checks failed for <registry>/test/chains/demo-5:latest and predicate https://cyclonedx.org/bom: The image contains GPL licenses which are not allowed.
Found licenses: ["GPL-3.0-only","GPL-3.0-or-later","Latex2e"]
; The image contains Expat license which is not allowed.
Found licenses: [,"GPL","LGPL","public-domain"]
修改 ClusterPolicy
中的许可证限制以允许 GPL 许可证。
conditions:
- any:
- key: "{{ components[].licenses[].license.id }}"
operator: AllNotIn
value: ["GPL-8.0-only"]
message: |
镜像包含不允许的 GPL 许可证。
发现的许可证:{{ components[].licenses[].license.id }}
- key: "{{ components[].licenses[].license.name }}"
operator: AllNotIn
value: ["GPL-x"]
message: |
镜像包含不允许的 Expat 许可证。
发现的许可证:{{ components[].licenses[].license.name }}
然后创建 Pod 验证策略。
$ kubectl run -n $NAMESPACE component-licenses --image=${IMAGE} -- sleep 3600
pod/component-licenses created
Pod 将成功创建。
步骤 2:(可选)验证镜像是否存在 CVE-2022-42889
TIP
- 如果您有兴趣向策略添加更多条件,可以继续阅读以下内容。
- 这是一个简单示例,您可以用相同方法检查其他漏洞。
CVE-2022-42889 是 Apache Commons Text 库中的一个严重漏洞,可能导致任意代码执行,影响版本为 1.5 到 1.9。通过在 SBOM 中识别受影响版本的 "commons-text" 包,可以检测受影响的包。此策略检查指定在 imageReferences
下的镜像的 CycloneDX 格式的认证 SBOM,如果包含 commons-text 包的 1.5-1.9 版本,则拒绝该镜像。
我们只需在 ClusterPolicy
中添加一个条件,检查镜像中是否存在 commons-text
包。
conditions:
- all:
- key: "{{ components[?name=='commons-text'].version || 'none' }}"
operator: AllNotIn
value: ["1.5","1.6","1.7","1.8","1.9"]
此处不做演示,有兴趣的读者可自行尝试。
步骤 3:清理资源
删除前面步骤中创建的 Pod。
$ export NAMESPACE=<policy>
$ kubectl delete pod -n $NAMESPACE component-licenses
删除策略。
$ kubectl delete clusterpolicy verify-component-licenses
预期结果
完成本指南后:
- 您已成功配置 Kyverno 进行许可证合规性验证
- 您的容器镜像自动在其认证中包含 SBOM 信息
- 只有符合许可证要求的镜像能在指定命名空间中部署
- 不合规许可证的镜像会被 Kyverno 策略自动阻止
- 您已通过验证容器镜像组件的许可证信息,实现了基础的供应链安全控制
本指南为在 CI/CD 流水线中实现许可证合规性验证提供了基础。在生产环境中,您应当:
- 配置合适的命名空间隔离和访问控制
- 实施安全的密钥管理以保护签名密钥
- 设置策略违规的监控和告警
- 根据许可证要求定期更新安全策略
参考文献