Home / News / How to verify container signatures in disconnected OpenShift

How to verify container signatures in disconnected OpenShift

The introduction of sigstore and its suite of tools, such as CoSign, has simplified the signing and verification of container images. Red Hat OpenShift Container Platform 4.19 leverages the oc-mirror v2 tool to enable the mirroring of container images and their cryptographic signatures to local/remote registries. This development is significant as it facilitates container signature verification with CoSign in disconnected, or “air-gapped” environments.

This article presents a proof of concept outlining the steps required to mirror content for a disconnected OpenShift installation. It further details how to enable and test signature verification using CoSign within this setup.

This article covers: 

  • A proof of concept for a feature that is in technology preview at the time of this writing.
  • A procedure tested in a home lab environment using a single node OpenShift instance.
  • The oc-mirror client used for this procedure was version 4.19.5, which was the latest version available at the time of writing.
  • This procedure was tested with the Red Hat Operators catalog, as it is currently the only one that provides signatures for all of its operator images.
  • The exact code used to create this demo and produce the results. 

While we hope these steps will work for others, platform differences may produce different results. This is not a production-ready guide, nor is it exhaustive or comprehensive.

Mirroring signatures with oc-mirror 

This section details the configuration of the ImageSetConfiguration file. This file specifies which container images and operator catalogs to mirror from a connected registry to your disconnected environment.

# cat v2_imageset-config_with_RHOperators_4.19.yml
kind: ImageSetConfiguration
apiVersion: mirror.openshift.io/v2alpha1
archiveSize: 16
mirror:
  platform:
    channels:
    - name: stable-4.19
      minVersion: 4.19.5
      maxVersion: 4.19.5
  operators:
  - catalog: registry.redhat.io/redhat/redhat-operator-index:v4.19
    full: false
    packages:
      - name: advanced-cluster-management
      - name: ansible-automation-platform-operator
      - name: datagrid
      - name: lvms-operator
      - name: mcg-operator
      - name: ocs-client-operator
      - name: ocs-operator
      - name: odf-csi-addons-operator
      - name: odf-multicluster-orchestrator
      - name: odf-operator
      - name: odr-cluster-operator
      - name: openshift-gitops-operator
      - name: quay-operator
      - name: rhbk-operator
      - name: rhsso-operator
      - name: servicemeshoperator
      - name: servicemeshoperator3
      - name: skupper-operator
      - name: submariner
  additionalImages:
   - name: registry.redhat.io/ubi8/ubi:latest
   - name: registry.redhat.io/ubi9/ubi:latest

Run like this:

oc-mirror --v2 --image-timeout 20m0s --retry-times 5 --retry-delay 5s --remove-signatures=false -c  v2_imageset-config_all_RHOperators_4.19.yml --workspace file:///data/oc-mirror/workdir/  --log-level info docker://quay.local.momolab.io:443/mirror

Apply configuration changes to OpenShift 

First, add the Signature Verification FeatureGate. To do this, edit the FeatureGate object to ensure its spec contains the following configuration:

Note that TechPreviewNoUpgrade will prevent updates of the cluster and cannot be reversed.

$ export EDITOR=vi
$ oc edit featuregate cluster
spec: 
  featureSet: TechPreviewNoUpgrade

This enables the required SigstoreImageVerification feature. This change will trigger an update to the machine configuration. You can monitor the progress with the following command.

Wait for OpenShift to apply the new policies.

This may take up to 10 minutes, and the API might become unavailable (as it is single node OpenShift).

$  oc get mcp
NAME     CONFIG                                             UPDATED   UPDATING   DEGRADED   MACHINECOUNT   READYMACHINECOUNT   UPDATEDMACHINECOUNT   DEGRADEDMACHINECOUNT   AGE
master   rendered-master-1c612127e5ae4fd194b9ecac38fe4f9d   True      False      False      1              1                   1                     0                      13d
worker   rendered-worker-c88af97175298b6ed0d4f17ce32c9852   True      False      False      0              0                   0                     0                      13d

Wait for the UPDATING column to transition from False -> True -> False.

