镜像扫描、SBOM、签名与准入 Hands-on

验证:未记录
适用版本
未记录
验证范围
尚未登记验证记录。
本文缩写(英文全称与中文含义)
缩写 英文全称/名称 中文含义
API Application Programming Interface 应用程序编程接口
AWS Amazon Web Services 亚马逊云服务
CI Continuous Integration 持续集成
CLI Command-Line Interface 命令行接口
CVE Common Vulnerabilities and Exposures 通用漏洞披露标识体系
DB Database 数据库
KMS Key Management Service 密钥管理服务
OCI Open Container Initiative 开放容器倡议及其镜像/运行时规范
PEM Privacy-Enhanced Mail 常用于证书/密钥的文本封装格式
SBOM Software Bill Of Materials 软件物料清单

场景:同一订单镜像经过扫描、签名、准入后晋级;不重新构建生产镜像。前置:Kyverno、私有 OCI registry、已批准的 Trivy/Cosign/crane CLI、短期 CI 凭据。镜像仓库支持签名相关 OCI 工件,控制器可认证访问它。

1. 固定镜像与漏洞库#

将本节作为 Bash 脚本运行,失败立即退出,禁止扫描失败后仍继续签名:

set -euo pipefail
export IMAGE_REPO='registry.example.com/orders/api'
export BUILD_TAG='REPLACE_IMMUTABLE_BUILD_TAG'
DIGEST=$(crane digest "$IMAGE_REPO:$BUILD_TAG")
export DIGEST
[[ "$DIGEST" =~ ^sha256:[0-9a-f]{64}$ ]]
export IMAGE="$IMAGE_REPO@$DIGEST"
trivy --version
cosign version
trivy image --format cyclonedx --output sbom.cdx.json "$IMAGE"
trivy image --severity HIGH,CRITICAL --exit-code 1 --format json --output vulnerabilities.json "$IMAGE"

扫描失败阻断发布;例外必须有 CVE、影响评估、负责人、到期时间。不要用全局 ignore-unfixed 掩盖风险。记录扫描器/DB 更新时间;SBOM 不是“无漏洞”证明,多架构镜像需覆盖生产实际平台。

2. 用企业 KMS 签名并验证#

以 AWS KMS 为例,预先创建专用非对称签名 key,CI 只允许指定 key 的 Sign/GetPublicKey,节点不持有签名权限:

先确定透明日志服务与数据披露策略,再执行签名。 私有环境预先配置企业 Sigstore 服务或所选版本支持的离线方案;下列命令继承已批准的配置,不能在配置未知时直接使用公共默认服务。

export COSIGN_KEY='awskms:///REPLACE_KMS_KEY_ARN'
cosign public-key --key "$COSIGN_KEY" > cosign.pub
cosign sign --key "$COSIGN_KEY" "$IMAGE"
cosign verify --key cosign.pub "$IMAGE" > signature-verification.json
cosign attest --key "$COSIGN_KEY" --type cyclonedx --predicate sbom.cdx.json "$IMAGE"
cosign verify-attestation --key cosign.pub --type cyclonedx "$IMAGE" > sbom-verification.json

CI 中签名步骤必须依赖扫描 job 成功;若跨 job,用受保护的同一 digest/扫描结果传递,不能在签名阶段重新解析可变 tag。公开 key 入平台 repo;签名私钥不能下载到 Git/流水线文件。

3. 配置准入验签#

下例使用 Kyverno ClusterPolicy verifyImages,适用于支持该 API 的已固定版本;新版本其他策略 API 不直接混用。保存 verify-orders.yaml,把 cosign.pub 的完整 PEM 替换到 publicKeys:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata: {name: verify-orders-images}
spec:
  validationFailureAction: Enforce
  background: false
  webhookTimeoutSeconds: 30
  rules:
    - name: trusted-orders-image
      match:
        any:
          - resources:
              kinds: [Pod]
              namespaces: [orders]
      verifyImages:
        - imageReferences: ['registry.example.com/orders/*']
          required: true
          mutateDigest: true
          verifyDigest: true
          attestors:
            - entries:
                - keys:
                    publicKeys: |-
                      REPLACE_WITH_COMPLETE_PEM_PUBLIC_KEY

该规则只验证匹配仓库,不会拒绝其他仓库,因此同时建立仓库白名单。保存 allowed-registry.yaml:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata: {name: orders-allowed-images}
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: approved-repository
      match:
        any:
          - resources:
              kinds: [Pod]
              namespaces: [orders]
      validate:
        message: 'orders 容器必须使用受信任仓库。'
        foreach:
          - list: 'request.object.spec.[containers, initContainers, ephemeralContainers][]'
            pattern:
              image: 'registry.example.com/orders/*'

正式规则允许哪些 mesh/诊断镜像要逐项定义且同样验签;不能给任意 sidecar 开放整个仓库。为 Kyverno admission controller 配置只读 registry 凭据及 KMS/证书信任,参照所选版本 imagePullSecrets 配置;先在独立 namespace 验证,再覆盖业务。

kubectl apply --dry-run=server -f verify-orders.yaml -f allowed-registry.yaml
kubectl apply -f verify-orders.yaml -f allowed-registry.yaml
kubectl -n orders rollout restart deployment/orders-api
kubectl -n orders rollout status deployment/orders-api --timeout=5m

4. 正反向验收与轮换#

在 故障篇的隔离 Deployment 副本测试:已签 digest 成功;同仓库未签 digest 被拒;非白名单仓库被拒;篡改镜像后的 digest 被拒;registry 不可达时观察 timeout/拒绝及告警,已有运行 Pod 不会自动退出。

SBOM 签名证明来源,若需强制漏洞门禁,还应添加受信扫描 attestation 校验及 freshness 约束;不能因为本篇只验镜像签名就宣称准入已验证漏洞结果。

轮换:准入先接受新旧公钥→CI 使用新 key→重新签名仍需运行的旧镜像→验收所有历史回滚镜像→移除旧信任。失败时恢复已签旧 digest;不删除全部验签策略恢复发布。

参考:Cosign KMS、Trivy SBOM、Kyverno 验签。

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