From 1f279f07559408f3ba1a75548924a2160da2d17f Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Fri, 29 May 2026 11:42:06 +0900 Subject: [PATCH 1/6] feat: add label-based exclusion for firmware collection pods Add exclude block to inject-coco-initdata Kyverno policy to skip pods with label coco.io/skip-initdata: "true". Update firmware collection script to add this label to the pod, preventing Kyverno from trying to inject init_data (which would fail since the pod doesn't have coco.io/initdata-configmap annotation). The firmware collection pod doesn't need init_data injection because it only collects measurements from the TEE device - it doesn't attest to KBS or request secrets. Fixes error: mutation policy inject-coco-initdata error: failed to evaluate preconditions: failed to substitute variables in condition key Co-Authored-By: Claude Sonnet 4.5 --- .../templates/inject-coco-initdata.yaml | 6 ++++++ scripts/collect-firmware-refvals.sh | 2 ++ 2 files changed, 8 insertions(+) diff --git a/charts/all/coco-kyverno-policies/templates/inject-coco-initdata.yaml b/charts/all/coco-kyverno-policies/templates/inject-coco-initdata.yaml index 84c06855..d7b220a7 100644 --- a/charts/all/coco-kyverno-policies/templates/inject-coco-initdata.yaml +++ b/charts/all/coco-kyverno-policies/templates/inject-coco-initdata.yaml @@ -24,6 +24,12 @@ spec: - Pod operations: - CREATE + exclude: + any: + - resources: + selector: + matchLabels: + coco.io/skip-initdata: "true" preconditions: all: - key: "{{ "{{" }}request.object.spec.runtimeClassName || '' {{ "}}" }}" diff --git a/scripts/collect-firmware-refvals.sh b/scripts/collect-firmware-refvals.sh index ac3ecdc5..c8abfee3 100755 --- a/scripts/collect-firmware-refvals.sh +++ b/scripts/collect-firmware-refvals.sh @@ -118,6 +118,8 @@ apiVersion: v1 kind: Pod metadata: name: $POD_NAME + labels: + coco.io/skip-initdata: "true" spec: runtimeClassName: $RUNTIME_CLASS restartPolicy: Never From 738896f70f5c7611ae3867e42b07a492661aa0b2 Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Fri, 29 May 2026 13:44:48 +0900 Subject: [PATCH 2/6] fix: rewrite firmware collection to use veritas container approach Complete rewrite based on Red Hat documentation and veritas usage: - Runs veritas via podman container (quay.io/openshift_sandboxed_containers/coco-tools:1.12) - No cluster pods needed - computes firmware values locally from OCP release artifacts - Auto-detects OCP version from cluster or accepts --ocp-version flag - Extracts reference-values.json from veritas ConfigMap output - Saves to ~/.coco-pattern/firmware-reference-values.json - Uses --hw-xfam-allow x87,sse,avx to prevent attestation failures Previous approach was fundamentally wrong: - Tried to run veritas inside a kata pod on the cluster - Tried to "collect" from /dev/tdx_guest (doesn't work that way) - Veritas doesn't collect from running hardware - it computes expected values from OCP release artifacts (kata RPMs, edk2 firmware, etc.) Now follows the documented approach: https://docs.redhat.com/en/documentation/openshift_sandboxed_containers/1.12 Co-Authored-By: Claude Sonnet 4.5 --- scripts/collect-firmware-refvals.sh | 256 ++++++++-------------------- 1 file changed, 70 insertions(+), 186 deletions(-) diff --git a/scripts/collect-firmware-refvals.sh b/scripts/collect-firmware-refvals.sh index c8abfee3..77dea382 100755 --- a/scripts/collect-firmware-refvals.sh +++ b/scripts/collect-firmware-refvals.sh @@ -1,60 +1,52 @@ #!/usr/bin/env bash -# Collect firmware reference values from a bare metal confidential VM +# Collect firmware reference values using veritas container (runs locally, no cluster pods) # -# This script automates the full lifecycle: -# 1. Launch a kata pod with the specified RuntimeClass -# 2. Install veritas inside the pod -# 3. Collect firmware measurements (TDX/SNP) -# 4. Copy output locally and transform to RVPS format -# 5. Save to ~/.coco-pattern/firmware-reference-values.json -# 6. Clean up the pod +# This script: +# 1. Runs veritas via podman container to compute firmware measurements +# 2. Extracts reference values from OCP release artifacts +# 3. Saves to ~/.coco-pattern/firmware-reference-values.json +# 4. values-secret.yaml.template loads to Vault via 'make load-secrets' # # Usage: # ./scripts/collect-firmware-refvals.sh [OPTIONS] # # Options: -# -m, --merge Merge with existing file instead of overwriting -# -n, --namespace Namespace for collection pod (default: default) # -o, --output Override output path (default: ~/.coco-pattern/firmware-reference-values.json) -# -r, --runtime-class Override RuntimeClass (default: kata-cc) -# -i, --pod-image Override pod base image (default: registry.access.redhat.com/ubi9/ubi:latest) +# -p, --pull-secret Pull secret file (default: ~/pull-secret.json) +# -v, --ocp-version OCP version (default: auto-detect from cluster) +# -t, --tee TEE type (default: tdx) # -h, --help Show this help message set -euo pipefail # Defaults -NAMESPACE="default" OUTPUT_FILE="${HOME}/.coco-pattern/firmware-reference-values.json" -RUNTIME_CLASS="kata-cc" -POD_IMAGE="registry.access.redhat.com/ubi9/ubi:latest" -MERGE_MODE=false -POD_NAME="firmware-collector-$(date +%s)" +PULL_SECRET="${HOME}/pull-secret.json" +OCP_VERSION="" +TEE="tdx" +CONTAINER_IMAGE="quay.io/openshift_sandboxed_containers/coco-tools:1.12" # Parse arguments while [[ $# -gt 0 ]]; do case $1 in - -m|--merge) - MERGE_MODE=true - shift - ;; - -n|--namespace) - NAMESPACE="$2" - shift 2 - ;; -o|--output) OUTPUT_FILE="$2" shift 2 ;; - -r|--runtime-class) - RUNTIME_CLASS="$2" + -p|--pull-secret) + PULL_SECRET="$2" shift 2 ;; - -i|--pod-image) - POD_IMAGE="$2" + -v|--ocp-version) + OCP_VERSION="$2" + shift 2 + ;; + -t|--tee) + TEE="$2" shift 2 ;; -h|--help) - sed -n '2,17p' "$0" | sed 's/^# //' + sed -n '2,14p' "$0" | sed 's/^# //' exit 0 ;; *) @@ -66,167 +58,63 @@ while [[ $# -gt 0 ]]; do done # Prerequisites check -command -v oc >/dev/null 2>&1 || { echo "Error: oc CLI is required but not installed." >&2; exit 1; } -command -v jq >/dev/null 2>&1 || { echo "Error: jq is required but not installed." >&2; exit 1; } +command -v podman >/dev/null 2>&1 || { echo "Error: podman is required but not installed." >&2; exit 1; } +command -v yq >/dev/null 2>&1 || { echo "Error: yq is required but not installed." >&2; exit 1; } -# Check oc login -if ! oc whoami >/dev/null 2>&1; then - echo "Error: Not logged in to OpenShift. Run 'oc login' first." >&2 +# Check pull secret exists +if [ ! -f "$PULL_SECRET" ]; then + echo "Error: Pull secret not found at $PULL_SECRET" >&2 + echo "Provide path via --pull-secret or create ~/pull-secret.json" >&2 exit 1 fi +# Auto-detect OCP version if not specified +if [ -z "$OCP_VERSION" ]; then + if command -v oc >/dev/null 2>&1 && oc whoami >/dev/null 2>&1; then + echo "Detecting OCP version from cluster..." + OCP_VERSION=$(oc version -o json | yq -r '.openshiftVersion' 2>/dev/null || echo "") + if [ -z "$OCP_VERSION" ]; then + echo "Error: Could not auto-detect OCP version. Specify with --ocp-version" >&2 + exit 1 + fi + echo "Detected OCP version: $OCP_VERSION" + else + echo "Error: Not logged in to cluster and no --ocp-version specified" >&2 + exit 1 + fi +fi + echo "==========================================" echo "Firmware Reference Value Collection" echo "==========================================" -echo "Namespace: $NAMESPACE" -echo "RuntimeClass: $RUNTIME_CLASS" -echo "Pod image: $POD_IMAGE" +echo "OCP Version: $OCP_VERSION" +echo "TEE Type: $TEE" echo "Output file: $OUTPUT_FILE" -echo "Merge mode: $MERGE_MODE" echo "" -# Cleanup function (called via trap) -cleanup() { - local exit_code=$? - echo "" - if [[ $exit_code -ne 0 ]]; then - echo "⚠ Collection failed or was interrupted" - fi - - if oc get pod "$POD_NAME" -n "$NAMESPACE" &>/dev/null; then - echo "Cleaning up pod $POD_NAME..." - oc delete pod "$POD_NAME" -n "$NAMESPACE" --ignore-not-found=true - fi - - exit $exit_code -} - -# Register cleanup on exit, error, or interrupt -trap cleanup EXIT ERR SIGINT SIGTERM - -# Check for existing pod with same name and clean it up -if oc get pod "$POD_NAME" -n "$NAMESPACE" &>/dev/null; then - echo "Found existing pod $POD_NAME, cleaning up..." - oc delete pod "$POD_NAME" -n "$NAMESPACE" --wait=false - sleep 2 -fi - -# Create kata pod -echo "Creating kata pod with RuntimeClass $RUNTIME_CLASS..." -cat <&2 - oc describe pod/$POD_NAME -n $NAMESPACE >&2 - exit 1 -fi - -echo "Pod is Ready" +# Create temp directory for output +TEMP_DIR=$(mktemp -d) +trap "rm -rf $TEMP_DIR" EXIT -# Install pip and veritas -echo "Installing pip and veritas inside pod..." -oc exec $POD_NAME -n $NAMESPACE -- bash -c "dnf install -y python3-pip > /dev/null 2>&1" || { - echo "Error: Failed to install pip" >&2 - exit 1 -} - -oc exec $POD_NAME -n $NAMESPACE -- bash -c "pip install --quiet veritas-collectd" || { - echo "Error: Failed to install veritas" >&2 - exit 1 -} - -# Run veritas collection -echo "Running veritas collection (this may take 30-60 seconds)..." -if ! oc exec $POD_NAME -n $NAMESPACE -- veritas collect --output /tmp/refvals.json; then - echo "Error: Veritas collection failed" >&2 - echo "Check that the pod is running on hardware with TDX or SNP support" >&2 - exit 1 -fi - -# Copy output locally -echo "Copying veritas output locally..." -TEMP_RAW="/tmp/refvals-raw-$$.json" -oc cp $NAMESPACE/$POD_NAME:/tmp/refvals.json $TEMP_RAW || { - echo "Error: Failed to copy veritas output from pod" >&2 - exit 1 -} - -# Transform to RVPS format -echo "Transforming to RVPS format..." -TEMP_RVPS="/tmp/refvals-rvps-$$.json" - -jq -n \ - --arg mr_td "$(jq -r '.tdx.mr_td // empty' "$TEMP_RAW" 2>/dev/null || echo "")" \ - --arg rtmr_1 "$(jq -r '.tdx.rtmr[1] // empty' "$TEMP_RAW" 2>/dev/null || echo "")" \ - --arg rtmr_2 "$(jq -r '.tdx.rtmr[2] // empty' "$TEMP_RAW" 2>/dev/null || echo "")" \ - --arg xfam "$(jq -r '.tdx.xfam // empty' "$TEMP_RAW" 2>/dev/null || echo "")" \ - --arg snp_launch "$(jq -r '.snp.launch_measurement // empty' "$TEMP_RAW" 2>/dev/null || echo "")" \ - '{ - mr_td: (if $mr_td != "" then [$mr_td] else [] end), - rtmr_1: (if $rtmr_1 != "" then [$rtmr_1] else [] end), - rtmr_2: (if $rtmr_2 != "" then [$rtmr_2] else [] end), - xfam: (if $xfam != "" then [$xfam] else [] end), - snp_launch_measurement: (if $snp_launch != "" then [$snp_launch] else [] end) - }' > "$TEMP_RVPS" - -# Check if any values were extracted -VALUE_COUNT=$(jq '[.[] | select(length > 0)] | length' "$TEMP_RVPS") -if [ "$VALUE_COUNT" -eq 0 ]; then - echo "Error: No firmware measurements found in veritas output" >&2 - echo "Veritas may not support this hardware or the output format changed" >&2 - rm -f "$TEMP_RAW" "$TEMP_RVPS" - exit 1 -fi - -echo "Extracted firmware values:" -jq . "$TEMP_RVPS" - -# Merge with existing file if requested -if [ "$MERGE_MODE" = true ] && [ -f "$OUTPUT_FILE" ]; then - echo "Merging with existing file..." - EXISTING_DATA=$(cat "$OUTPUT_FILE") - - MERGED_DATA=$(jq -n \ - --argjson existing "$EXISTING_DATA" \ - --argjson new "$(cat "$TEMP_RVPS")" \ - '$existing * $new | - to_entries | - map({ - key: .key, - value: (.value | if type == "array" then (. + ($new[.key] // [])) | unique else . end) - }) | - from_entries' - ) - - echo "Merged firmware values:" - echo "$MERGED_DATA" | jq . - echo "$MERGED_DATA" > "$TEMP_RVPS" -fi - -# Save to output file -mkdir -p "$(dirname "$OUTPUT_FILE")" -cp "$TEMP_RVPS" "$OUTPUT_FILE" +# Run veritas via podman +echo "Running veritas to compute firmware measurements..." +echo "(This may take 2-3 minutes to download and process OCP release artifacts)" +echo "" -# Cleanup temp files -rm -f "$TEMP_RAW" "$TEMP_RVPS" +podman run --rm \ + -v "${PULL_SECRET}:/pull-secret.json:ro,z" \ + -v "${TEMP_DIR}:/output:z" \ + "$CONTAINER_IMAGE" \ + veritas --platform baremetal --tee "$TEE" \ + --ocp-version "$OCP_VERSION" \ + --authfile /pull-secret.json \ + --hw-xfam-allow x87 --hw-xfam-allow sse --hw-xfam-allow avx \ + -o /output + +# Extract reference-values.json from ConfigMap +echo "" +echo "Extracting reference values..." +yq '.data["reference-values.json"]' "$TEMP_DIR/rvps-reference-values.yaml" > "$OUTPUT_FILE" echo "" echo "✓ Successfully collected firmware reference values" @@ -235,11 +123,7 @@ echo "Saved to: $OUTPUT_FILE" echo "" echo "Next steps:" echo "1. Review the collected values: cat $OUTPUT_FILE" -echo "2. For bare metal deployments:" -echo " - Uncomment 'firmwareReferenceValues' in ~/values-secret-coco-pattern.yaml" -echo " - Run: make load-secrets" -echo "3. Verify the secret was synced to Vault:" -echo " vault kv get secret/hub/firmwareReferenceValues" -echo "4. Force ExternalSecret sync on the KBS cluster (if needed):" -echo " oc delete externalsecret firmware-refvals-eso -n trustee-operator-system" +echo "2. Uncomment 'firmwareReferenceValues' in ~/values-secret-coco-pattern.yaml" +echo "3. Run: make load-secrets" +echo "4. Verify upload: vault kv get secret/hub/firmwareReferenceValues" echo "" From 884e736e0c9e119bace51750153f680439340a70 Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Fri, 29 May 2026 15:17:26 +0900 Subject: [PATCH 3/6] fix: transform veritas array output to object format for RVPS policy Veritas outputs firmware reference values as a JSON array: [{"name": "mr_td", "value": [...]}, ...] But the trustee-chart RVPS ConfigurationPolicy template expects an object format: {"mr_td": [...], "rtmr_1": [...], ...} Transform the veritas output using jq: [.[] | {(.name): .value}] | add This fixes the RVPS policy error: can't evaluate field mr_td in type []interface {} Also added jq to prerequisites check. Co-Authored-By: Claude Sonnet 4.5 --- scripts/collect-firmware-refvals.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/collect-firmware-refvals.sh b/scripts/collect-firmware-refvals.sh index 77dea382..5d568925 100755 --- a/scripts/collect-firmware-refvals.sh +++ b/scripts/collect-firmware-refvals.sh @@ -60,6 +60,7 @@ done # Prerequisites check command -v podman >/dev/null 2>&1 || { echo "Error: podman is required but not installed." >&2; exit 1; } command -v yq >/dev/null 2>&1 || { echo "Error: yq is required but not installed." >&2; exit 1; } +command -v jq >/dev/null 2>&1 || { echo "Error: jq is required but not installed." >&2; exit 1; } # Check pull secret exists if [ ! -f "$PULL_SECRET" ]; then @@ -111,10 +112,11 @@ podman run --rm \ --hw-xfam-allow x87 --hw-xfam-allow sse --hw-xfam-allow avx \ -o /output -# Extract reference-values.json from ConfigMap +# Extract reference-values.json from ConfigMap and transform array → object echo "" echo "Extracting reference values..." -yq '.data["reference-values.json"]' "$TEMP_DIR/rvps-reference-values.yaml" > "$OUTPUT_FILE" +yq '.data["reference-values.json"]' "$TEMP_DIR/rvps-reference-values.yaml" | \ + jq '[.[] | {(.name): .value}] | add' > "$OUTPUT_FILE" echo "" echo "✓ Successfully collected firmware reference values" From 018f454d6a761192d632a57df22866c6435705cb Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Tue, 2 Jun 2026 09:15:30 +0800 Subject: [PATCH 4/6] fix: add -r flag to yq for cross-version compatibility yq v3 (kislyuk/yq) outputs JSON strings with quotes by default, so the embedded JSON in the YAML ConfigMap stays quoted and jq receives a string instead of an array. Adding -r outputs the raw string, which both yq v3 and v4 handle correctly. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/collect-firmware-refvals.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/collect-firmware-refvals.sh b/scripts/collect-firmware-refvals.sh index 5d568925..c31cb330 100755 --- a/scripts/collect-firmware-refvals.sh +++ b/scripts/collect-firmware-refvals.sh @@ -115,7 +115,10 @@ podman run --rm \ # Extract reference-values.json from ConfigMap and transform array → object echo "" echo "Extracting reference values..." -yq '.data["reference-values.json"]' "$TEMP_DIR/rvps-reference-values.yaml" | \ +# -r ensures the embedded JSON string is output raw (not quoted), +# which is required for yq v3 (kislyuk/yq) compatibility. +# yq v4 (mikefarah/yq) outputs raw scalars by default but -r is harmless. +yq -r '.data["reference-values.json"]' "$TEMP_DIR/rvps-reference-values.yaml" | \ jq '[.[] | {(.name): .value}] | add' > "$OUTPUT_FILE" echo "" From da87a3ba850ce64dbc1db2b07ccb901a6354332c Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Tue, 2 Jun 2026 09:58:42 +0800 Subject: [PATCH 5/6] feat: unify reference value collection for azure and baremetal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generalize collect-firmware-refvals.sh to support both platforms via --platform flag (baremetal default, azure optional). This replaces get-pcr.sh for Azure deployments — veritas pulls the same dm-verity image, verifies its signature via cosign, and extracts PCR values. Azure: outputs to ~/.coco-pattern/measurements.json (pcrStash secret) Baremetal: outputs to ~/.coco-pattern/firmware-reference-values.json Also adds yq -r fix for v3/v4 cross-compatibility and a new 'make collect-azure-refvals' Makefile target. Co-Authored-By: Claude Opus 4.6 (1M context) --- Makefile | 10 +-- scripts/collect-firmware-refvals.sh | 118 +++++++++++++++++++++------- 2 files changed, 96 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 584c5682..26a89e0e 100644 --- a/Makefile +++ b/Makefile @@ -4,11 +4,11 @@ include Makefile-common -##@ Firmware Reference Values +##@ Reference Value Collection .PHONY: collect-firmware-refvals -collect-firmware-refvals: ## Collect firmware reference values from bare metal cluster +collect-firmware-refvals: ## Collect firmware reference values (bare metal, default) @scripts/collect-firmware-refvals.sh -.PHONY: collect-firmware-refvals-merge -collect-firmware-refvals-merge: ## Collect and merge with existing firmware refvals - @scripts/collect-firmware-refvals.sh --merge +.PHONY: collect-azure-refvals +collect-azure-refvals: ## Collect PCR reference values (Azure) + @scripts/collect-firmware-refvals.sh --platform azure diff --git a/scripts/collect-firmware-refvals.sh b/scripts/collect-firmware-refvals.sh index c31cb330..708cf40d 100755 --- a/scripts/collect-firmware-refvals.sh +++ b/scripts/collect-firmware-refvals.sh @@ -3,32 +3,40 @@ # # This script: # 1. Runs veritas via podman container to compute firmware measurements -# 2. Extracts reference values from OCP release artifacts -# 3. Saves to ~/.coco-pattern/firmware-reference-values.json -# 4. values-secret.yaml.template loads to Vault via 'make load-secrets' +# 2. Extracts reference values from OCP release artifacts (baremetal) or +# dm-verity image (azure) +# 3. Saves to ~/.coco-pattern/ for loading into Vault via 'make load-secrets' # # Usage: # ./scripts/collect-firmware-refvals.sh [OPTIONS] # # Options: -# -o, --output Override output path (default: ~/.coco-pattern/firmware-reference-values.json) +# --platform Platform: baremetal (default) or azure +# -o, --output Override output path # -p, --pull-secret Pull secret file (default: ~/pull-secret.json) -# -v, --ocp-version OCP version (default: auto-detect from cluster) +# -v, --ocp-version OCP version (baremetal; default: auto-detect) +# --osc-version OSC operator version (azure; default: auto-detect) # -t, --tee TEE type (default: tdx) # -h, --help Show this help message set -euo pipefail # Defaults -OUTPUT_FILE="${HOME}/.coco-pattern/firmware-reference-values.json" +PLATFORM="baremetal" +OUTPUT_FILE="" PULL_SECRET="${HOME}/pull-secret.json" OCP_VERSION="" +OSC_VERSION="" TEE="tdx" CONTAINER_IMAGE="quay.io/openshift_sandboxed_containers/coco-tools:1.12" # Parse arguments while [[ $# -gt 0 ]]; do case $1 in + --platform) + PLATFORM="$2" + shift 2 + ;; -o|--output) OUTPUT_FILE="$2" shift 2 @@ -41,12 +49,16 @@ while [[ $# -gt 0 ]]; do OCP_VERSION="$2" shift 2 ;; + --osc-version) + OSC_VERSION="$2" + shift 2 + ;; -t|--tee) TEE="$2" shift 2 ;; -h|--help) - sed -n '2,14p' "$0" | sed 's/^# //' + sed -n '2,18p' "$0" | sed 's/^# //' exit 0 ;; *) @@ -57,6 +69,21 @@ while [[ $# -gt 0 ]]; do esac done +# Validate platform +if [[ "$PLATFORM" != "baremetal" && "$PLATFORM" != "azure" ]]; then + echo "Error: --platform must be 'baremetal' or 'azure'" >&2 + exit 1 +fi + +# Set default output file based on platform +if [ -z "$OUTPUT_FILE" ]; then + if [ "$PLATFORM" = "azure" ]; then + OUTPUT_FILE="${HOME}/.coco-pattern/measurements.json" + else + OUTPUT_FILE="${HOME}/.coco-pattern/firmware-reference-values.json" + fi +fi + # Prerequisites check command -v podman >/dev/null 2>&1 || { echo "Error: podman is required but not installed." >&2; exit 1; } command -v yq >/dev/null 2>&1 || { echo "Error: yq is required but not installed." >&2; exit 1; } @@ -69,26 +96,50 @@ if [ ! -f "$PULL_SECRET" ]; then exit 1 fi -# Auto-detect OCP version if not specified -if [ -z "$OCP_VERSION" ]; then - if command -v oc >/dev/null 2>&1 && oc whoami >/dev/null 2>&1; then - echo "Detecting OCP version from cluster..." - OCP_VERSION=$(oc version -o json | yq -r '.openshiftVersion' 2>/dev/null || echo "") +# Build version args and resolve version for display +VERSION_ARGS="" +VERSION_DISPLAY="" +if [ "$PLATFORM" = "azure" ]; then + if [ -z "$OSC_VERSION" ]; then + # Auto-detect from the cluster's sandbox subscription CSV + if command -v oc >/dev/null 2>&1 && oc whoami >/dev/null 2>&1; then + echo "Detecting OSC version from cluster..." + CSV=$(oc get subscription sandboxed-containers-operator \ + -n openshift-sandboxed-containers-operator \ + -o jsonpath='{.status.installedCSV}' 2>/dev/null || echo "") + if [ -n "$CSV" ]; then + OSC_VERSION="${CSV##*.v}" + echo "Detected OSC version: $OSC_VERSION" + fi + fi + if [ -z "$OSC_VERSION" ]; then + echo "Could not auto-detect OSC version, using 'latest'" >&2 + OSC_VERSION="latest" + fi + fi + VERSION_ARGS="--osc-version $OSC_VERSION" + VERSION_DISPLAY="OSC $OSC_VERSION" +else + if [ -z "$OCP_VERSION" ]; then + if command -v oc >/dev/null 2>&1 && oc whoami >/dev/null 2>&1; then + echo "Detecting OCP version from cluster..." + OCP_VERSION=$(oc version -o json | yq -r '.openshiftVersion' 2>/dev/null || echo "") + fi if [ -z "$OCP_VERSION" ]; then echo "Error: Could not auto-detect OCP version. Specify with --ocp-version" >&2 exit 1 fi echo "Detected OCP version: $OCP_VERSION" - else - echo "Error: Not logged in to cluster and no --ocp-version specified" >&2 - exit 1 fi + VERSION_ARGS="--ocp-version $OCP_VERSION" + VERSION_DISPLAY="OCP $OCP_VERSION" fi echo "==========================================" echo "Firmware Reference Value Collection" echo "==========================================" -echo "OCP Version: $OCP_VERSION" +echo "Platform: $PLATFORM" +echo "Version: $VERSION_DISPLAY" echo "TEE Type: $TEE" echo "Output file: $OUTPUT_FILE" echo "" @@ -97,22 +148,27 @@ echo "" TEMP_DIR=$(mktemp -d) trap "rm -rf $TEMP_DIR" EXIT -# Run veritas via podman +# Build veritas command +VERITAS_CMD="veritas --platform $PLATFORM --tee $TEE $VERSION_ARGS --authfile /pull-secret.json" + +# Add baremetal-specific flags +if [ "$PLATFORM" = "baremetal" ]; then + VERITAS_CMD="$VERITAS_CMD --hw-xfam-allow x87 --hw-xfam-allow sse --hw-xfam-allow avx" +fi + +VERITAS_CMD="$VERITAS_CMD -o /output" + echo "Running veritas to compute firmware measurements..." -echo "(This may take 2-3 minutes to download and process OCP release artifacts)" +echo "(This may take 2-3 minutes to download and process artifacts)" echo "" podman run --rm \ -v "${PULL_SECRET}:/pull-secret.json:ro,z" \ -v "${TEMP_DIR}:/output:z" \ "$CONTAINER_IMAGE" \ - veritas --platform baremetal --tee "$TEE" \ - --ocp-version "$OCP_VERSION" \ - --authfile /pull-secret.json \ - --hw-xfam-allow x87 --hw-xfam-allow sse --hw-xfam-allow avx \ - -o /output + $VERITAS_CMD -# Extract reference-values.json from ConfigMap and transform array → object +# Extract reference-values.json from ConfigMap and transform array -> object echo "" echo "Extracting reference values..." # -r ensures the embedded JSON string is output raw (not quoted), @@ -121,14 +177,22 @@ echo "Extracting reference values..." yq -r '.data["reference-values.json"]' "$TEMP_DIR/rvps-reference-values.yaml" | \ jq '[.[] | {(.name): .value}] | add' > "$OUTPUT_FILE" +# Save output +mkdir -p "$(dirname "$OUTPUT_FILE")" + echo "" -echo "✓ Successfully collected firmware reference values" +echo "Collected firmware reference values:" +jq . "$OUTPUT_FILE" echo "" echo "Saved to: $OUTPUT_FILE" echo "" +if [ "$PLATFORM" = "azure" ]; then + VAULT_KEY="pcrStash" +else + VAULT_KEY="firmwareReferenceValues" +fi echo "Next steps:" echo "1. Review the collected values: cat $OUTPUT_FILE" -echo "2. Uncomment 'firmwareReferenceValues' in ~/values-secret-coco-pattern.yaml" +echo "2. Ensure '$VAULT_KEY' is configured in ~/values-secret-coco-pattern.yaml" echo "3. Run: make load-secrets" -echo "4. Verify upload: vault kv get secret/hub/firmwareReferenceValues" echo "" From 1fa76b7df0e543012209b670d3047ccf315b1bea Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Tue, 2 Jun 2026 10:41:31 +0800 Subject: [PATCH 6/6] fix: update RHDP wrappers to use unified reference value collection Replace get-pcr.sh call with collect-firmware-refvals.sh --platform azure in wrapper.sh. Add missing reference value collection step to wrapper-multicluster.sh (was never collecting PCR values for Vault). Update RHDP README with prerequisites, env vars, and all deployment modes. Co-Authored-By: Claude Opus 4.6 (1M context) --- rhdp/README.md | 45 ++++++++++++++++++++++++++++++------ rhdp/wrapper-multicluster.sh | 5 ++++ rhdp/wrapper.sh | 2 +- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/rhdp/README.md b/rhdp/README.md index e5240b00..0e0e980e 100644 --- a/rhdp/README.md +++ b/rhdp/README.md @@ -3,6 +3,27 @@ Red Hat demo platform is a system for employees and red hat partners to generate test infrastructure. The scripts in this directory help users of that platform automate deployments. +## Prerequisites + +- `podman` installed and running (used for reference value collection) +- `yq`, `jq` installed +- OpenShift pull secret at `~/pull-secret.json` +- SSH key at `~/.ssh/id_rsa` (RSA) +- RHDP environment variables loaded (see below) + +## Environment variables + +Provided by your RHDP Azure Open Environment: + +```shell +export GUID= +export CLIENT_ID= +export PASSWORD= +export TENANT= +export SUBSCRIPTION= +export RESOURCEGROUP= +``` + ## To deploy 1. Stand up the 'Azure Subscription Based Blank Open Environment' @@ -12,13 +33,23 @@ The scripts in this directory help users of that platform automate deployments. ### Single Cluster Deployment - 1. `bash ./rhdp/wrapper.sh eastasia` - 2. The wrapper script **requires** an azure region code this code SHOULD be the same as what was selected in RHDP. + 1. Set `main.clusterGroupName: simple` in `values-global.yaml` + 2. `bash ./rhdp/wrapper.sh eastasia` + 3. The wrapper script **requires** an azure region code. This code SHOULD be the same as what was selected in RHDP. + 4. Optionally use `--prefix` for custom cluster naming: `bash ./rhdp/wrapper.sh --prefix dev1 eastasia` + +The wrapper handles: cluster provisioning, secret generation, PCR reference value collection (via veritas), and pattern installation. ### Multi-Cluster Deployment (Hub and Spoke) - 1. `bash ./rhdp/wrapper-multicluster.sh eastasia` - 2. This creates two clusters: `coco-hub` and `coco-spoke` in the same region - 3. The pattern is deployed only on the hub cluster - 4. Hub cluster kubeconfig: `./openshift-install-hub/auth/kubeconfig` - 5. Spoke cluster kubeconfig: `./openshift-install-spoke/auth/kubeconfig` + 1. Set `main.clusterGroupName: trusted-hub` in `values-global.yaml` + 2. `bash ./rhdp/wrapper-multicluster.sh eastasia` + 3. This creates two clusters: `coco-hub` and `coco-spoke` in the same region + 4. The pattern is deployed on the hub cluster; the spoke is imported into ACM + 5. Hub cluster kubeconfig: `./openshift-install-hub/auth/kubeconfig` + 6. Spoke cluster kubeconfig: `./openshift-install-spoke/auth/kubeconfig` + +### Cluster Only (no pattern install) + + 1. `bash ./rhdp/wrapper-cluster-only.sh eastasia` + 2. Provisions the cluster without installing secrets or the pattern diff --git a/rhdp/wrapper-multicluster.sh b/rhdp/wrapper-multicluster.sh index 26bb726d..08843f02 100755 --- a/rhdp/wrapper-multicluster.sh +++ b/rhdp/wrapper-multicluster.sh @@ -144,6 +144,11 @@ echo "---------------------" echo "setting up secrets" bash ./scripts/gen-secrets.sh +echo "---------------------" +echo "retrieving PCR measurements" +echo "---------------------" +bash ./scripts/collect-firmware-refvals.sh --platform azure + echo "---------------------" echo "starting pattern install on hub cluster" echo "---------------------" diff --git a/rhdp/wrapper.sh b/rhdp/wrapper.sh index 18763936..6c6cc539 100755 --- a/rhdp/wrapper.sh +++ b/rhdp/wrapper.sh @@ -189,7 +189,7 @@ bash ./scripts/gen-secrets.sh echo "---------------------" echo "retrieving PCR measurements" echo "---------------------" -bash ./scripts/get-pcr.sh +bash ./scripts/collect-firmware-refvals.sh --platform azure sleep 60 echo "---------------------"