二进制授权:只允许部署受信镜像

FreeGuideOnline 最新 2026-07-04

bash cosign generate-key-pair


执行后会生成两个文件:
- `cosign.key`:私钥(务必妥善保管,不要上传到公开仓库)
- `cosign.pub`:公钥(用于验证签名)

### 1.2 登录镜像仓库

```bash
# 以 Docker Hub 为例
docker login

1.3 构建并推送一个测试镜像

创建一个简单的 Dockerfile:

FROM alpine:3.18
CMD ["echo", "hello secure world"]

构建并推送:

docker build -t <your-registry>/hello-secure:v1 .
docker push <your-registry>/hello-secure:v1

替换 <your-registry> 为你的实际仓库路径,例如 docker.io/myuser/hello-secure:v1

1.4 用 Cosign 对镜像签名

cosign sign --key cosign.key <your-registry>/hello-secure:v1

执行后,签名会被上传到镜像仓库中(以 OCI artifact 形式存储)。你可以用以下命令验证签名已经存在:

cosign verify --key cosign.pub <your-registry>/hello-secure:v1

如果输出镜像摘要和验证通过的信息,则表示签名成功。


第二步:部署策略引擎(Kyverno)

我们使用 Kyverno 作为 Kubernetes 动态准入控制器,来强制执行“只允许已签名镜像”的策略。

2.1 安装 Kyverno

kubectl create -f https://github.com/kyverno/kyverno/releases/download/v1.10.0/install.yaml

等待所有 Pod 就绪:

kubectl get pods -n kyverno

2.2 创建验证公钥的 Secret

为了让 Kyverno 能校验镜像签名,需要将你的公钥注入集群。

kubectl create secret generic mycosign-pub --from-file=cosign.pub -n kyverno

本例中密钥放在 kyverno 命名空间,策略可以跨命名空间引用它。


第三步:编写镜像验证策略

使用 Kyverno 的 ClusterPolicy 资源定义签名校验规则。

3.1 策略 YAML 示例

创建一个文件 require-image-signature.yaml

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-image-signature
spec:
  validationFailureAction: Enforce   # 拒绝未签名镜像
  background: false
  rules:
    - name: check-image-signature
      match:
        any:
        - resources:
            kinds:
              - Pod
      verifyImages:
      - imageReferences:
        - "*"   # 匹配所有镜像,可根据需求限定仓库
        attestors:
        - count: 1
          entries:
          - keys:
              publicKeys: |-
                -----BEGIN PUBLIC KEY-----
                <你的公钥内容>
                -----END PUBLIC KEY-----                

<你的公钥内容> 替换为 cosign.pub 文件中的完整内容,注意保留 PEM 格式。

如果你希望直接从 Secret 引用公钥(更安全),可以使用:

        attestors:
        - count: 1
          entries:
          - keys:
              secret:
                name: mycosign-pub
                namespace: kyverno

3.2 应用策略

kubectl apply -f require-image-signature.yaml

策略生效后,任何未签名的镜像在创建 Pod 时都会被拒绝。


第四步:测试二进制授权效果

4.1 测试已签名镜像

创建一个使用已签名镜像的 Pod:

# secure-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-test
spec:
  containers:
  - name: hello
    image: <your-registry>/hello-secure:v1

部署:

kubectl apply -f secure-pod.yaml

Pod 应成功创建。

4.2 测试未签名镜像

尝试部署一个公共镜像(通常未签名):

kubectl run insecure-test --image=alpine:3.18 --command -- sleep 3600

你将看到类似以下的拒绝信息:

Error from server: admission webhook "validate.kyverno.svc-fail" denied the request:
failed to verify image alpine:3.18: no matching signatures found