Signing Keys¶
Three kinds of Secret sign different parts of the pipeline. The workload-namespace chart creates the two HMAC keys in each enabled namespace. The watcher creates each namespace's Ed25519 key in the webhook's own namespace. Nothing rotates them.
| Secret | Key field | Signs | Held by |
|---|---|---|---|
aibom-discovery-hmac-key |
hmac-key |
Hardware and storage data from the aibom-discovery init container |
The init container only. The watcher reads it to verify. |
aibom-dataset-hmac-key |
hmac-key |
Dataset data published by the aibom-dataset-sidecar |
The sidecar only. The watcher reads it to verify. |
aibom-compiled-signing-key-<namespace>, in the webhook's namespace |
ed25519-key |
The compiled AIBOM's spec.data for that namespace |
The aibom-postprocess Job only |
The two HMAC keys are shared secrets between the webhook's own components. The Ed25519 key is asymmetric so that oc aibom and anyone holding an archived AIBOM can verify a signature without being able to forge one. Its public half is embedded in each AIBOM (spec.signaturePublicKey) and published in the aibom-compiled-signing-public-key ConfigMap, the cluster-side anchor that oc aibom describe cross-checks. The oc aibom describe page in the CLI docs lists each result it can report.
The signatures are a tamper check, not proof the content is true. Detected Fields covers what each field does and doesn't guarantee.
What the signatures protect against¶
The keys are kept away from the code running inside a workload's containers, so a compromised training script or dependency can't sign anything. They don't hold against whoever writes the pod spec.
- The compiled AIBOM is safe from both. Its key and the
aibom-postprocessServiceAccount exist only in the webhook's namespace, and a pod can't mount a Secret or run as a ServiceAccount from another namespace. A user who can create pods in an enabled namespace can't create an AIBOM that verifies. - Hardware, storage and dataset data are not. Their HMAC keys are Secrets in the workload's own namespace, because the init container and sidecar that sign the data run in workload pods. Kubernetes lets any pod mount any Secret in its namespace, with no RBAC check. A user who can create pods there can mount
aibom-discovery-hmac-keyoraibom-dataset-hmac-key, write forged data that passes verification, and it ends up in a correctly signed AIBOM.
So a valid signature on an AIBOM means the pipeline compiled it and nothing changed it since. It doesn't mean its hardware or dataset sections came from the real discovery container and sidecar if untrusted users can create pods in that namespace. Restrict pod creation in enabled namespaces to people you trust with those claims.
This is a limitation of the design, not something a setting fixes. Anything signed inside a workload pod can be forged by whoever writes that pod's spec. Blocking pods that mount the HMAC Secrets wouldn't be enough: a pod can also share its process namespace with the sidecar or get a debug container attached to it, and the dataset sidecar signs whatever the workload writes to its handoff file, so dataset data needs no key to forge. Data that holds up against pod authors has to come from outside the pod, such as hardware read from node labels.
How keys are created and kept¶
The chart generates each HMAC Secret on first install. On later helm upgrade --install runs it looks the Secret up in the cluster and reuses the existing value, so re-running the install, for example to refresh the aibom-scripts ConfigMap, does not change the keys. The Ed25519 key is generated by the watcher the first time it postprocesses a workload from a namespace, and reused after that. It never exists in the workload namespace, so a user who can create pods there can't mount it.
Rendering the chart without cluster access
Reuse depends on Helm's lookup, which returns nothing when the chart is rendered offline. Tools that render with helm template instead of talking to the cluster, which is Argo CD's default, as well as helm template itself and --dry-run without a cluster connection, generate fresh random keys on every render. Applied by such a tool, every sync would replace both HMAC Secrets. The Ed25519 key isn't part of either chart.
If you manage namespaces this way, either use a tool that runs a real helm upgrade, or exclude the two HMAC Secrets from the sync and let the first install create them. To check that keys survive a sync, compare a hash before and after:
oc get secret aibom-discovery-hmac-key -n <namespace> -o jsonpath='{.data.hmac-key}' | sha256sum
What a key change does¶
There is no rotation command. A key changes only if its Secret is deleted and the chart runs again, or if it was replaced by an offline render as described above. For the Ed25519 key, delete aibom-compiled-signing-key-<namespace> in the webhook's namespace and the watcher creates a new one on the next postprocess. This follows from how the chart and pipeline are built, and has not been exercised on a live cluster.
| Key | Effect of a change |
|---|---|
| Discovery or dataset HMAC key | Pods already running were signed with the old key, so the watcher can't verify their data. It drops those entries and logs them, and the AIBOM is missing that pod's hardware or dataset data. Pods started after the change are unaffected. |
| Compiled AIBOM key | New AIBOMs are signed with the new key, and the aibom-compiled-signing-public-key ConfigMap is overwritten with its public half. Existing AIBOMs keep their own embedded key and still verify against it, but oc aibom describe reports them as KEY MISMATCH, because the live anchor no longer matches. |
Namespaces installed before signing existed have no Secret. The watcher treats that as "verification unavailable" and passes the data through unverified instead of dropping it. A Secret that exists but can't be read for another reason, such as a missing grant, is also passed through, with a logged warning.
Backup¶
The HMAC keys carry no long-term value: losing one costs only the in-flight pods described above. Back up aibom-compiled-signing-key-<namespace> if you want later AIBOMs to keep verifying against the same published key after a loss of the namespace. It is a private key, so store it in your secrets manager, not in Git.
The watcher's access to the HMAC Secrets is limited by resourceNames, in namespaces that installed the workload chart. In its own namespace it can create Secrets but not read them, which is enough to generate the Ed25519 keys. The aibom-postprocess ServiceAccount has no API grant on any Secret. The kubelet mounts the key into the Job.