From a88740d4101d4cccef77915ae57ef0d9a2710d7b Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Wed, 22 Apr 2026 13:12:36 +0900 Subject: [PATCH 1/7] feat: add baremetal TDX and SNP attestation support Add direct TEE attestation rules for baremetal Intel TDX and AMD SEV-SNP. These use init_data hash verification (platform-independent) rather than Azure vTPM PCR measurements. Make pcr-stash secret lookup conditional in RVPS policy so baremetal deployments (which lack pcr-stash) don't fail. The init_data reference value is always included for both Azure and baremetal platforms. Co-Authored-By: Claude Opus 4.6 --- templates/attestation-policy.yaml | 18 +++++++++++++++++- templates/rvps-values-policies.yaml | 8 ++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/templates/attestation-policy.yaml b/templates/attestation-policy.yaml index dbf1660..224159a 100644 --- a/templates/attestation-policy.yaml +++ b/templates/attestation-policy.yaml @@ -53,4 +53,20 @@ data: configuration := 2 if { input["az-tdx-vtpm"] - } \ No newline at end of file + } + + ##### Baremetal TDX + executables := 3 if { + input["tdx"] + input.init_data in query_reference_value("init_data") + } + hardware := 2 if { input["tdx"] } + configuration := 2 if { input["tdx"] } + + ##### Baremetal SNP + executables := 3 if { + input["snp"] + input.init_data in query_reference_value("init_data") + } + hardware := 2 if { input["snp"] } + configuration := 2 if { input["snp"] } \ No newline at end of file diff --git a/templates/rvps-values-policies.yaml b/templates/rvps-values-policies.yaml index 3ea586f..a4fb4a9 100644 --- a/templates/rvps-values-policies.yaml +++ b/templates/rvps-values-policies.yaml @@ -21,12 +21,16 @@ spec: object-templates-raw: | {{`{{- $pcr8Hash := fromConfigMap "imperative" "initdata" "PCR8_HASH" -}}`}} {{`{{- $debugPcr8Hash := fromConfigMap "imperative" "debug-initdata" "PCR8_HASH" -}}`}} - {{`{{- $secretData := (lookup "v1" "Secret" "trustee-operator-system" "pcr-stash").data.json | base64dec | fromJson -}}`}} + {{`{{- $referenceValues := list (dict "name" "init_data" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash)) -}}`}} + {{`{{- $pcrStash := (lookup "v1" "Secret" "trustee-operator-system" "pcr-stash") -}}`}} + {{`{{- if $pcrStash -}}`}} + {{`{{- $secretData := $pcrStash.data.json | base64dec | fromJson -}}`}} {{`{{- $pcr03 := $secretData.measurements.sha256.pcr03 -}}`}} {{`{{- $pcr09 := $secretData.measurements.sha256.pcr09 -}}`}} {{`{{- $pcr11 := $secretData.measurements.sha256.pcr11 -}}`}} {{`{{- $pcr12 := $secretData.measurements.sha256.pcr12 -}}`}} - {{`{{- $referenceValues := list (dict "name" "snp_pcr03" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr03)) (dict "name" "tdx_pcr03" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr03)) (dict "name" "snp_pcr08" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash)) (dict "name" "tdx_pcr08" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash)) (dict "name" "snp_pcr09" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr09)) (dict "name" "tdx_pcr09" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr09)) (dict "name" "snp_pcr11" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr11)) (dict "name" "tdx_pcr11" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr11)) (dict "name" "snp_pcr12" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr12)) (dict "name" "tdx_pcr12" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr12)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "snp_pcr03" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr03)) (dict "name" "tdx_pcr03" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr03)) (dict "name" "snp_pcr08" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash)) (dict "name" "tdx_pcr08" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash)) (dict "name" "snp_pcr09" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr09)) (dict "name" "tdx_pcr09" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr09)) (dict "name" "snp_pcr11" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr11)) (dict "name" "tdx_pcr11" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr11)) (dict "name" "snp_pcr12" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr12)) (dict "name" "tdx_pcr12" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr12)) -}}`}} + {{`{{- end -}}`}} - complianceType: mustonlyhave objectDefinition: apiVersion: v1 From 02fe0394faa871a83310688d9a5348b7db6739a7 Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Wed, 22 Apr 2026 14:39:56 +0900 Subject: [PATCH 2/7] fix: disable TLS cert verification for PCCS in QCNL config The PCCS service uses a self-signed certificate which causes SGX_QL_ROOT_CA_UNTRUSTED errors during TDX quote verification. Co-Authored-By: Claude Opus 4.6 --- templates/tdx-config.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/tdx-config.yaml b/templates/tdx-config.yaml index d854da1..dcf8db2 100644 --- a/templates/tdx-config.yaml +++ b/templates/tdx-config.yaml @@ -9,6 +9,7 @@ metadata: data: sgx_default_qcnl.conf: | { - "collateral_service": "{{ .Values.kbs.tdx.collateralService }}" + "collateral_service": "{{ .Values.kbs.tdx.collateralService }}", + "use_secure_cert": false } {{- end }} From e4cb549aa99c356493950268acb0710dfd0f454e Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Wed, 22 Apr 2026 14:53:26 +0900 Subject: [PATCH 3/7] feat: support both Azure vTPM and baremetal init_data reference values The init_data RVPS entry now includes four values: - PCR8_HASH (secure + debug): SHA256(zeros || SHA256(toml)) for Azure vTPM - RAW_HASH padded (secure + debug): SHA256(toml) zero-padded to 48 bytes for baremetal TDX/SNP This allows a single attestation server to validate both Azure vTPM attestation (which presents PCR-extended hashes) and baremetal TDX/SNP attestation (which presents raw SHA-256 initdata hashes in the quote's mr_config_id field, zero-padded to SHA-384 width). Long-term, veritas (https://github.com/confidential-devhub/veritas) should be integrated for comprehensive reference value generation including firmware, kernel, and RTMR measurements. Co-Authored-By: Claude Opus 4.6 --- templates/rvps-values-policies.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/templates/rvps-values-policies.yaml b/templates/rvps-values-policies.yaml index a4fb4a9..07cf64b 100644 --- a/templates/rvps-values-policies.yaml +++ b/templates/rvps-values-policies.yaml @@ -21,7 +21,11 @@ spec: object-templates-raw: | {{`{{- $pcr8Hash := fromConfigMap "imperative" "initdata" "PCR8_HASH" -}}`}} {{`{{- $debugPcr8Hash := fromConfigMap "imperative" "debug-initdata" "PCR8_HASH" -}}`}} - {{`{{- $referenceValues := list (dict "name" "init_data" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash)) -}}`}} + {{`{{- $rawHash := fromConfigMap "imperative" "initdata" "RAW_HASH" -}}`}} + {{`{{- $debugRawHash := fromConfigMap "imperative" "debug-initdata" "RAW_HASH" -}}`}} + {{`{{- $rawHashPadded := printf "%s00000000000000000000000000000000" $rawHash -}}`}} + {{`{{- $debugRawHashPadded := printf "%s00000000000000000000000000000000" $debugRawHash -}}`}} + {{`{{- $referenceValues := list (dict "name" "init_data" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash $rawHashPadded $debugRawHashPadded)) -}}`}} {{`{{- $pcrStash := (lookup "v1" "Secret" "trustee-operator-system" "pcr-stash") -}}`}} {{`{{- if $pcrStash -}}`}} {{`{{- $secretData := $pcrStash.data.json | base64dec | fromJson -}}`}} From da742acc8675d72d8672f61c5474ab991649b49b Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Wed, 22 Apr 2026 15:01:36 +0900 Subject: [PATCH 4/7] fix: use chained single-item append calls for ACM compatibility ACM ConfigurationPolicy template engine rejects variadic append (want 2 got 11). Chain individual append calls instead. Co-Authored-By: Claude Opus 4.6 --- templates/rvps-values-policies.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/templates/rvps-values-policies.yaml b/templates/rvps-values-policies.yaml index 07cf64b..212f4b9 100644 --- a/templates/rvps-values-policies.yaml +++ b/templates/rvps-values-policies.yaml @@ -33,7 +33,16 @@ spec: {{`{{- $pcr09 := $secretData.measurements.sha256.pcr09 -}}`}} {{`{{- $pcr11 := $secretData.measurements.sha256.pcr11 -}}`}} {{`{{- $pcr12 := $secretData.measurements.sha256.pcr12 -}}`}} - {{`{{- $referenceValues = append $referenceValues (dict "name" "snp_pcr03" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr03)) (dict "name" "tdx_pcr03" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr03)) (dict "name" "snp_pcr08" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash)) (dict "name" "tdx_pcr08" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash)) (dict "name" "snp_pcr09" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr09)) (dict "name" "tdx_pcr09" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr09)) (dict "name" "snp_pcr11" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr11)) (dict "name" "tdx_pcr11" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr11)) (dict "name" "snp_pcr12" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr12)) (dict "name" "tdx_pcr12" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr12)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "snp_pcr03" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr03)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "tdx_pcr03" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr03)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "snp_pcr08" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "tdx_pcr08" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr8Hash $debugPcr8Hash)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "snp_pcr09" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr09)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "tdx_pcr09" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr09)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "snp_pcr11" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr11)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "tdx_pcr11" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr11)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "snp_pcr12" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr12)) -}}`}} + {{`{{- $referenceValues = append $referenceValues (dict "name" "tdx_pcr12" "expiration" "2027-12-12T00:00:00Z" "value" (list $pcr12)) -}}`}} {{`{{- end -}}`}} - complianceType: mustonlyhave objectDefinition: From a2aa3ccbef6161e7de6444f9991dc97e2835e9d6 Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Tue, 28 Apr 2026 16:04:42 +0800 Subject: [PATCH 5/7] feat: add NVIDIA GPU attestation via NRAS remote verifier - Add kbs.gpu.enabled value (default false) for GPU attestation support - Configure NRAS remote verifier when GPU enabled (kbs-config-map) - Add default_gpu.rego policy for NRAS x-nvidia-* claims - Add GPU-aware resource policy requiring both cpu0 and gpu0 affirming - Existing GPU rules in default_cpu.rego handle CPU-class + GPU evidence Co-Authored-By: Claude Opus 4.6 --- templates/attestation-policy.yaml | 60 ++++++++++++++++++++++++++++++- templates/kbs-config-map.yaml | 5 +++ templates/resource-policy.yaml | 9 ++++- values.yaml | 4 +++ 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/templates/attestation-policy.yaml b/templates/attestation-policy.yaml index 224159a..6219e6c 100644 --- a/templates/attestation-policy.yaml +++ b/templates/attestation-policy.yaml @@ -69,4 +69,62 @@ data: input.init_data in query_reference_value("init_data") } hardware := 2 if { input["snp"] } - configuration := 2 if { input["snp"] } \ No newline at end of file + configuration := 2 if { input["snp"] } + {{- if .Values.kbs.gpu.enabled }} + + ##### GPU Attestation (NVIDIA H100/H200) — CPU-class evidence with GPU data + hardware := 2 if { + input["snp"] + input["gpu"] + } + + executables := 3 if { + input["snp"] + input["gpu"] + input.init_data in query_reference_value("init_data") + } + + configuration := 2 if { + input["snp"] + input["gpu"] + } + {{- end }} +{{- if .Values.kbs.gpu.enabled }} + default_gpu.rego: | + package policy + + import rego.v1 + + default hardware := 97 + default executables := 33 + default configuration := 36 + + trust_claims := { + "executables": executables, + "hardware": hardware, + "configuration": configuration, + } + + hardware := 2 if { + input.nvidia + input.nvidia["x-nvidia-gpu-attestation-report-cert-chain"]["x-nvidia-cert-status"] == "valid" + input.nvidia["x-nvidia-gpu-attestation-report-parsed"] + input.nvidia["x-nvidia-gpu-attestation-report-signature-verified"] + input.nvidia["x-nvidia-gpu-arch-check"] + } + + configuration := 2 if { + input.nvidia.secboot + input.nvidia.dbgstat == "disabled" + } + + executables := 3 if { + input.nvidia["x-nvidia-gpu-driver-rim-fetched"] + input.nvidia["x-nvidia-gpu-driver-rim-schema-validated"] + input.nvidia["x-nvidia-gpu-driver-rim-signature-verified"] + input.nvidia["x-nvidia-gpu-vbios-rim-fetched"] + input.nvidia["x-nvidia-gpu-vbios-rim-schema-validated"] + input.nvidia["x-nvidia-gpu-vbios-rim-signature-verified"] + input.nvidia.measres == "success" + } +{{- end }} \ No newline at end of file diff --git a/templates/kbs-config-map.yaml b/templates/kbs-config-map.yaml index 177963e..186a3d5 100644 --- a/templates/kbs-config-map.yaml +++ b/templates/kbs-config-map.yaml @@ -52,6 +52,11 @@ data: [attestation_service.rvps_config.storage] type = "LocalJson" file_path = "/opt/confidential-containers/rvps/reference-values/reference-values.json" + {{- if .Values.kbs.gpu.enabled }} + + [attestation_service.verifier_config.nvidia_verifier] + type = "Remote" + {{- end }} [[plugins]] name = "resource" diff --git a/templates/resource-policy.yaml b/templates/resource-policy.yaml index 2b5851e..1f3b2ed 100644 --- a/templates/resource-policy.yaml +++ b/templates/resource-policy.yaml @@ -15,4 +15,11 @@ data: allow if { input["submods"]["cpu0"]["ear.status"] == "affirming" - } \ No newline at end of file + } + {{- if .Values.kbs.gpu.enabled }} + + allow if { + input["submods"]["cpu0"]["ear.status"] == "affirming" + input["submods"]["gpu0"]["ear.status"] == "affirming" + } + {{- end }} \ No newline at end of file diff --git a/values.yaml b/values.yaml index 7d2e1af..0df9564 100644 --- a/values.yaml +++ b/values.yaml @@ -48,6 +48,10 @@ kbs: # exist in the trustee-operator-system namespace. extraSecrets: [] + # NVIDIA GPU confidential computing configuration + gpu: + enabled: false + # Intel TDX (Trust Domain Extensions) configuration tdx: # Enable TDX attestation support From 2b69e22b70b4f454a6b7b9238740826a6fbe4a8f Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Tue, 5 May 2026 20:15:22 +0900 Subject: [PATCH 6/7] fix: ensure GPU attestation is required when GPU is enabled Previously, when GPU attestation was enabled, the policy would still allow access with only CPU attestation due to the first rule being unconditionally present. This fix ensures the CPU-only rule only applies when GPU is disabled, preventing the bypass. Co-Authored-By: Claude Sonnet 4.5 --- templates/resource-policy.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/resource-policy.yaml b/templates/resource-policy.yaml index 1f3b2ed..56d8a47 100644 --- a/templates/resource-policy.yaml +++ b/templates/resource-policy.yaml @@ -12,11 +12,12 @@ data: import rego.v1 default allow := false + {{- if not .Values.kbs.gpu.enabled }} allow if { input["submods"]["cpu0"]["ear.status"] == "affirming" } - {{- if .Values.kbs.gpu.enabled }} + {{- else }} allow if { input["submods"]["cpu0"]["ear.status"] == "affirming" From 92d3ae2c9d0704dc0bda888ff2a7e58f1c1918fa Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Tue, 5 May 2026 20:20:10 +0900 Subject: [PATCH 7/7] chore: version bump Signed-off-by: Chris Butler --- Chart.yaml | 2 +- README.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Chart.yaml b/Chart.yaml index ec3226d..8f6cb49 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -7,4 +7,4 @@ keywords: - confidential-containers name: trustee # DO NOT EDIT VERSION HERE, IT IS AUTO-GENERATED BY SEMANTIC-RELEASE -version: 0.3.2 +version: 0.3.3 diff --git a/README.md b/README.md index f462935..83b21de 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # trustee -![Version: 0.3.2](https://img.shields.io/badge/Version-0.3.2-informational?style=flat-square) +![Version: 0.3.3](https://img.shields.io/badge/Version-0.3.3-informational?style=flat-square) A Helm chart to provide an opinionated deployment of Trustee in a validated pattern @@ -34,6 +34,7 @@ In order to use this chart, you will need to: | kbs.admin.format | string | `"v1.0"` | | | kbs.cosignKeys | string | `"secret/data/hub/coSignKeys"` | | | kbs.extraSecrets | list | `[]` | | +| kbs.gpu.enabled | bool | `false` | | | kbs.publicKey | string | `"secret/data/hub/kbsPublicKey"` | | | kbs.secretResources[0].key | string | `"secret/data/hub/kbsres1"` | | | kbs.secretResources[0].name | string | `"kbsres1"` | |