License Compliance Verification

在 ACP (Alauda Container Platform) 中,您可以使用 Tekton Pipeline 中的 trivysyft 任务为镜像生成 SBOM。

SBOM 包含镜像中每个组件的许可证信息。
我们可以使用 Kyverno 策略拒绝包含特定许可证的镜像。

由于在基础镜像和 SBOM 验证中已经为镜像生成了 SBOM,这里不再创建流水线,而是直接使用已有镜像来验证此功能。

TIP

本章节基于基础镜像和 SBOM 验证,仅增加了验证镜像许可证信息的逻辑。

目录

功能概述

此方法与基础镜像和 SBOM 验证类似,仅更改 Kyverno 规则以验证许可证合规性。

  1. 配置 Kyverno 规则以验证 SBOM。
  2. 使用镜像创建 Pod 以验证许可证合规性。

使用场景

以下场景需要参考本文档的指导:

  • 在 Kubernetes 集群中使用 Kyverno 实现许可证合规性验证
  • 强制执行安全策略,阻止包含特定许可证(如 GPL)的镜像
  • 在 CI/CD 流水线中设置自动许可证验证
  • 确保生产环境中的许可证合规性
  • 通过验证容器镜像中组件的许可证,实现供应链安全控制

前提条件

流程概览

步骤操作说明
1验证许可证信息创建并应用 Kyverno 策略以验证组件许可证
2(可选)验证 CVE 检查在策略中添加条件检查特定漏洞
3清理删除测试资源和策略

详细步骤

步骤 1:验证镜像的许可证信息

步骤 1.1:创建 Kyverno 策略以验证基础镜像信息

TIP

此步骤需要集群管理员权限。

有关 Kyverno ClusterPolicy 的更多详情,请参阅 Kyverno ClusterPolicy

策略如下:

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 流水线中实现许可证合规性验证提供了基础。在生产环境中,您应当:

  1. 配置合适的命名空间隔离和访问控制
  2. 实施安全的密钥管理以保护签名密钥
  3. 设置策略违规的监控和告警
  4. 根据许可证要求定期更新安全策略

参考文献