From 303a90b46a27b56b99623b9dc698357b81102930 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 9 Dec 2025 16:23:10 -0800 Subject: [PATCH 1/2] manifests*/0000_90_cluster-update-keys_configmap: New release-repository-* Preparation for Sigstore, as described in the README text I'm adding. I backed off on some of the signature assertions in the previous README, but checking some recent releases to see who's signing what, OCP releases are signed by release key 2 [1]: $ DIGEST="$(oc image info -o json quay.io/openshift-release-dev/ocp-release:4.20.6-x86_64 | jq -r .digest)" $ echo "${DIGEST}" sha256:a29bcbc9f286d68b394ffa0288c5de7e487c90077c06cbaf7a4cadeb0398ce28 $ curl -s "https://mirror.openshift.com/pub/openshift-v4/signatures/openshift/release/${DIGEST/:/=}/signature-1" | gpg --decrypt | jq . gpg: Signature made Thu 27 Nov 2025 11:27:17 AM PST gpg: using RSA key 199E2F91FD431D51 gpg: Good signature from "Red Hat, Inc. (release key 2) " [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 567E 347A D004 4ADE 55BA 8A5F 199E 2F91 FD43 1D51 { "critical": { "image": { "docker-manifest-digest": "sha256:a29bcbc9f286d68b394ffa0288c5de7e487c90077c06cbaf7a4cadeb0398ce28" }, "type": "atomic container signature", "identity": { "docker-reference": "quay.io/openshift-release-dev/ocp-release:4.20.6-x86_64" } }, "optional": { "creator": "Red Hat OpenShift Signing Authority 0.0.1" } } $ gpg --list-packets " [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: B08B 659E E86A F623 BC90 E8DB 938A 80CA F215 41EB { "critical": { "image": { "docker-manifest-digest": "sha256:e3a750749770f4435360852de7c566e370bef20ad90cdc1446e8ac84e4728e49" }, "type": "atomic container signature", "identity": { "docker-reference": "quay.io/openshift-release-dev/ocp-release:4.21.0-ec.3-x86_64" } }, "optional": { "creator": "Red Hat OpenShift Signing Authority 0.0.1" } } $ gpg --list-packets " [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 6A95 88F0 7F2D 3AE7 973A D2A9 193E 53CC D2E2 F7A4 { "critical": { "type": "atomic container signature", "image": { "docker-manifest-digest": "sha256:80fa69fc5aaa9ac897df610817f60649d4310c2ab362bef6ed85fbff2203c441" }, "identity": { "docker-reference": "registry.ci.openshift.org/ocp/release:4.21.0-0.nightly-2025-12-09-062745" } }, "optional": { "creator": "openshift release-controller", "timestamp": 1765261875 } } $ gpg --list-packets " [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 6A95 88F0 7F2D 3AE7 973A D2A9 193E 53CC D2E2 F7A4 { "critical": { "type": "atomic container signature", "image": { "docker-manifest-digest": "sha256:9c0435c9552cfa98248532d3e8b0ecd7020ca332ba2a0bba21d2c8f0185d8fb5" }, "identity": { "docker-reference": "quay.io/okd/scos-release:4.20.0-okd-scos.12" } }, "optional": { "creator": "openshift release-controller", "timestamp": 1765172601 } } and they trust that key: $ oc adm release extract --to okd quay.io/okd/scos-release:4.20.0-okd-scos.12 $ diff -wU3 okd/0000_90_cluster-update-keys_configmap.yaml manifests/0000_90_cluster-update-keys_configmap.yaml ...no key differences... OKD Engineering Candidates are also signed by the CI key [7]: $ DIGEST="$(oc image info -o json quay.io/okd/scos-release:4.21.0-okd-scos.ec.13 | jq -r .digest)" $ echo "${DIGEST}" sha256:a303ecbfab19d1d98d2258efde3b43cac4c308bedff49e3c10a27314b70dfe37 $ curl -s "https://storage.googleapis.com/openshift-ci-release/releases/signatures/openshift/release/${DIGEST/:/=}/signature-1" | gpg --decrypt | jq . gpg: Signature made Sun 07 Dec 2025 09:15:46 PM PST gpg: using RSA key 6A9588F07F2D3AE7973AD2A9193E53CCD2E2F7A4 gpg: Good signature from "openshift-ci-release-key (This key is used to sign releases from the OpenShift CI system) " [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 6A95 88F0 7F2D 3AE7 973A D2A9 193E 53CC D2E2 F7A4 { "critical": { "type": "atomic container signature", "image": { "docker-manifest-digest": "sha256:a303ecbfab19d1d98d2258efde3b43cac4c308bedff49e3c10a27314b70dfe37" }, "identity": { "docker-reference": "quay.io/okd/scos-release:4.21.0-okd-scos.ec.13" } }, "optional": { "creator": "openshift release-controller", "timestamp": 1765170946 } } [1]: https://amd64.ocp.releases.ci.openshift.org/#4-stable [2]: https://amd64.ocp.releases.ci.openshift.org/#4-dev-preview [3]: https://amd64.ocp.releases.ci.openshift.org/#4.21.0-0.nightly [4]: https://mirror.openshift.com/pub/openshift-v4/OpenShift_Release_Types.pdf [5]: https://amd64.ocp.releases.ci.openshift.org/#4.21.0-0.ci [6]: https://amd64.origin.releases.ci.openshift.org/#4-scos-stable [7]: https://amd64.origin.releases.ci.openshift.org/#4-scos-next --- README.md | 33 +++++++++---------- ...0000_90_cluster-update-keys_configmap.yaml | 1 + ...0000_90_cluster-update-keys_configmap.yaml | 1 + 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 7b8fa75..cde760a 100644 --- a/README.md +++ b/README.md @@ -6,22 +6,21 @@ The config map must have the annotation `release.openshift.io/verification-confi The keys within the config map define how verification is performed: -``` -verifier-public-key-*: One or more GPG public keys in ASCII form that must have signed the - release image by digest. +* `verifier-public-key-*`: One or more GPG public keys in ASCII form that must have signed the release image by digest. +* `store-*`: A URL (scheme file://, http://, or https://) location that contains signatures. + These signatures are in the atomic container signature format. + The URL will have the digest of the image appended to it as `/=/signature-` as described in [the container image signing format][signature-protocols]. + The `docker-image-manifest` section of the signature must match the release image digest. + Signatures are searched starting at `NUMBER` 1 and incrementing if the signature exists but is not valid. + The signature is a GPG signed and encrypted JSON message. + The file store is provided for testing only at the current time, although future versions of the CVO might allow host mounting of signatures. +* `release-repository-*`: In addition to checking for valid OpenPGP signatures, the cluster-version operator will also require the that target release image pullspec matches one of these expected registries. + This supports an eventual transition from OpenPGP signatures to Sigstore signatures, where: + * ClusterImagePolicies such as [the `openshift` policy](manifests.rhel/0000_90_openshift-cluster-image-policy.yaml) cover authentication ("yes, the configured policy for that scope asserts that the image is actually `quay.io/openshift-release-dev/ocp-release@sha256:a29b...`" vs. "no, the configured policy for that scope fails on `quay.io/openshift-release-dev/ocp-release@sha256:0000...`, it might be malicious or corrupted"). + * The release pullspec check covers authorization ("yes, `quay.io/openshift-release-dev/ocp-release` is the expected repository for OCP releases" vs. "no, `quay.io/okd/scos-release` is not the expected repository for OCP release, you probably don't want to update your OCP cluster to an OKD release image"). -store-*: A URL (scheme file://, http://, or https://) location that contains signatures. These - signatures are in the atomic container signature format. The URL will have the digest - of the image appended to it as "/=/signature-" as described - in the container image signing format. The docker-image-manifest section of the - signature must match the release image digest. Signatures are searched starting at - NUMBER 1 and incrementing if the signature exists but is not valid. The signature is a - GPG signed and encrypted JSON message. The file store is provided for testing only at - the current time, although future versions of the CVO might allow host mounting of - signatures. -``` +[OKD builds][OKD] are signed with CI release key and signatures updated to `openshift-ci-release` GCS bucket. +Official OCP builds are signed with Red Hat release key, signatures uploaded to `openshift-release` GCS bucket and mirrored to https://mirror.openshift.com/pub/openshift-v4/signatures/openshift/release/ -See https://github.com/containers/image/blob/ab49b0a48428c623a8f03b41b9083d48966b34a9/docs/signature-protocols.md for a description of the signature store. - -The OpenShift CI system uses the public key described here and signs releases at https://amd64.ocp.releases.ci.openshift.org/ once they are created. Nightly and OKD builds are signed with CI release key and signatures updated to openshift-ci-release GCS bucket/. -Official OCP builds are signed with Red Hat release key, signatures uploaded to openshift-release GCS bucket and mirrored to https://mirror.openshift.com/pub/openshift-v4/signatures/openshift/release +[signature-protocols]: https://github.com/containers/image/blob/ab49b0a48428c623a8f03b41b9083d48966b34a9/docs/signature-protocols.md +[OKD]: https://amd64.origin.releases.ci.openshift.org/ diff --git a/manifests.rhel/0000_90_cluster-update-keys_configmap.yaml b/manifests.rhel/0000_90_cluster-update-keys_configmap.yaml index 36f442a..ad20e64 100644 --- a/manifests.rhel/0000_90_cluster-update-keys_configmap.yaml +++ b/manifests.rhel/0000_90_cluster-update-keys_configmap.yaml @@ -1,6 +1,7 @@ # Release verification against Official Red Hat keys apiVersion: v1 data: + release-repository-default: quay.io/openshift-release-dev/ocp-release store-openshift-official-release: https://storage.googleapis.com/openshift-release/official/signatures/openshift/release store-openshift-official-release-mirror: https://mirror.openshift.com/pub/openshift-v4/signatures/openshift/release verifier-public-key-redhat: | diff --git a/manifests/0000_90_cluster-update-keys_configmap.yaml b/manifests/0000_90_cluster-update-keys_configmap.yaml index fb8ed95..afa9f7f 100644 --- a/manifests/0000_90_cluster-update-keys_configmap.yaml +++ b/manifests/0000_90_cluster-update-keys_configmap.yaml @@ -1,6 +1,7 @@ # Release verification against OpenShift CI keys signed by the CI infrastructure apiVersion: v1 data: + release-repository-default: quay.io/okd/scos-release store-openshift-ci-release: https://storage.googleapis.com/openshift-ci-release/releases/signatures/openshift/release verifier-public-key-ci: | -----BEGIN PGP PUBLIC KEY BLOCK----- From a1cba4a44d2c11f676b987a2568622fcdad7b31e Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 9 Dec 2025 16:24:42 -0800 Subject: [PATCH 2/2] manifests.rhel/0000_90_cluster-update-keys_configmap: Drop duplicate 'namespace' Cleaning up after 9af1fc2526 (Add IBM Cloud managed annotations to CVO manifests, 2020-11-11, #24). We only need to set the namespace key once. --- manifests.rhel/0000_90_cluster-update-keys_configmap.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/manifests.rhel/0000_90_cluster-update-keys_configmap.yaml b/manifests.rhel/0000_90_cluster-update-keys_configmap.yaml index ad20e64..9346b4d 100644 --- a/manifests.rhel/0000_90_cluster-update-keys_configmap.yaml +++ b/manifests.rhel/0000_90_cluster-update-keys_configmap.yaml @@ -69,4 +69,3 @@ metadata: creationTimestamp: null name: release-verification namespace: openshift-config-managed - namespace: openshift-config-managed