许可证合规性验证

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

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

由于已在基础镜像和 SBOM 验证中为镜像生成 SBOM,因此这里不再创建 Pipeline,而是直接使用现有镜像验证此功能。

TIP

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

功能概述

此方法类似于基础镜像和 SBOM 验证,只需更改 Kyverno 规则即可验证许可证合规性。

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

使用场景

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

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

前提条件

流程概述

步骤操作描述
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:
              # The credential needs to exist in the namespace where kyverno is deployed
              - registry-credentials

          attestations:
            - type: https://cyclonedx.org/bom
              attestors:
                - entries:
                    - attestor:
                      keys:
                        publicKeys: |- # <- The public key of the signer
                          -----BEGIN PUBLIC KEY-----
                          MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFZNGfYwn7+b4uSdEYLKjxWi3xtP3
                          UkR8hQvGrG25r0Ikoq0hI3/tr0m7ecvfM75TKh5jGAlLKSZUJpmCGaTToQ==
                          -----END PUBLIC KEY-----

                        ctlog:
                          ignoreSCT: true

                        rekor:
                          ignoreTlog: true

              conditions:
                - any:
                    # Check if the image contains specific licenses
                    - key: "{{ components[].licenses[].license.id }}"
                      operator: AllNotIn
                      value: ["GPL-3.0-only", "GPL-3.0-or-later"]
                      message: |
                        The image contains GPL licenses which are not allowed.
                        Found licenses: {{ components[].licenses[].license.id }}

                    # Check if the image contains specific license names
                    - key: "{{ components[].licenses[].license.name }}"
                      operator: AllNotIn
                      value: ["GPL"]
                      message: |
                        The image contains Expat license which is not allowed.
                        Found licenses: {{ components[].licenses[].license.name }}
Explanation of YAML fields
  • 该策略与镜像签名验证中的策略基本一致
  • 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 的 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: |
        The image contains GPL licenses which are not allowed.
        Found licenses: {{ components[].licenses[].license.id }}

    - key: "{{ components[].licenses[].license.name }}"
      operator: AllNotIn
      value: ["GPL-x"]
      message: |
        The image contains Expat license which is not allowed.
        Found licenses: {{ 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. 根据您的许可证要求定期更新安全策略

参考资料