A good way to check if the process has completed is to confirm that the ClusterImagePolicies CRD is available.

$ oc get crds |grep -i clusterimagepolicies
clusterimagepolicies.config.openshift.io                          2025-08-03T23:26:20Z

Once the oc-mirror process is complete, you should see this:

# ls -la /data/oc-mirror/workdir/working-dir/cluster-resources/
total 28
drwxr-xr-x.  2 root root 4096 Aug  2 10:04 .
drwxr-xr-x. 10 root root  158 Aug  2 06:53 ..
-rw-r--r--.  1 root root  431 Aug  2 10:04 cc-redhat-operator-index-v4-19.yaml
-rw-r--r--.  1 root root  433 Aug  2 10:04 cs-redhat-operator-index-v4-19.yaml
-rw-r--r--.  1 root root 3113 Aug  2 10:04 idms-oc-mirror.yaml
-rw-r--r--.  1 root root  929 Aug  2 10:04 itms-oc-mirror.yaml
-rw-r--r--.  1 root root 1626 Aug  2 10:04 signature-configmap.json
-rw-r--r--.  1 root root 1614 Aug  2 10:04 signature-configmap.yaml

In the cc-redhat-operator-index-v4-19.yaml and cs-redhat-operator-index-v4-19.yaml files, replace the metadata name with redhat-operators, as some operators use this CatalogSource name and will fail otherwise.

Generate ClusterImagePolicy for each repository (generates remapIdentity).

The following script has been provided to generate a ClusterImagePolicy for each repository mirrored to the local mirror.

# cat generate_cluster_image_policies.py

# looks up files generated by oc-mirror v2, and creates a ClusterImagePolicy for each mirror/source pair.
# Run using python generate_cluster_image_policies.py
import os
import yaml

# Directory where oc-mirror YAML files are stored
input_dir = "files/disconnected/4.18/" # Change to match what you need.
output_file = "ClusterImagePolicies.yaml"

# Red Hat public key: security.access.redhat.com/data/63405576.txt (between BEGIN and END, passed through | base64 -w0) 
sigstore_key = """LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUEwQVN5dUgyVExXdkJVcVBIWjRJcAo3NWc3RW5jQmtnUUhkSm5qenhBVzVLUVRNaC9zaUJvQi9Cb1NydGlQTXduQ2hiVENuUU9JUWVadURpRm5odUo3Ck0vRDNiN0pvWDBtMTIzTmNDU242N21BZGpCYTZCZzZrdWtaZ0NQNFpVWmVFU2FqV1gvRWp5bEZjUkZPWFc1N3AKUkRDRU40MkovallsVnF0K2c5K0dya2VyOFN6ODZIM2wwdGJxT2RqYnovVnhIWWh3RjBjdFVNSHN5VlJEcTJRUAp0cXpOWGxtbE1oUy9Qb0ZyNlI0dS83SENuL0srTGVnY08yZkFGT2I0MEt2S1NLS1ZENmxld1VaRXJob3AxQ2dKClhqRHRHbW1POWRHTUY3MW1mNkhFZmFLU2R5K0VFNmlTRjJBMlZ2OVFoQmF3TWlxMmtPekVpTGc0bkFkSlQ4d2cKWnJNQW1QQ3FHSXNYTkdaNC9RK1lUd3dsY2UzZ2xxYjVMOXRmTm96RWRTUjlOODVERVNmUUxRRWRZM0NhbHdLTQpCVDFPRWhFWDF3SFJDVTRkck1PZWo2Qk5XMFZ0c2NHdEhtQ3JzNzRqUGV6aHdOVDh5cGt5UytUMHpUNFRzeTZmClZYa0o4WVNIeWVuU3pNQjJPcDJidnNFM2dyWStzNzRXaEc5VUlBNkRCeGNUaWUxNU5Tekt3Znphb05XT0RjTEYKcDdCWThhYUhFMk1xRnhZRlgrSWJqcGtRUmZhZVFRc291REZkQ2tYRUZWZlBwYkQyZGs2RmxlYU1UUHV5eHRJVApnalZFdEdRSzJxR0NGR2lRSEZkNGhmVitlQ0E2M0pybzF6MHpvQk01QmJJSVEzK2VWRnd0M0FsWnA1VVZ3cjZkCnNlY3FraS95cm12M1kwZHFaOVZPbjNVQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ=="""

