confidential-attestation
ugallu-confidential-attestation answers “is this node what it
claims to be?” - a per-node DaemonSet generates a hardware-rooted
quote, the controller verifies it against a configured policy, and
the result is sealed by the attestor for
downstream consumption.
Per-node dispatch
Section titled “Per-node dispatch”Unlike the other ugallu operators, this one runs without leader
election because each node must reconcile runs targeted at
itself. The reconciler filters cluster-wide on
spec.targetNodeName == os.Getenv("NODE_NAME") and skips
everything else - so 100 nodes producing 100 quotes is 100
independent reconciles, no coordination.
Backends
Section titled “Backends”| Backend | What it produces |
|---|---|
tpm | TPM 2.0 quote over PCR 0–7 using go-tpm-tools client.AttestationKeyECC. The quote includes the TPM-signed PCR digest + nonce. |
sev-snp | AMD SEV-SNP attestation report from /dev/sev-guest. Used on confidential VMs. |
tdx | Intel TDX attestation report from /dev/tdx-guest. Used on TDX-enabled hosts. |
Missing or unreadable devices fail the run with a structured reason
- there is no fallback to a software-emulated quote.
Verification policy
Section titled “Verification policy”ConfidentialAttestationRun.spec.policy declares the expected PCR
values / SEV-SNP IDBlock / TDX MRTD. The controller compares the
quote against the policy and emits:
AttestationVerified(Compliance class) on matchAttestationFailed(Detection class, severity=critical) on mismatch or device error
Example
Section titled “Example”apiVersion: security.ugallu.io/v1alpha1kind: ConfidentialAttestationRunmetadata: { name: bootcheck-node1, namespace: ugallu-system }spec: backend: tpm targetNodeName: node1.example.internal policy: tpm: pcrs: "0": "ab12...c3" "7": "ee45...77" timeout: 30sInternals
Section titled “Internals”State machine
Section titled “State machine”ConfidentialAttestationRun.status.phase: “ (Pending) ->
Running -> Succeeded | Failed. No finalizer. Per-node
scoping: a DaemonSet pod skips the run if
run.Spec.TargetNodeName != os.Getenv("NODE_NAME") - so 100
nodes producing 100 quotes is 100 independent reconciles.
Reconcile loop
Section titled “Reconcile loop”on each ConfidentialAttestationRun event: run := Get(req) if run.Spec.TargetNodeName != myNodeName: return # not for me if run.Status.Phase in {Succeeded, Failed}: return if run.Status.Phase == "": patch Status.Phase=Running, StartTime=now emitSE(AttestationStarted, info) return Requeue attester := attesterFor(run.Spec.Backend) # tpm | sev-snp | tdx outcome := attester.Attest(ctx, run.Spec.Nonce, run.Spec.Policy) upsert ConfidentialAttestationResult (Verdict, Quote, Measurements) patch Status.Phase = (outcome.Verdict==Verified ? Succeeded : Failed) emitSE(AttestationVerified | AttestationFailed)Error recovery
Section titled “Error recovery”Restart mid-attestation: new pod re-Gets the CR (Phase=Running)
and re-calls Attest(). Re-running with the same nonce is
deterministic against the hardware - the quote bytes will match
the earlier (lost) one. Result CR Create returns AlreadyExists
on retry; the controller falls back to Update on the result and
re-patches verdict. No leader election: each DaemonSet pod
owns its own reconciles, no coordination needed.
Crash recovery scenario
Section titled “Crash recovery scenario”Pod killed after Attest() returns but before the Result CR is
written: the new pod re-Gets the run, re-runs Attest()
(idempotent against the same nonce), creates the Result CR. The
hardware never produces conflicting quotes for the same nonce, so
the second run agrees with the first.
Edge cases
Section titled “Edge cases”- Indeterminate verdicts (e.g. policy says expected PCR but
the verifier can’t read the device) are emitted as
AttestationVerifiedatinfoseverity with notes inverifier.notes; the run is stillSucceededso dashboards see a result. - Software-emulated quotes are not allowed. Missing or unreadable hardware devices fail the run with a structured reason; there is no fallback.
- Per-node DaemonSet runs in
ugallu-system-privilegedwithpriorityClassName: system-node-criticalto survive node pressure.
Full RBAC (ClusterRole)
Section titled “Full RBAC (ClusterRole)”rules: - apiGroups: [security.ugallu.io] resources: - confidentialattestationruns - confidentialattestationruns/status - confidentialattestationresults - confidentialattestationresults/status verbs: [get, list, watch, create, update, patch] - apiGroups: [security.ugallu.io] resources: [securityevents] verbs: [create] - apiGroups: [""] resources: [events] verbs: [create, patch]No leases (no leader election).
CRDs owned
Section titled “CRDs owned”ConfidentialAttestationRun- per-run, per-node.
ConfidentialAttestationResult- quote bytes + verifier verdict.
Key flags
Section titled “Key flags”--cluster-id, --cluster-name, --node-name (defaults to
NODE_NAME env), --tpm-device, --sev-snp-device,
--tdx-device.
Deployment
Section titled “Deployment”DaemonSet in ugallu-system-privileged,
priorityClassName=system-node-critical, leader election off.
Mounts the hardware device hostPaths read-only. Each pod reconciles
only its own node’s runs.