Supply chain & attestation CRDs
These four kinds form the supply-chain story: every signed fact in
the cluster is an AttestationBundle, the attestor reads
AttestorConfig for its signing mode, and per-node hardware
measurements flow through the ConfidentialAttestationRun /
ConfidentialAttestationResult pair.
| Kind | Scope | Cardinality | Owning operator |
|---|---|---|---|
AttestationBundle | Cluster | per signed fact | ugallu-attestor |
AttestorConfig | Namespaced | singleton per namespace | ugallu-attestor |
ConfidentialAttestationRun | Namespaced | per node + window | confidential-attestation |
ConfidentialAttestationResult | Namespaced | per run | confidential-attestation |
AttestationBundle
Section titled “AttestationBundle”Cluster-scoped, one CR per signed fact. Owned by ugallu-attestor.
Spec
attestedFor(ObjectReference) - the SecurityEvent or EventResponse being signed.parentBundleRef(ObjectReference, optional) - for re-attestation, closure, or redaction records that chain back to a previous bundle.
Status
phase(enum) -Pending,Signed,Logged,Sealed.statementDigest(string) - SHA-256 of the canonicalised in-toto Statement.signature.mode(enum) -fulcio-keyless,openbao-transit,dual.signature.keyID(string) - fingerprint of the key used.rekorEntry.{logIndex, uuid, inclusionProof}- transparency log inclusion proof.wormRef- DSSE envelope archived to WORM.signedAt,sealedAt- lifecycle timestamps.failures[]- errors encountered during pipeline stages (preserved on retry so a half-failure stays auditable).
A bundle reaches Sealed only after the DSSE envelope is in WORM
AND the rekor inclusion proof is recorded. Anything short of that
keeps the bundle in an earlier phase, and forensics will not
trigger on it (when requireAttested=true).
Example (created by the attestor, not by humans)
apiVersion: security.ugallu.io/v1alpha1kind: AttestationBundlemetadata: name: bundle-1f4abc labels: ugallu.io/source-uid: "1f4abc..."spec: attestedFor: apiVersion: security.ugallu.io/v1alpha1 kind: SecurityEvent name: ugse-cluster-admin-xfb2status: phase: Sealed statementDigest: "sha256:..." signature: mode: fulcio-keyless keyID: "abcd1234..." rekorEntry: logIndex: 8412933 uuid: "..." signedAt: "2026-04-29T20:11:42Z" sealedAt: "2026-04-29T20:11:46Z"AttestorConfig
Section titled “AttestorConfig”Namespace-scoped singleton. Configures the signing mode plus the endpoints / credentials for the active backend(s).
Spec
signingMode(enum) -fulcio-keyless(default),openbao-transit, ordual(sign with both, fail if either fails).fulcio.issuer(string) - OIDC issuer URL.fulcio.fulcioURL(string) - Fulcio v2 CA endpoint.fulcio.oidcTokenPath(string) - projected ServiceAccount token mount path.openbao.address(string) - OpenBao base URL.openbao.transitMount(string) - defaulttransit.openbao.keyName(string) - must beed25519,rsa-pss-sha256, orecdsa-p256.openbao.authRole(string) - K8s auth role bound to the attestor’s ServiceAccount.rekor.enabled(bool) - defaulttrue.rekor.url(string) - transparency log endpoint.
Status - none. Last-load failures surface as a SE rather than on the CR.
InsecureSkipVerify on the Fulcio CA bundle and OpenBao TLS is
exposed for development clusters only; flip it back off before
promoting to staging.
Example
apiVersion: security.ugallu.io/v1alpha1kind: AttestorConfigmetadata: { name: default, namespace: ugallu-system }spec: signingMode: dual fulcio: issuer: "https://kubernetes.default.svc.cluster.local" fulcioURL: "https://fulcio.sigstore.dev" oidcTokenPath: "/var/run/secrets/sigstore/oidc-token" openbao: address: "https://openbao.openbao:8200" transitMount: transit keyName: ugallu-attestor-prod authRole: ugallu-attestor rekor: enabled: true url: "https://rekor.sigstore.dev"ConfidentialAttestationRun
Section titled “ConfidentialAttestationRun”Namespace-scoped, one CR per node + window. Owned by confidential-attestation.
Spec
backend(enum) -tpm,sev-snp,tdx.targetNodeName(string) - node the run targets. The DaemonSet pod whoseNODE_NAMEmatches handles the reconcile; everyone else skips.nonce(string) - anti-replay value (32-byte hex recommended).policyRef(LocalProfileRef, optional) -AttestationPolicywith expected measurements. Absent = report-only mode.timeout(Duration) - default2m.
Status
phase(enum) -Pending,Running,Succeeded,Failed.startTime,completionTime.resultRef- theConfidentialAttestationResultproduced (empty untilSucceeded).conditions[].
Example
apiVersion: security.ugallu.io/v1alpha1kind: ConfidentialAttestationRunmetadata: { name: bootcheck-node1, namespace: ugallu-system }spec: backend: tpm targetNodeName: node1.example.internal nonce: "1f4abc...32 bytes hex..." policyRef: name: tpm-policy-bios-v3 kind: AttestationPolicy timeout: 30sConfidentialAttestationResult
Section titled “ConfidentialAttestationResult”Namespace-scoped, one CR per run. Carries the quote bytes plus the verifier verdict.
Spec
derivedFromRun(LocalProfileRef).backend(enum) - mirrors the run.nodeName(string) - the node that answered.nonce(string) - the value the run requested (audit trail).quote(bytes) - raw attestation evidence (TPM2 quote / SNP report / TDX report - shape varies by backend).signature(bytes) - quote signature (TPM EK / SNP VLEK / TDX - empty when the signature is embedded in the quote bytes).measurements[]- per-slot digest summary extracted by the verifier.verdict(enum) -verified,failed,indeterminate.verifierNotes(string) - chain check details, missing-device messages, etc.
Status
trusted(bool) -trueonly whenverdict=verified.
Results are kept 7 days; the linked AttestationBundle carries the
long-term signed snapshot.
Example (controller-produced)
apiVersion: security.ugallu.io/v1alpha1kind: ConfidentialAttestationResultmetadata: { name: bootcheck-node1-result, namespace: ugallu-system }spec: derivedFromRun: { name: bootcheck-node1 } backend: tpm nodeName: node1.example.internal nonce: "1f4abc..." quote: "<base64 quote bytes>" signature: "<base64 quote signature>" measurements: - { slot: "PCR-0", digest: "sha256:ab12...c3" } - { slot: "PCR-7", digest: "sha256:ee45...77" } verdict: verified verifierNotes: "policy tpm-policy-bios-v3 matched, all PCRs ok"status: trusted: true