# Collect mirror-source pairs
pairs = []

for fname in os.listdir(input_dir):
    if fname.endswith("oc-mirror.yaml"):
        with open(os.path.join(input_dir, fname)) as f:
            docs = list(yaml.safe_load_all(f))
            for doc in docs:
                if not doc or "spec" not in doc:
                    continue
                key = "imageDigestMirrors" if "imageDigestMirrors" in doc["spec"] else "imageTagMirrors"
                for entry in doc["spec"].get(key, []):
                    source = entry["source"]
                    for mirror in entry["mirrors"]:
                        pairs.append((mirror, source))

# Deduplicate
unique_pairs = sorted(set(pairs))

# Generate policy YAMLs
policies = []
for mirror, source in unique_pairs:
    name = mirror.split("/")[-1].replace(".", "-").replace(":", "-")
    policy = {
        "apiVersion": "config.openshift.io/v1alpha1",
        "kind": "ClusterImagePolicy",
        "metadata": {"name": f"enforce-signatures-quay-mirror-{name}"},
        "spec": {
            "scopes": [mirror],
            "policy": {
                "type": "sigstore",
                "rootOfTrust": {
                    "policyType": "PublicKey",
                    "publicKey": {
                        "keyData": sigstore_key
                    }
                },
                "signedIdentity": {
                    "type": "RemapIdentity",
                    "matchPolicy": "RemapIdentity",
                    "remapIdentity": {
                        "prefix": mirror,
                        "signedPrefix": source
                    }
                }    
            }
        }
    }
    policies.append(policy)

# Output to file
with open(output_file, "w") as f:
     f.write("# This was generated by https://github.com/momoah/snolibvirt/blob/main/files/generate_cluster_image_policies.py\n")
    f.write("---\n" + "\n---\n".join(yaml.dump(p, sort_keys=False) for p in policies))

print(f"Generated {len(policies)} ClusterImagePolicy objects in {output_file}")

Refer to the source on GitHub.

This is what the generated ClusterImagePolicy YAML for OpenShift release images looks like:

---
apiVersion: config.openshift.io/v1alpha1
kind: ClusterImagePolicy
metadata:
 name: enforce-signatures-quay-mirror-release-images
spec:
 scopes:
 - quay.local.momolab.io:443/mirror/openshift/release-images
 policy:
   type: sigstore
   rootOfTrust:
     policyType: PublicKey
     publicKey:
       keyData: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUEwQVN5dUgyVExXdkJVcVBIWjRJcAo3NWc3RW5jQmtnUUhkSm5qenhBVzVLUVRNaC9zaUJvQi9Cb1NydGlQTXduQ2hiVENuUU9JUWVadURpRm5odUo3Ck0vRDNiN0pvWDBtMTIzTmNDU242N21BZGpCYTZCZzZrdWtaZ0NQNFpVWmVFU2FqV1gvRWp5bEZjUkZPWFc1N3AKUkRDRU40MkovallsVnF0K2c5K0dya2VyOFN6ODZIM2wwdGJxT2RqYnovVnhIWWh3RjBjdFVNSHN5VlJEcTJRUAp0cXpOWGxtbE1oUy9Qb0ZyNlI0dS83SENuL0srTGVnY08yZkFGT2I0MEt2S1NLS1ZENmxld1VaRXJob3AxQ2dKClhqRHRHbW1POWRHTUY3MW1mNkhFZmFLU2R5K0VFNmlTRjJBMlZ2OVFoQmF3TWlxMmtPekVpTGc0bkFkSlQ4d2cKWnJNQW1QQ3FHSXNYTkdaNC9RK1lUd3dsY2UzZ2xxYjVMOXRmTm96RWRTUjlOODVERVNmUUxRRWRZM0NhbHdLTQpCVDFPRWhFWDF3SFJDVTRkck1PZWo2Qk5XMFZ0c2NHdEhtQ3JzNzRqUGV6aHdOVDh5cGt5UytUMHpUNFRzeTZmClZYa0o4WVNIeWVuU3pNQjJPcDJidnNFM2dyWStzNzRXaEc5VUlBNkRCeGNUaWUxNU5Tekt3Znphb05XT0RjTEYKcDdCWThhYUhFMk1xRnhZRlgrSWJqcGtRUmZhZVFRc291REZkQ2tYRUZWZlBwYkQyZGs2RmxlYU1UUHV5eHRJVApnalZFdEdRSzJxR0NGR2lRSEZkNGhmVitlQ0E2M0pybzF6MHpvQk01QmJJSVEzK2VWRnd0M0FsWnA1VVZ3cjZkCnNlY3FraS95cm12M1kwZHFaOVZPbjNVQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ==
   signedIdentity:
     type: RemapIdentity
     matchPolicy: RemapIdentity
     remapIdentity:
       prefix: quay.local.momolab.io:443/mirror/openshift/release-images
       signedPrefix: quay.io/openshift-release-dev/ocp-release

