2.4. 容器镜像签名
红帽为 Red Hat Container Registries 中的镜像提供签名。在使用 Machine Config Operator(MCO)拉取到 OpenShift Container Platform 4 集群时,会自动验证这些签名。
Quay.io 提供了组成 OpenShift Container Platform 的大多数镜像,只有发行镜像会被签名。发行镜像指的是批准的 OpenShift Container Platform 镜像,它可以对供应链攻击提供一定程度的保护。但是,OpenShift Container Platform 的一些扩展(如日志记录、监控和服务网格)会作为 Operator Lifecycle Manager(OLM)的 Operator 提供。这些镜像来自 红帽生态系统目录容器镜像 registry。
要验证这些镜像在红帽 registry 和您的基础架构间的完整性,启用签名验证。
2.4.1. 为 Red Hat Container registry 启用签名验证
为 Red Hat Container Registries 启用容器签名验证需要编写签名验证策略文件,指定从这些 registry 中验证镜像的密钥。对于 RHEL8 节点,默认已在 /etc/containers/registries.d
中定义 registry。
流程
创建 Butane 配置文件
51-worker-rh-registry-trust.bu
,其中包含 worker 节点的必要配置。注意如需有关 Butane 的信息,请参阅"使用 Butane 创建机器配置"。
variant: openshift version: 4.16.0 metadata: name: 51-worker-rh-registry-trust labels: machineconfiguration.openshift.io/role: worker storage: files: - path: /etc/containers/policy.json mode: 0644 overwrite: true contents: inline: | { "default": [ { "type": "insecureAcceptAnything" } ], "transports": { "docker": { "registry.access.redhat.com": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release" } ], "registry.redhat.io": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release" } ] }, "docker-daemon": { "": [ { "type": "insecureAcceptAnything" } ] } } }
使用 Butane 生成机器配置 YAML 文件
51-worker-rh-registry-trust.yaml
,其中包含要写入 worker 节点上的磁盘的文件:$ butane 51-worker-rh-registry-trust.bu -o 51-worker-rh-registry-trust.yaml
应用创建的机器配置:
$ oc apply -f 51-worker-rh-registry-trust.yaml
检查 worker 机器配置池已使用新机器配置推出:
检查是否创建了新机器配置:
$ oc get mc
输出示例
NAME GENERATEDBYCONTROLLER IGNITIONVERSION AGE 00-master a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 25m 00-worker a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 25m 01-master-container-runtime a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 25m 01-master-kubelet a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 25m 01-worker-container-runtime a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 25m 01-worker-kubelet a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 25m 51-master-rh-registry-trust 3.2.0 13s 51-worker-rh-registry-trust 3.2.0 53s 1 99-master-generated-crio-seccomp-use-default 3.2.0 25m 99-master-generated-registries a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 25m 99-master-ssh 3.2.0 28m 99-worker-generated-crio-seccomp-use-default 3.2.0 25m 99-worker-generated-registries a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 25m 99-worker-ssh 3.2.0 28m rendered-master-af1e7ff78da0a9c851bab4be2777773b a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 8s rendered-master-cd51fd0c47e91812bfef2765c52ec7e6 a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 24m rendered-worker-2b52f75684fbc711bd1652dd86fd0b82 a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 24m rendered-worker-be3b3bce4f4aa52a62902304bac9da3c a2178ad522c49ee330b0033bb5cb5ea132060b0a 3.2.0 48s 2
检查 worker 机器配置池是否使用新机器配置更新:
$ oc get mcp
输出示例
NAME CONFIG UPDATED UPDATING DEGRADED MACHINECOUNT READYMACHINECOUNT UPDATEDMACHINECOUNT DEGRADEDMACHINECOUNT AGE master rendered-master-af1e7ff78da0a9c851bab4be2777773b True False False 3 3 3 0 30m worker rendered-worker-be3b3bce4f4aa52a62902304bac9da3c False True False 3 0 0 0 30m 1
- 1
- 当
UPDATING
字段为True
时,机器配置池会使用新机器配置进行更新。当字段变为False
时,代表 worker 机器配置池已应用到新机器配置。
如果您的集群使用任何 RHEL7 worker 节点,当 worker 机器配置池被更新时,在
/etc/containers/registries.d
目录中在这些节点上创建 YAML 文件,用于指定给定 registry 服务器的分离签名的位置。以下示例只适用于托管在registry.access.redhat.com
和registry.redhat.io
中的镜像。为每个 RHEL7 worker 节点启动一个 debug 会话:
$ oc debug node/<node_name>
将您的根目录改为
/host
:sh-4.2# chroot /host
创建一个包含以下内容的
/etc/containers/registries.d/registry.redhat.io.yaml
文件:docker: registry.redhat.io: sigstore: https://registry.redhat.io/containers/sigstore
创建一个包含以下内容的
/etc/containers/registries.d/registry.access.redhat.com.yaml
文件:docker: registry.access.redhat.com: sigstore: https://access.redhat.com/webassets/docker/content/sigstore
- 退出 debug 会话。
2.4.2. 验证签名验证配置
将机器配置应用到集群后,Machine Config Controller 会检测到新的 MachineConfig
对象,并生成新的 rendered-worker-<hash>
版本。
先决条件
- 您可以使用机器配置文件启用签名验证。
流程
在命令行中运行以下命令显示所需 worker 的信息:
$ oc describe machineconfigpool/worker
初始 worker 监控的输出示例
Name: worker Namespace: Labels: machineconfiguration.openshift.io/mco-built-in= Annotations: <none> API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfigPool Metadata: Creation Timestamp: 2019-12-19T02:02:12Z Generation: 3 Resource Version: 16229 Self Link: /apis/machineconfiguration.openshift.io/v1/machineconfigpools/worker UID: 92697796-2203-11ea-b48c-fa163e3940e5 Spec: Configuration: Name: rendered-worker-f6819366eb455a401c42f8d96ab25c02 Source: API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 00-worker API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 01-worker-container-runtime API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 01-worker-kubelet API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 51-worker-rh-registry-trust API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 99-worker-92697796-2203-11ea-b48c-fa163e3940e5-registries API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 99-worker-ssh Machine Config Selector: Match Labels: machineconfiguration.openshift.io/role: worker Node Selector: Match Labels: node-role.kubernetes.io/worker: Paused: false Status: Conditions: Last Transition Time: 2019-12-19T02:03:27Z Message: Reason: Status: False Type: RenderDegraded Last Transition Time: 2019-12-19T02:03:43Z Message: Reason: Status: False Type: NodeDegraded Last Transition Time: 2019-12-19T02:03:43Z Message: Reason: Status: False Type: Degraded Last Transition Time: 2019-12-19T02:28:23Z Message: Reason: Status: False Type: Updated Last Transition Time: 2019-12-19T02:28:23Z Message: All nodes are updating to rendered-worker-f6819366eb455a401c42f8d96ab25c02 Reason: Status: True Type: Updating Configuration: Name: rendered-worker-d9b3f4ffcfd65c30dcf591a0e8cf9b2e Source: API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 00-worker API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 01-worker-container-runtime API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 01-worker-kubelet API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 99-worker-92697796-2203-11ea-b48c-fa163e3940e5-registries API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 99-worker-ssh Degraded Machine Count: 0 Machine Count: 1 Observed Generation: 3 Ready Machine Count: 0 Unavailable Machine Count: 1 Updated Machine Count: 0 Events: <none>
再次运行
oc describe
命令:$ oc describe machineconfigpool/worker
worker 更新后的输出示例
... Last Transition Time: 2019-12-19T04:53:09Z Message: All nodes are updated with rendered-worker-f6819366eb455a401c42f8d96ab25c02 Reason: Status: True Type: Updated Last Transition Time: 2019-12-19T04:53:09Z Message: Reason: Status: False Type: Updating Configuration: Name: rendered-worker-f6819366eb455a401c42f8d96ab25c02 Source: API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 00-worker API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 01-worker-container-runtime API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 01-worker-kubelet API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 51-worker-rh-registry-trust API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 99-worker-92697796-2203-11ea-b48c-fa163e3940e5-registries API Version: machineconfiguration.openshift.io/v1 Kind: MachineConfig Name: 99-worker-ssh Degraded Machine Count: 0 Machine Count: 3 Observed Generation: 4 Ready Machine Count: 3 Unavailable Machine Count: 0 Updated Machine Count: 3 ...
注意Observed Generation
参数显示基于控制器生成的配置的生成数量的增加数。此控制器即使没有处理规格并生成修订,也会更新这个值。Configuration Source
值指向51-worker-rh-registry-trust
配置。使用以下命令确认
policy.json
文件已存在:$ oc debug node/<node> -- chroot /host cat /etc/containers/policy.json
输出示例
Starting pod/<node>-debug ... To use host binaries, run `chroot /host` { "default": [ { "type": "insecureAcceptAnything" } ], "transports": { "docker": { "registry.access.redhat.com": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release" } ], "registry.redhat.io": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release" } ] }, "docker-daemon": { "": [ { "type": "insecureAcceptAnything" } ] } } }
使用以下命令确认
registry.redhat.io.yaml
文件已存在:$ oc debug node/<node> -- chroot /host cat /etc/containers/registries.d/registry.redhat.io.yaml
输出示例
Starting pod/<node>-debug ... To use host binaries, run `chroot /host` docker: registry.redhat.io: sigstore: https://registry.redhat.io/containers/sigstore
使用以下命令确认
registry.access.redhat.com.yaml
文件已存在:$ oc debug node/<node> -- chroot /host cat /etc/containers/registries.d/registry.access.redhat.com.yaml
输出示例
Starting pod/<node>-debug ... To use host binaries, run `chroot /host` docker: registry.access.redhat.com: sigstore: https://access.redhat.com/webassets/docker/content/sigstore
2.4.3. 了解缺少可验证的容器镜像的验证
每个 OpenShift Container Platform 发行镜像都是不可变的,并使用红帽产品密钥签名。在 OpenShift Container Platform 更新或安装过程中,发行镜像可能会部署没有可验证签名的容器镜像。每个签名的发行镜像摘要都是不可变的。发行镜像中的每个引用都是另一个镜像的不可变摘要,因此内容可以被信任。换句话说,发行镜像中的签名会验证所有发行内容。
例如,没有可验证的签名的镜像引用包含在签名的 OpenShift Container Platform 发行镜像中:
发行信息输出示例
$ oc adm release info quay.io/openshift-release-dev/ ocp-release@sha256:2309578b68c5666dad62aed696f1f9d778ae1a089ee461060ba7b9514b7ca417 -o pullspec 1 quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9aafb914d5d7d0dec4edd800d02f811d7383a7d49e500af548eab5d00c1bffdb 2
2.4.3.1. 更新过程中自动验证
签名验证是自动的。OpenShift Cluster Version Operator (CVO) 在 OpenShift Container Platform 更新过程中会在发行镜像上验证签名。这是一个内部过程。如果自动验证失败,OpenShift Container Platform 安装会失败。
也可以使用 skopeo
命令行工具手动验证签名。
其他资源
2.4.3.2. 使用 skopeo 验证红帽容器镜像的签名
您可以通过从 OCP 发行镜像站点拉取这些签名来验证 OpenShift Container Platform 发行镜像中包含的容器镜像的签名。因为镜像站点上的签名不是 Podman 或 CRI-O 理解的格式,所以您可以使用 skopeo standalone-verify
命令来验证您的发行镜像是否由红帽签名。
先决条件
-
已安装
skopeo
命令行工具。
流程
运行以下命令,获取您的发行版本的完整 SHA:
$ oc adm release info <release_version> \ 1
- 1
- 将 <release_version> 替换为您的版本号,如
4.14.3
。
输出片断示例
--- Pull From: quay.io/openshift-release-dev/ocp-release@sha256:e73ab4b33a9c3ff00c9f800a38d69853ca0c4dfa5a88e3df331f66df8f18ec55 ---
运行以下命令关闭红帽发行密钥:
$ curl -o pub.key https://access.redhat.com/security/data/fd431d51.txt
运行以下命令,获取您要验证的特定发行版本的签名文件:
$ curl -o signature-1 https://mirror.openshift.com/pub/openshift-v4/signatures/openshift-release-dev/ocp-release/sha256%<sha_from_version>/signature-1 \ 1
- 1
- 将
<sha_from_version>
替换为与发行版本 SHA 匹配的镜像站点的完整链接中的 SHA 值。例如,到 4.12.23 发行版本的签名链接为https://mirror.openshift.com/pub/openshift-v4/signatures/openshift-release-dev/ocp-release/sha256%e73ab4b33a9c3ff00c9f800a38d69853ca0c4dfa5a88e3df331f66df8f18ec55/signature-1
,SHA 值为e73ab4b33a9c3ff00c9f800a38d69853ca0c4dfa5a88e3df331f66df8f18ec55
。
运行以下命令,获取发行镜像的清单:
$ skopeo inspect --raw docker://<quay_link_to_release> > manifest.json \ 1
- 1
- 将
<quay_link_to_release>
替换为oc adm release info
命令的输出。例如:quay.io/openshift-release-dev/ocp-release@sha256:e73ab4b33a9c3ff00c9f800a38d69853ca0c4dfa5a88e3df331f66df8f18ec55
。
使用 skopeo 验证签名:
$ skopeo standalone-verify manifest.json quay.io/openshift-release-dev/ocp-release:<release_number>-<arch> any signature-1 --public-key-file pub.key
其中:
<release_number>
-
指定发行号,如
4.14.3
。 <arch>
指定架构,如
x86_64
。输出示例
Signature verified using fingerprint 567E347AD0044ADE55BA8A5F199E2F91FD431D51, digest sha256:e73ab4b33a9c3ff00c9f800a38d69853ca0c4dfa5a88e3df331f66df8f18ec55