Creating an image policy CR
A cluster administrator or application developer can use an ImagePolicy custom resource (CR) to configure a sigstore signature verification policy for a specific namespace.
The MCO watches ImagePolicy instances in different namespaces and updates the /etc/crio/policies/<namespace>.json and /etc/containers/registries.d/sigstore-registries.yaml files on all the nodes in the cluster.
|
|
If a scoped image or repository in an image policy is nested under one of the scoped images or repositories in a cluster image policy, only the policy from cluster image policy is applied. However, the image policy object is created with an error message. For example, if an image policy specifies |
The following example shows general guidelines on how to configure an ImagePolicy object. For more details on the parameters, see "About cluster and image policy parameters".
-
You have a sigstore-supported public key infrastructure (PKI) key, a Bring Your Own Public Key Infrastructure (BYOPKI) certificate, or provide a Cosign public and private key pair for signing operations.
-
You have a signing process in place to sign your images.
-
You have access to a registry that supports Cosign signatures, if you are using Cosign signatures.
-
Create an image policy object similar to the following examples. See "About cluster and image policy parameters" for specific details on these parameters.
The following example image policy object uses a public key policy and the
MatchRepositorymatch policy:apiVersion: config.openshift.io/v1 kind: ImagePolicy metadata: name: p0 namespace: mynamespace spec: scopes: - example.io/crio/signed policy: rootOfTrust: policyType: PublicKey publicKey: keyData: a2V5RGF0YQ== rekorKeyData: cmVrb3JLZXlEYXRh signedIdentity: matchPolicy: MatchRepositorywhere:
kind-
Specifies that the configuration is for a
ImagePolicyobject. metadata.namespace-
Specifies the namespace where the image policy is applied.
spec.scopes-
Specifies a list of repositories or images assigned to this policy.
spec.policy-
Specifies the parameters that define how the images are verified.
spec.policy.rootOfTrust-
Specifies a root of trust for the policy.
spec.policy.rootOfTrust.policyType-
Specifies the policy types that define the root of trust, either a public key, a BYOPKI certificate, or a Fulcio certificate. Here, a public key with Rekor verification.
spec.policy.rootOfTrust.publicKey.keyData-
For a public key policy, specifies a base64-encoded public key in the PEM format. The maximum length is 8192 characters.
spec.policy.rootOfTrust.publicKey.rekorKeyData-
Optional: Specifies a base64-encoded Rekor public key in the PEM format. The maximum length is 8192 characters.
spec.policy.signedIdentity.matchPolicy-
Optional: Specifies one of the following processes to verify the identity in the signature and the actual image identity:
-
MatchRepoDigestOrExact. -
MatchRepository. -
ExactRepository. TheexactRepositoryparameter must be specified. -
RemapIdentity. TheprefixandsignedPrefixparameters must be specified.
-
The following example image policy object uses a BYOPKI policy and the
MatchRepositorymatch policy:apiVersion: config.openshift.io/v1alpha1 kind: ImagePolicy metadata: name: pki-policy namespace: mynamespace spec: scopes: - example.io policy: rootOfTrust: policyType: PKI pki: caRootsData: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk....RVJUSUZJQ0FURS0tLS0t caIntermediatesData: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURkVENDQ....0QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= pkiCertificateSubject: email: email@example.com hostname: myhost.example.com signedIdentity: matchPolicy: MatchRepositorywhere:
kind-
Specifies that the configuration is for a
ImagePolicyobject. metadata.namespace-
Specifies the namespace where the image policy is applied.
spec.scopes-
Specifies a list of repositories or images assigned to this policy.
spec.policy-
Specifies the parameters that define how the images are verified.
spec.policy.rootOfTrust-
Specifies a root of trust for the policy.
spec.policy.rootOfTrust.policyType-
Specifies the policy types that define the root of trust, either a public key, a BYOPKI certificate, or a Fulcio certificate. Here, a BYOPKI certificate.
spec.policy.rootOfTrust.pki-
For a BYOPKI certificate, specifies
caRootsData. This parameter specifies a base64-encoded CA root certificate in the PEM format. The maximum length is 8192 characters. Optionally withcaIntermediatesData, specifies a base64-encoded intermediate CA root certificate in the PEM format. The maximum length is 8192 characters. spec.policy.rootOfTrust.pki.pkiCertificateSubject-
Specifies a subject alternative name (SAN) to authenticate the user’s identity by using a hostname and an email address:
-
email. Specifies the email address specified when the certificate was generated. -
hostname. Specifies the hostname specified when the certificate was generated.
-
spec.policy.signedIdentity.matchPolicy-
For a BYOPKI certificate, specify
MatchRepositoryto verify the identity in the signature and the actual image identity. The default signed identity ismatchRepoDigestOrExact, which requires digest specification. The signature in this case was not created for digested image.
The following example image policy object uses a Fulcio certificate policy and the
ExactRepositorymatch policy:apiVersion: config.openshift.io/v1 kind: ImagePolicy metadata: name: p1 namespace: mynamespace spec: scopes: - example.io/crio/signed policy: rootOfTrust: policyType: FulcioCAWithRekor fulcioCAWithRekor: fulcioCAData: a2V5RGF0YQ== fulcioSubject: oidcIssuer: "https://expected.OIDC.issuer/" signedEmail: "expected-signing-user@example.com" rekorKeyData: cmVrb3JLZXlEYXRh signedIdentity: matchPolicy: ExactRepository exactRepository: repository: quay.io/crio/signedwhere:
kind-
Specifies that the configuration is for a
ImagePolicyobject. metadata.namespace-
Specifies the namespace where the image policy is applied.
spec.scopes-
Specifies a list of repositories or images assigned to this policy.
spec.policy-
Specifies the parameters that define how the images are verified.
spec.policy.rootOfTrust-
Specifies a root of trust for the policy.
spec.policy.rootOfTrust.policyType-
Specifies the policy types that define the root of trust, either a public key, a BYOPKI certificate, or a Fulcio certificate. Here, a Fulcio certificate with required Rekor verification.
spec.policy.rootOfTrust.fulcioCAWithRekor-
For a Fulcio certificate policy, the following parameters are required:
-
fulcioCAData: Specifies a base64-encoded Fulcio certificate in the PEM format. The maximum length is 8192 characters. -
fulcioSubject: Specifies the OIDC issuer and the email of the Fulcio authentication configuration. -
rekorKeyData: Specifies a base64-encoded Rekor public key in the PEM format. This parameter is required when thepolicyTypeisFulcioCAWithRekor. The maximum length is 8192 characters.
-
spec.policy.signedIdentity.matchPolicy-
Optional: Specifies one of the following processes to verify the identity in the signature and the actual image identity:
-
MatchRepoDigestOrExact. -
MatchRepository. -
ExactRepository. TheexactRepositoryparameter must be specified. -
RemapIdentity. TheprefixandsignedPrefixparameters must be specified.
-
spec.policy.signedIdentity.exactRepository.repository-
For the
exactRepositorymatch policy, specifies the repository that contains the image identity and signature.
-
Create the image policy object:
$ oc create -f <file_name>.yamlThe Machine Config Operator (MCO) updates the machine config pools (MCP) in your cluster.
-
After the nodes in your cluster are updated, you can verify that the image policy has been configured:
-
Start a debug pod for the node by running the following command:
$ oc debug node/<node_name> -
Set
/hostas the root directory within the debug shell by running the following command:sh-5.1# chroot /host/ -
Examine the
<namespace>.jsonfile by running the following command:sh-5.1# cat /etc/crio/policies/<namespace>.jsonExample output for the image policy object with a public key showing the new image policy# ... "transports": { # ... "docker": { "example.io/crio/signed": [ { "type": "sigstoreSigned", "keyData": "a2V5RGF0YQ==", "rekorPublicKeyData": "cmVrb3JLZXlEYXRh", "signedIdentity": { "type": "matchRepository", "dockerRepository": "example.org/crio/signed" } # ...Example output for the image policy object for a BYOPKI certificate showing the new image policy# ... "transports": { # ... "docker": { "docker.io": [ { "type": "sigstoreSigned", "pki": { "caRootsData": "LS0t...LS0t", "caIntermediatesData": "LS0t...LS0t" "subjectEmail": "email@example.com", "subjectHostname": "myhost.example.com" }, "signedIdentity": { "type": "matchRepository" } } ],Example output for the image policy object with a Fulcio certificate showing the new image policy# ... "transports": { # ... "docker": { "example.io/crio/signed": [ { "type": "sigstoreSigned", "fulcio": { "caData": "a2V5RGF0YQ==", "oidcIssuer": "https://expected.OIDC.issuer/", "subjectEmail": "expected-signing-user@example.com" }, "rekorPublicKeyData": "cmVrb3JLZXlEYXRh", "signedIdentity": { "type": "exactRepository", "dockerRepository": "quay.io/crio/signed" } } ], # ... -
Examine the
sigstore-registries.yamlfile by running the following command:sh-5.1# cat /etc/containers/registries.d/sigstore-registries.yamlExample output showing that the scoped registry was addeddocker: example.io/crio/signed: use-sigstore-attachments: true quay.io/openshift-release-dev/ocp-release: use-sigstore-attachments: truewhere:
docker.example.com.use-sigstore-attachments-
When
true, specifies that sigstore signatures are going to be read along with the image.
-
Check the crio log for sigstore signature verification by running the following command:
sh-5.1# journalctl -u crio | grep -A 100 "Pulling image: example.io/crio"Example output with timestamp removed# ... msg="IsRunningImageAllowed for image docker:example.io/crio/signed:latest" file="signature/policy_eval.go:274" msg="Using transport \"docker\" specific policy section \"example.io/crio/signed\"" file="signature/policy_eval.go:150" msg="Reading /var/lib/containers/sigstore/crio/signed@sha256=18b42e8ea347780f35d979a829affa178593a8e31d90644466396e1187a07f3a/signature-1" file="docker/docker_image_src.go:545" msg="Looking for Sigstore attachments in quay.io/crio/signed:sha256-18b42e8ea347780f35d979a829affa178593a8e31d90644466396e1187a07f3a.sig" file="docker/docker_client.go:1138" msg="GET https://quay.io/v2/crio/signed/manifests/sha256-18b42e8ea347780f35d979a829affa178593a8e31d90644466396e1187a07f3a.sig" file="docker/docker_client.go:617" msg="Content-Type from manifest GET is \"application/vnd.oci.image.manifest.v1+json\"" file="docker/docker_client.go:989" msg="Found a Sigstore attachment manifest with 1 layers" file="docker/docker_image_src.go:639" msg="Fetching Sigstore attachment 1/1: sha256:8276724a208087e73ae5d9d6e8f872f67808c08b0acdfdc73019278807197c45" file="docker/docker_image_src.go:644" # ...The
IsRunningImageAllowedline confirms that image is allowed by the configured sigstore verification policy.The
Using transport \"docker\" specific policy section \"example.io/crio/signed\"" file="signature/policy_eval.go:150line confirms that the image policy has been applied.
-