Apply the output files in the following sequence:

# Step 1: Mirror image references
oc apply -f idms-oc-mirror.yaml
oc apply -f itms-oc-mirror.yaml

# Step 2: Trust signatures
oc apply -f signature-configmap.yaml
oc apply -f ClusterImagePolicies.yaml

# Step 3: Catalogd content (new way)
oc apply -f cc-*.yaml

# Step 4: Legacy CatalogSource (optional)
oc apply -f cs-*.yaml

Apply Generated ClusterImagePolicy YAML:

$ oc create -f ClusterImagePolicies.yaml
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-ansible-automation-platform created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-ansible-automation-platform-25 created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-datagrid created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-lvms4 created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-odf4 created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-openshift-gitops-1 created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-openshift-service-mesh created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-openshift-service-mesh-dev-preview-beta created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-openshift-service-mesh-tech-preview created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-release created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-release-images created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-openshift4 created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-quay created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-rh-sso-7 created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-rhacm2 created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-rhbk created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-rhceph created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-rhel8 created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-rhel9 created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-rhem created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-service-interconnect created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-ubi8 created
clusterimagepolicy.config.openshift.io/enforce-signatures-quay-mirror-ubi9 created

Check the current policies as follows:

$ oc get clusterimagepolicy
NAME                                                                     AGE
enforce-signatures-quay-mirror-ansible-automation-platform               104s
enforce-signatures-quay-mirror-ansible-automation-platform-25            104s
enforce-signatures-quay-mirror-datagrid                                  104s
enforce-signatures-quay-mirror-lvms4                                     104s
enforce-signatures-quay-mirror-odf4                                      104s
enforce-signatures-quay-mirror-openshift-gitops-1                        104s
enforce-signatures-quay-mirror-openshift-service-mesh                    104s
enforce-signatures-quay-mirror-openshift-service-mesh-dev-preview-beta   103s
enforce-signatures-quay-mirror-openshift-service-mesh-tech-preview       103s
enforce-signatures-quay-mirror-openshift4                                103s
enforce-signatures-quay-mirror-quay                                      103s
enforce-signatures-quay-mirror-release                                   103s
enforce-signatures-quay-mirror-release-images                            103s
enforce-signatures-quay-mirror-rh-sso-7                                  103s
enforce-signatures-quay-mirror-rhacm2                                    103s
enforce-signatures-quay-mirror-rhbk                                      103s
enforce-signatures-quay-mirror-rhceph                                    103s
enforce-signatures-quay-mirror-rhel8                                     103s
enforce-signatures-quay-mirror-rhel9                                     103s
enforce-signatures-quay-mirror-rhem                                      103s
enforce-signatures-quay-mirror-service-interconnect                      103s
enforce-signatures-quay-mirror-ubi8                                      103s
enforce-signatures-quay-mirror-ubi9                                      103s
openshift                                                                5m7s

