Verify Component Versions in the Controller
On this page
- Goal
- You’ll end up with
- Prerequisites
- Steps
- How verification protects component references
- Troubleshooting
- Symptom: “signature verification failed for signature …”
- Symptom: “signature … not found in component”
- Symptom: “digest mismatch … for component version …:…”
- Symptom: “not safely digestible” event
- Symptom: “secret not found” or “failed to get secret”
- Symptom: “secret … does not contain key … for signature verification”
- Next Steps
- Related Documentation
Goal
Configure the OCM Kubernetes controller to automatically verify component version signatures before reconciling resources.
You’ll end up with
- A
Componentresource that ensures signature verification
Estimated time: ~5 minutes
Prerequisites
- Controller environment set up
- A signed component version in a local CTF archive
- The public key file at
/tmp/keys/public-key.pem(from Generate Signing Keys) - Access to an OCI registry (e.g., ghcr.io)
Steps
Transfer the signed component version to the registry
Push your signed component version from the local CTF archive to a remote OCI registry:
ocm transfer cv /tmp/helloworld/transport-archive//github.com/acme.org/helloworld:1.0.0 ghcr.io/<your-namespace>Verify the upload:
ocm get cv ghcr.io/<your-namespace>//github.com/acme.org/helloworld:1.0.0Expected output
COMPONENT │ VERSION │ PROVIDER ───────────────────────────────────┼─────────┼────────────── github.com/acme.org/helloworld │ 1.0.0 │ acme.orgPrepare the public key
Base64-encode your public key for use in the
Componentresource’svaluefield. The controller expects the PEM file content encoded as a base64 string:cat /tmp/keys/public-key.pem | base64 | tr -d '\n'Save the output - you will need it in the next step.
Create the
RepositoryresourceCreate and apply a
Repositorythat points to your OCI registry:cat <<EOF > repository.yaml apiVersion: delivery.ocm.software/v1alpha1 kind: Repository metadata: name: helloworld-repository spec: repositorySpec: baseUrl: ghcr.io/<your-namespace> type: OCIRegistry interval: 10m EOFkubectl apply -f repository.yamlCreate the
Componentresource with verificationCreate and apply a
Componentthat references the repository and configures signature verification. Choose one of the following approaches:Verify the
Componentis readyCheck that the
Componentresource reconciles successfully with verification:kubectl get component helloworld-component -o wideExpected output
NAME READY AGE helloworld-component Applied version 1.0.0 98sTo confirm the signature was actually verified, check the controller logs:
kubectl logs -n ocm-k8s-toolkit-system deploy/ocm-k8s-toolkit-controller-manager | grep "verifying signature"Expected output
{"level":"info","ts":"2026-04-28T15:58:14Z","msg":"verifying signature","component":"github.com/acme.org/helloworld","version":"1.0.0"}If verification fails, the
Componentwill not become ready and an error condition will be set.Check for failure
kubectl get component helloworld-component -o wideNAME READY AGE helloworld-component signature verification failed for signature default: missing public key, required for plain RSA signatures 7s
How verification protects component references
Component references can carry digests. When the controller resolves a reference that includes a digest, it computes a fresh digest of the referenced component and compares it against the recorded value. If they do not match, reconciliation fails.
Reference digests are computed and added automatically by ocm add cv. The ocm sign cv
command checks that the component version is safely digestible and warns if any reference or
resource digests are missing.
Troubleshooting
When verification fails, the Component resource’s Ready condition is set to False with the
error message. Check it with:
kubectl get component <name> -o jsonpath='{.status.conditions[?(@.type=="Ready")].message}'Symptom: “signature verification failed for signature …”
Cause: The verification credential (public key or certificate) does not match the private key used to sign the component version.
Fix: Ensure you are using the correct verification credential that corresponds to the private key used during signing. Verify the signature name matches by inspecting the component version:
ocm get cv ghcr.io/<your-namespace>//github.com/acme.org/helloworld:1.0.0 -o yaml | grep -A 5 "signatures:"Symptom: “signature … not found in component”
Cause: The component version does not contain a signature with the name specified in the
verify section of the Component resource spec.
Fix: Check which signatures exist on the component version and ensure the signature field
in the verify section of your Component resource matches:
ocm get cv ghcr.io/<your-namespace>//github.com/acme.org/helloworld:1.0.0 -o yaml | grep -A 5 "signatures:"Symptom: “digest mismatch … for component version …:…”
Cause: A parent component version includes a reference to another component version with a recorded digest. When the controller resolves that reference, the actual content does not match the recorded digest. This typically means the referenced component was modified or re-published after the parent recorded its digest.
Fix: Inspect the parent component version’s references to identify the digest mismatch:
ocm get cv ghcr.io/<your-namespace>//github.com/acme.org/parent-component:1.0.0 -o yamlLook at the componentReferences: section and their digest fields. To resolve, rebuild the
parent component version with correct reference digests, re-sign it, and then publish it.
Symptom: “not safely digestible” event
The Component becomes Ready, but a Kubernetes event with severity error is emitted containing
“not safely digestible”.
Cause: The component version does not satisfy OCM’s digest consistency rules:
- Component references must have complete digests (hash algorithm, normalisation algorithm, value)
- Resources with access must have complete digests
- Resources without access must not carry a digest
Without consistent digests, signature verification is skipped because the normalised form cannot be reliably computed.
Fix: Rebuild the component version with consistent digests, re-sign it, and then publish it.
The ocm sign cv command warns when a component version is not safely digestible.
Symptom: “secret not found” or “failed to get secret”
Cause: The Secret referenced in secretRef does not exist in the same namespace as the
Component resource.
Fix: Ensure the Secret is created in the same namespace:
kubectl get secret signing-verification-secret -n <component-namespace>Symptom: “secret … does not contain key … for signature verification”
Cause: The Secret does not contain a data entry matching the signature name.
Fix: The key in the Secret’s data field must exactly match the signature field in the
verify configuration. If your signature is named default, the Secret must have a default
key:
data:
default: <base64-encoded-public-key>Next Steps
- Getting Started: Deploy Helm Charts - Deploy resources from verified component versions
Related Documentation
- Concept: Signing and Verification - Understand how OCM signing works
- How-To: Verify Component Versions (CLI) - Verify signatures using the CLI
- How-To: Configure Credentials for OCM Controllers - Set up registry credentials for the controller