Testing signature verification

For this demonstration, we use two versions of the ubi9 image. The first is the signed image, mirrored with its signature: quay.local.momolab.io:443/mirror/ubi9/ubi:latest. The second is an unsigned version that was pushed manually to the registry: quay.local.momolab.io:443/mirror/ubi9/ubi:no-sig.

Create a new project as follows:

$ oc new-project verification

Test with no signature, assuming you are already authenticated to your cluster:

$ oc run test-ubi9-no-sig \
  --image=quay.local.momolab.io:443/mirror/ubi9/ubi:no-sig \
  --restart=Never \
  --overrides='{
    "apiVersion": "v1",
    "spec": {
      "containers": [{
        "name": "test-ubi9-no-sig",
        "image": "quay.local.momolab.io:443/mirror/ubi9/ubi:no-sig",
        "command": ["sleep", "infinity"],
        "securityContext": {
          "runAsNonRoot": true,
          "allowPrivilegeEscalation": false,
          "capabilities": {
            "drop": ["ALL"]
          },
          "seccompProfile": {
            "type": "RuntimeDefault"
          }
        }
      }]
    }
  }'

Check the status of your pod:

$ oc get pods
NAME               READY   STATUS                      RESTARTS   AGE
test-ubi9-no-sig   0/1     SignatureValidationFailed   0          11s

Test with signature:

$ oc run test-ubi9-with-sig \
  --image=quay.local.momolab.io:443/mirror/ubi9/ubi:latest \
  --restart=Never \
  --overrides='{
    "apiVersion": "v1",
    "spec": {
      "containers": [{
        "name": "test-ubi9-with-sig",
        "image": "quay.local.momolab.io:443/mirror/ubi9/ubi:latest",
        "command": ["sleep", "infinity"],
        "securityContext": {
          "runAsNonRoot": true,
          "allowPrivilegeEscalation": false,
          "capabilities": {
            "drop": ["ALL"]
          },
          "seccompProfile": {
            "type": "RuntimeDefault"
          }
        }
      }]
    }
  }'

Check the status of your pod:

$ oc get pods
NAME                 READY   STATUS                      RESTARTS   AGE
test-ubi9-no-sig     0/1     SignatureValidationFailed   0          40s
test-ubi9-with-sig   1/1     Running                     0          4s

You can confirm that verification is working by using Podman with the following steps.

Log in to the node via debug mode:

$ oc debug node/sno1.local.momolab.io
Temporary namespace openshift-debug-82g7n is created for debugging node...
Starting pod/sno1localmomolabio-debug-klhq9 ...
To use host binaries, run `chroot /host`
Pod IP: 192.168.1.231
If you don't see a command prompt, try pressing enter.
sh-5.1# chroot /host

Test pulling a container with no signature. Log in to the registry first:

sh-5.1# podman login quay.local.momolab.io:443
Username: quayadmin
Password: 
Login Succeeded!

Test pulling an unsigned container image:

sh-5.1# podman --log-level debug pull quay.local.momolab.io:443/mirror/ubi9/ubi:no-sig 2>&1 | grep signatures  
time="2025-08-04T00:46:27Z" level=debug msg="Error pulling candidate quay.local.momolab.io:443/mirror/ubi9/ubi:no-sig: Source image rejected: None of the signatures were accepted, reasons: cryptographic signature verification failed: crypto/rsa: verification error; cryptographic signature verification failed: crypto/rsa: verification error; Signature for identity \"registry.redhat.io/ubi9/ubi:9.6\" is not accepted; Signature for identity \"registry.redhat.io/ubi9/ubi:9.6-1749542372\" is not accepted; Signature for identity \"registry.redhat.io/ubi9/ubi:latest\" is not accepted; Signature for identity \"registry.access.redhat.com/ubi9/ubi:9.6\" is not accepted; Signature for identity \"registry.access.redhat.com/ubi9/ubi:9.6-1749542372\" is not accepted; Signature for identity \"registry.access.redhat.com/ubi9/ubi:latest\" is not accepted; Signature for identity \"registry.redhat.io/ubi9/ubi:9.6\" is not accepted; Signature for identity \"registry.redhat.io/ubi9/ubi:9.6-1749542372\" is not accepted; Signature for identity \"registry.redhat.io/ubi9/ubi:latest\" is not accepted; Signature for identity \"registry.access.redhat.com/ubi9/ubi:9.6\" is not accepted; Signature for identity \"registry.access.redhat.com/ubi9/ubi:9.6-1749542372\" is not accepted; Signature for identity \"registry.access.redhat.com/ubi9/ubi:latest\" is not accepted"
Error: Source image rejected: None of the signatures were accepted, reasons: cryptographic signature verification failed: crypto/rsa: verification error; cryptographic signature verification failed: crypto/rsa: verification error; Signature for identity "registry.redhat.io/ubi9/ubi:9.6" is not accepted; Signature for identity "registry.redhat.io/ubi9/ubi:9.6-1749542372" is not accepted; Signature for identity "registry.redhat.io/ubi9/ubi:latest" is not accepted; Signature for identity "registry.access.redhat.com/ubi9/ubi:9.6" is not accepted; Signature for identity "registry.access.redhat.com/ubi9/ubi:9.6-1749542372" is not accepted; Signature for identity "registry.access.redhat.com/ubi9/ubi:latest" is not accepted; Signature for identity "registry.redhat.io/ubi9/ubi:9.6" is not accepted; Signature for identity "registry.redhat.io/ubi9/ubi:9.6-1749542372" is not accepted; Signature for identity "registry.redhat.io/ubi9/ubi:latest" is not accepted; Signature for identity "registry.access.redhat.com/ubi9/ubi:9.6" is not accepted; Signature for identity "registry.access.redhat.com/ubi9/ubi:9.6-1749542372" is not accepted; Signature for identity "registry.access.redhat.com/ubi9/ubi:latest" is not accepted

Note the key phrase in the output: ‘Signatures for identity...is not accepted‘. Also note the key phrase in the output: ‘Storing signatures‘.

Test pulling a container with a signature:

sh-5.1# podman --log-level debug pull quay.local.momolab.io:443/mirror/ubi9/ubi:latest 2>&1 | grep signatures
Getting image source signatures
Checking if image destination supports signatures
Storing signatures
time="2025-08-04T00:46:56Z" level=debug msg="saved image metadata \"{\\\"signature-sizes\\\":[699,699,4156,4164,4160,4160,4180,4168],\\\"signatures-sizes\\\":{\\\"sha256:b2572b4ec08febca6587d5833d6e64054236cee20f03c481e6cf7ef90088e4e0\\\":[699,699,4156,4164,4160,4160,4180,4168]}}\""

Notice the keywords above Storing signatures.

Signature verification with oc-mirror

As noted in the documentation, it is possible to configure oc-mirror to verify signatures while mirroring content. While selective verification is possible, this article demonstrates how to enable signature verification for all images using the --secure-policy=true flag.

To enforce signature verification during the mirroring process, add the --secure-policy=true flag to the oc-mirror command.

oc-mirror --v2 --image-timeout 20m0s --retry-times 5 --retry-delay 5s --remove-signatures=false --secure-policy=true -c  v2_imageset-config_all_RHOperators_4.19.yml --workspace file:///data/oc-mirror/workdir/  --log-level info docker://quay.local.momolab.io:443/mirror

This method works as long as signatures are available for all images. If signatures are missing for some images, further customization will be required.

Wrap up

As demonstrated, the latest features in oc-mirror and OpenShift Container Platform 4.19 make it possible to enforce container signature verification in disconnected clusters.

This proof of concept shows that by mirroring container images along with their signatures, organizations can enforce security policies and ensure image integrity, even in isolated environments.

The post How to verify container signatures in disconnected OpenShift appeared first on Red Hat Developer.

Tagged:

Leave a Reply

Your email address will not be published. Required fields are marked *