diff --git a/Makefile b/Makefile index 057ceaa1..358444c4 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,10 @@ include Makefile-common ##@ Key Management +.PHONY: gen-secrets +gen-secrets: ## Generate KBS keys, sealed-secrets signing key, and values-secret template + @scripts/gen-secrets.sh + .PHONY: cache-keys cache-keys: ## Download Red Hat signing keys from official sources to ~/.coco-pattern/ @mkdir -p ~/.coco-pattern @@ -99,6 +103,14 @@ dcap-offline-provision: ## Full DCAP offline provisioning workflow (collect coll $(MAKE) collect-dcap-collateral $(MAKE) load-secrets +.PHONY: check-pck-expiry +check-pck-expiry: ## Check expiry of PCK cache secrets and platform data (requires oc login) + @scripts/check-pck-expiry.sh + +.PHONY: check-collateral-expiry +check-collateral-expiry: ## Check expiry of TDX DCAP collateral in trustee-operator-system (requires oc login) + @scripts/check-collateral-expiry.sh + ##@ AMD SEV-SNP VCEK Provisioning .PHONY: snp-collect-vcek-urls @@ -191,6 +203,16 @@ argocd-login: ## Extract ArgoCD credentials from cluster and log in with argocd fi ##@ Hardware Detection +.PHONY: get-pccs-node +get-pccs-node: ## Detect a node with Intel TDX support for PCCS deployment (requires KUBECONFIG or oc login) + @NODE=$$(oc get nodes -l intel.feature.node.kubernetes.io/tdx=true \ + -o jsonpath='{.items[0].metadata.name}' 2>/dev/null); \ + if [ -z "$$NODE" ]; then \ + echo "ERROR: No TDX-capable nodes found" >&2; \ + exit 1; \ + fi; \ + echo "$$NODE" + .PHONY: detect-hardware detect-hardware: ## Detect hardware profile from cluster nodes (requires KUBECONFIG or oc login) @echo "Detecting hardware profile from cluster nodes..." diff --git a/README.md b/README.md index 57cca15a..65e2447c 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,8 @@ For air-gapped bare metal environments, see [`airgap/DEPLOY-RUNBOOK.md`](airgap/ These scripts generate the cryptographic material and attestation reference values needed by Trustee. Run them once before your first deployment. -1. `bash scripts/gen-secrets.sh` — generates KBS key pairs, sealed-secrets signing keys, and copies `values-secret.yaml.template` to `~/values-secret-coco-pattern.yaml` -2. Collect attestation reference values (requires `podman`, `yq`, `jq`, and `~/pull-secret.json`): +1. `make gen-secrets` — generates KBS key pairs, sealed-secrets signing keys, and copies `values-secret.yaml.template` to `~/values-secret-coco-pattern.yaml` +2. Collect attestation reference values (requires `veritas` — `pip install "osc-veritas[snp]==0.1.3rc1"` —, `cosign` >= 2.0 for Azure, `yq`, `jq`, and `~/pull-secret.json`). By default this collects and merges reference values for **both TDX and SNP**: - **Azure:** `make collect-azure-refvals` — pulls PCR measurements from the dm-verity image via veritas. Saves to `~/.coco-pattern/measurements.json`. - **Bare metal:** `make collect-firmware-refvals` — computes firmware measurements from OCP release artifacts via veritas. Saves to `~/.coco-pattern/firmware-reference-values.json`. For bare metal, also uncomment the `firmwareReferenceValues` section in `~/values-secret-coco-pattern.yaml`. - See [docs/firmware-reference-values.md](docs/firmware-reference-values.md) for detailed workflow and options. diff --git a/docs/firmware-reference-values.md b/docs/firmware-reference-values.md index efbbc936..0f225f02 100644 --- a/docs/firmware-reference-values.md +++ b/docs/firmware-reference-values.md @@ -13,14 +13,20 @@ Reference values are cryptographic measurements of the Trusted Computing Base (T | Bare metal | TDX | mr_td, rtmr_1, rtmr_2, xfam | SHA-384 | | Bare metal | SNP | snp_launch_measurement | SHA-384 | -Both platforms use the [veritas](https://github.com/confidential-devhub/veritas) tool, packaged in the `quay.io/openshift_sandboxed_containers/coco-tools` container. No cluster access is required — veritas computes expected measurements from OCP release artifacts or the dm-verity image. +Both platforms use the [veritas](https://github.com/confidential-devhub/veritas) tool. No cluster access is required — veritas computes expected measurements from OCP release artifacts or the dm-verity image. + +By default, `collect-firmware-refvals.sh` collects reference values for **both TDX and SNP and merges them** into a single output, so one RVPS ConfigMap supports heterogeneous (mixed-TEE) deployments out of the box — see [Multi-Architecture Collection](#multi-architecture-collection) below. ## Prerequisites -- `podman` installed and running +- `veritas` installed on the host: `pip install "osc-veritas[snp]==0.1.3rc1"` +- `cosign` >= 2.0 — Azure only, used by veritas to verify the Red Hat dm-verity image signature: - `yq` and `jq` installed - OpenShift pull secret at `~/pull-secret.json` - For bare metal: OCP version of your cluster (auto-detected if `oc` is logged in) +- For bare metal TDX: `tdx-measure` (`cargo install --git https://github.com/virtee/tdx-measure tdx-measure-cli`) — collection continues with a warning if absent, but TDX RTMR values will be incomplete + +**Why host-installed instead of the `coco-tools` container**: the container image (`quay.io/openshift_sandboxed_containers/coco-tools:0.5.1`) is pinned to an older veritas release that lacks `--skip-tlog`, which is needed to avoid the Azure verification failures described below. This is a deliberate, temporary deviation — see the tracking issue referenced in [Known Limitations](#known-limitations) for moving back to the container once a `coco-tools` release ships with a newer veritas. ## Collecting Reference Values @@ -36,7 +42,9 @@ make collect-azure-refvals Output: `~/.coco-pattern/measurements.json` -Veritas pulls the `osc-dm-verity-image` from the Red Hat registry, verifies its signature via cosign, and extracts pre-computed PCR values. These are the same values previously collected by `scripts/get-pcr.sh`. +Veritas pulls the `osc-dm-verity-image` from the Red Hat registry, verifies its signature via cosign, and extracts pre-computed PCR values. + +**Signature verification and Rekor**: by default this script passes `--skip-tlog` to veritas for the Azure branch. Red Hat signs and logs these images against its own private Rekor instance, which has been unreliable (repeated `curl` failures fetching the Rekor public key). `--skip-tlog` still verifies the cosign signature against Red Hat's public key — it only skips the transparency-log lookup, which cannot succeed against a different Rekor server anyway (the log entry only exists on Red Hat's instance, so pointing at a different one, e.g. public Sigstore, does not work as a substitute). Pass `--verify-tlog` to opt back into full transparency-log verification if needed. ### Bare Metal @@ -47,7 +55,7 @@ make collect-firmware-refvals # Or with explicit OCP version: ./scripts/collect-firmware-refvals.sh --ocp-version 4.20.18 -# Specify TEE type (default: tdx): +# Collect a single TEE only (default is both, see below): ./scripts/collect-firmware-refvals.sh --tee snp --ocp-version 4.20.18 ``` @@ -66,9 +74,18 @@ Options: -p, --pull-secret Pull secret file (default: ~/pull-secret.json) -v, --ocp-version OCP version (baremetal; default: auto-detect) --osc-version OSC operator version (azure; default: auto-detect) - -t, --tee TEE type (default: tdx) + -t, --tee TEE type (default: both -- collects and merges both) + --verify-tlog Azure only: verify against Rekor instead of --skip-tlog ``` +## Multi-Architecture Collection + +By default (`--tee both`, or by omitting `--tee` entirely), this script runs veritas **twice** — once per TEE — and merges the resulting reference values into a single output file, for both the Azure and bare-metal branches. This supports heterogeneous/mixed-TEE deployments (for example, a bare-metal hub that verifies evidence from both TDX and SNP spokes, per `values-baremetal-hub.yaml`'s `kbs.tdx.enabled` + `kbs.snp.enabled`) without any manual merge step. + +The merge is a plain JSON key union: TDX and SNP reference values use disjoint, TEE-prefixed key names (`tdx_*`/`mr_td`/`rtmr_*` vs `snp_*`/`snp_launch_measurement`), so there's no collision risk, and this matches how `trustee-chart`'s RVPS template already consumes the `firmwareReferenceValues`/`pcrStash` secrets (it passes through whichever TEE-specific keys are present). + +Pass `--tee tdx` or `--tee snp` explicitly to collect a single architecture only (faster, useful for single-cluster deployments pinned to one hardware profile). + ## Loading Values to Vault ### Step 1: Configure values-secret.yaml @@ -149,13 +166,22 @@ The following table maps what veritas provides vs what the attestation policy ch | TEE type | Policy hardcoded | - | Policy hardcoded | - | | Init data | Computed by imperative job | Computed by imperative job | Computed by imperative job | Computed by imperative job | -## Known Limitations +## Azure "External" Reference Values (kbs.azure.*) + +Azure SEV-SNP also has a second, separate set of reference values that veritas does **not** collect: `trustee-chart`'s `kbs.azure.*` block (`snpLaunchMeasurement`, `smtEnabled`, `tsmeEnabled`, `abiMajor`, `abiMinor`, `singleSocket`, `smtAllowed`). These are static Azure-platform/VM-series constants (describing the SEV-SNP policy Azure enforces for a given confidential VM series), not measurements derived from any artifact veritas can pull and hash. + +coco-pattern pins these explicitly in `overrides/values-trustee-azure.yaml` (wired into `values-azure.yaml`) rather than silently relying on `trustee-chart`'s own defaults, so the values are visible/versioned in this repository. See that file's comments for the current VM-series mapping and for how to update them if you change `global.azure.defaultVMFlavour` to a series with different platform behavior. -As of the coco-tools 1.12 container: +**Note**: as of the current `trustee-chart` attestation policy, the Rego checks that would compare evidence against these values are commented out upstream ("Azure manages TCB validation"), so they are not currently enforced — they're pinned here so they're ready to take effect if/when upstream re-enables those checks, and so the values are documented and auditable rather than hidden inside a dependency chart's defaults. + +There is currently no automated way to collect/verify these values against a real deployment. A `snpguest`-based collection script (SSH into the podvm with `enableSSHDebug`, run `snpguest report --openhcl`, parse the SNP attestation report) is tracked as a follow-up. + +## Known Limitations 1. **TCB version numbers** — Not collected for SNP (reported_tcb_bootloader, tcb_microcode, etc.). Hardware trust claim fallback rules handle this. -2. **SNP policy configuration** — SMT, TSME, guest ABI not output. Configuration fallback rules check debug disabled + init_data. +2. **Azure SNP platform configuration** — SMT, TSME, guest ABI are not collected by veritas at all (see [Azure "External" Reference Values](#azure-external-reference-values-kbsazure) above); bare-metal SNP configuration fallback rules check debug disabled + init_data instead. 3. **rtmr_2 variants** — Veritas generates multiple cmdline variants (nr_cpus=1..N). If the actual cmdline differs, the policy falls back to the rtmr_1-only rule (executables: 4 instead of 3). +4. **Host-installed veritas instead of the `coco-tools` container** — temporary, until `coco-tools` publishes a release pinning a newer veritas with `--skip-tlog`/`--cosign-pub-key`/`--mirror-registry` support. See the tracking issue for details and for moving back to the container-based approach. ## Security Considerations diff --git a/overrides/values-trustee-azure.yaml b/overrides/values-trustee-azure.yaml new file mode 100644 index 00000000..702cb688 --- /dev/null +++ b/overrides/values-trustee-azure.yaml @@ -0,0 +1,45 @@ +# Azure SEV-SNP platform configuration reference values, pinned explicitly in +# coco-pattern rather than silently inherited from trustee-chart's own +# values.yaml defaults. +# +# These describe the SEV-SNP policy Azure enforces for confidential VMs of a +# given series. They are NOT derived from the workload image -- they are +# Azure platform constants for the VM type -- and are NOT collected by +# 'make collect-azure-refvals' (veritas does not compute these; see +# docs/firmware-reference-values.md "Known Limitations"). +# +# Current values below match Azure DCasv5-series VMs (this pattern's default +# VM flavour, see global.azure.defaultVMFlavour in values-global.yaml): +# +# VM Series | SMT | TSME | ABI Minor | Notes +# ----------------|-----|------|-----------|------ +# DCasv5 (Genoa) | true| true | 31 | Standard CoCo peer-pod VMs (default) +# DCadsv5 (Genoa) | true| true | 31 | With local NVMe +# ECasv5 (Genoa) | true| true | 31 | Memory-optimized +# DCesv5 (Milan) | true| true | 31 | Earlier generation, may differ +# +# If you change global.azure.defaultVMFlavour to a series with different +# platform behaviour, or if Azure updates its confidential VM firmware, +# update the values below to match. There is currently no automated way to +# collect them (see the tracking issue for a snpguest-based collection +# script) -- the only documented method today is: check the trustee logs +# (RUST_LOG=debug is enabled by default on the KBS pod) for the actual +# values reported by the VM on attestation failure, and update these to +# match. +# +# NOTE: as of trustee-chart's current attestation-policy.yaml, the Rego +# checks that would compare evidence against these values (smt_enabled, +# tsme_enabled, abi_major/minor, single_socket, smt_allowed) are commented +# out upstream ("Azure manages TCB validation" / "Azure platform +# constants"), so these are not currently enforced. They are pinned here +# so the values are visible/versioned in this repo, and ready to take +# effect if/when upstream re-enables those policy checks. +kbs: + azure: + snpLaunchMeasurement: "qnydpVwThuWxZTsSWXi+2ns/laha6w+d2723g84FaijJ0CHaI5w0pYw6ZXZUJw7v" + smtEnabled: "true" + tsmeEnabled: "true" + abiMajor: "0" + abiMinor: "31" + singleSocket: "false" + smtAllowed: "true" diff --git a/rhdp/README.md b/rhdp/README.md index b8f9d711..01ec5b2e 100644 --- a/rhdp/README.md +++ b/rhdp/README.md @@ -5,7 +5,9 @@ The scripts in this directory help users of that platform automate deployments. ## Prerequisites -- `podman` installed and running (used for reference value collection) +- `podman` installed and running (used by `pattern.sh` itself) +- `veritas` installed on the host (used for reference value collection): `pip install "osc-veritas[snp]==0.1.3rc1"` +- `cosign` >= 2.0 (used by veritas for Azure image signature verification) - `yq`, `jq` installed - OpenShift pull secret (default: `~/pull-secret.json`, override with `PULL_SECRET` — see below) - An SSH key pair (default: auto-detected, preferring Ed25519 — override with `SSH_PUBLIC_KEY` — see below) diff --git a/scripts/collect-firmware-refvals.sh b/scripts/collect-firmware-refvals.sh index 3ea1c1e2..2a948995 100755 --- a/scripts/collect-firmware-refvals.sh +++ b/scripts/collect-firmware-refvals.sh @@ -1,11 +1,26 @@ #!/usr/bin/env bash -# Collect firmware reference values using veritas container (runs locally, no cluster pods) +# Collect firmware reference values using the veritas CLI (runs locally, no cluster pods) # # This script: -# 1. Runs veritas via podman container to compute firmware measurements +# 1. Runs veritas (installed on the host) to compute firmware measurements # 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' +# 3. By default collects for BOTH TDX and SNP and merges the results, so a +# single output supports heterogeneous (mixed-TEE) deployments +# 4. Saves to ~/.coco-pattern/ for loading into Vault via 'make load-secrets' +# +# veritas is installed on the host via pip (see Prerequisites below) rather +# than run in a container. The container image this script used to run +# (quay.io/openshift_sandboxed_containers/coco-tools) is pinned to an older +# veritas release that lacks --skip-tlog, which is needed to avoid repeated +# failures against Red Hat's private Rekor instance for Azure image signature +# verification. See the tracking issue for moving back to the container once +# a coco-tools release ships with a newer veritas. +# +# Prerequisites: +# pip install "osc-veritas[snp]==0.1.3rc1" +# cosign >= 2.0 (Azure only; https://docs.sigstore.dev/cosign/system_config/installation/) +# tdx-measure (baremetal TDX only; cargo install --git https://github.com/virtee/tdx-measure tdx-measure-cli) # # Usage: # ./scripts/collect-firmware-refvals.sh [OPTIONS] @@ -16,7 +31,11 @@ # -p, --pull-secret Pull secret file (default: ~/pull-secret.json) # -v, --ocp-version OCP version (baremetal; default: auto-detect) # --osc-version OSC operator version (azure; default: auto-detect) -# -t, --tee TEE type (default: tdx) +# -t, --tee TEE type (default: both -- collects and merges both) +# --verify-tlog Azure only: verify against the Rekor transparency +# log instead of the default --skip-tlog. Only the +# signature check is skipped by default, not +# overall image verification. # -h, --help Show this help message set -euo pipefail @@ -27,8 +46,9 @@ OUTPUT_FILE="" PULL_SECRET="${HOME}/pull-secret.json" OCP_VERSION="" OSC_VERSION="" -TEE="tdx" -CONTAINER_IMAGE="quay.io/openshift_sandboxed_containers/coco-tools:0.5.1" +TEE="both" +SKIP_TLOG=true +VERITAS_PIP_SPEC='osc-veritas[snp]==0.1.3rc1' # Parse arguments while [[ $# -gt 0 ]]; do @@ -57,8 +77,12 @@ while [[ $# -gt 0 ]]; do TEE="$2" shift 2 ;; + --verify-tlog) + SKIP_TLOG=false + shift + ;; -h|--help) - sed -n '2,18p' "$0" | sed 's/^# //' + sed -n '2,39p' "$0" | sed 's/^# \?//' exit 0 ;; *) @@ -75,6 +99,15 @@ if [[ "$PLATFORM" != "baremetal" && "$PLATFORM" != "azure" ]]; then exit 1 fi +# Validate TEE +case "$TEE" in + tdx|snp|both) ;; + *) + echo "Error: --tee must be 'tdx', 'snp', or 'both'" >&2 + exit 1 + ;; +esac + # Set default output file based on platform if [ -z "$OUTPUT_FILE" ]; then if [ "$PLATFORM" = "azure" ]; then @@ -85,9 +118,33 @@ if [ -z "$OUTPUT_FILE" ]; then fi # Prerequisites check -command -v podman >/dev/null 2>&1 || { echo "Error: podman is required but not installed." >&2; exit 1; } +if ! command -v veritas >/dev/null 2>&1; then + echo "Error: veritas is required but not installed." >&2 + echo " Install with: pip install \"${VERITAS_PIP_SPEC}\"" >&2 + exit 1 +fi python3 -c "import yaml" 2>/dev/null || { echo "Error: python3 with PyYAML module is required. Install with: pip3 install pyyaml" >&2; exit 1; } +# cosign is only used by veritas for Azure image signature verification. +# Bare metal verifies via 'oc adm release info --verify' instead. +if [ "$PLATFORM" = "azure" ]; then + if ! command -v cosign >/dev/null 2>&1; then + echo "Error: cosign is required for Azure signature verification but was not found." >&2 + echo " Install cosign >= 2.0: https://docs.sigstore.dev/cosign/system_config/installation/" >&2 + exit 1 + fi + COSIGN_RAW_VERSION=$(cosign version 2>/dev/null | grep -oE 'GitVersion:[[:space:]]*v?[0-9]+\.[0-9]+' | grep -oE '[0-9]+\.[0-9]+' | head -1) + if [ -z "$COSIGN_RAW_VERSION" ]; then + echo "WARNING: could not determine cosign version; veritas requires cosign >= 2.0" >&2 + else + COSIGN_MAJOR="${COSIGN_RAW_VERSION%%.*}" + if [ "$COSIGN_MAJOR" -lt 2 ]; then + echo "Error: cosign >= 2.0 is required (found: $COSIGN_RAW_VERSION)" >&2 + exit 1 + fi + fi +fi + # Check pull secret exists if [ ! -f "$PULL_SECRET" ]; then echo "Error: Pull secret not found at $PULL_SECRET" >&2 @@ -96,7 +153,8 @@ if [ ! -f "$PULL_SECRET" ]; then fi # Build version args and resolve version for display -VERSION_ARGS="" +VERSION_ARG_NAME="" +VERSION_ARG_VALUE="" VERSION_DISPLAY="" if [ "$PLATFORM" = "azure" ]; then if [ -z "$OSC_VERSION" ]; then @@ -116,7 +174,8 @@ if [ "$PLATFORM" = "azure" ]; then OSC_VERSION="latest" fi fi - VERSION_ARGS="--image-tag $OSC_VERSION" + VERSION_ARG_NAME="--image-tag" + VERSION_ARG_VALUE="$OSC_VERSION" VERSION_DISPLAY="OSC $OSC_VERSION" else if [ -z "$OCP_VERSION" ]; then @@ -130,49 +189,35 @@ else fi echo "Detected OCP version: $OCP_VERSION" fi - VERSION_ARGS="--ocp-version $OCP_VERSION" + VERSION_ARG_NAME="--ocp-version" + VERSION_ARG_VALUE="$OCP_VERSION" VERSION_DISPLAY="OCP $OCP_VERSION" fi +if [ "$TEE" = "both" ]; then + TEES_TO_RUN=(tdx snp) +else + TEES_TO_RUN=("$TEE") +fi + echo "==========================================" echo "Firmware Reference Value Collection" echo "==========================================" echo "Platform: $PLATFORM" echo "Version: $VERSION_DISPLAY" -echo "TEE Type: $TEE" +echo "TEE Type(s): ${TEES_TO_RUN[*]}" echo "Output file: $OUTPUT_FILE" echo "" -# Create temp directory for output +# Create temp directory for per-TEE veritas output and extracted JSON TEMP_DIR=$(mktemp -d) -trap "rm -rf $TEMP_DIR" EXIT - -# 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 artifacts)" -echo "" - -podman run --rm \ - -v "${PULL_SECRET}:/pull-secret.json:ro,z" \ - -v "${TEMP_DIR}:/output:z" \ - "$CONTAINER_IMAGE" \ - $VERITAS_CMD +trap 'rm -rf "$TEMP_DIR"' EXIT -# Extract reference values from ConfigMap YAML (supports both old and new veritas formats) -echo "" -echo "Extracting reference values..." -mkdir -p "$(dirname "$OUTPUT_FILE")" - -python3 -c " +extract_reference_values() { + # Extract reference values from a veritas-produced ConfigMap YAML into a + # plain JSON dict (supports both old and new veritas RVPS formats). + local yaml_path="$1" + python3 -c " import yaml, json, base64, sys with open(sys.argv[1]) as f: @@ -182,7 +227,7 @@ data = doc.get('data', {}) result = {} if 'reference_value' in data: - # New format (veritas 0.5.1+ / coco-tools 0.5.1): JSON object with base64-encoded RVPS entries + # New format (veritas 0.1.x / Trustee 1.2): JSON object with base64-encoded RVPS entries raw = data['reference_value'] entries = json.loads(raw) if isinstance(raw, str) else raw for claim_name, b64_value in entries.items(): @@ -202,7 +247,64 @@ else: sys.exit(1) print(json.dumps(result, indent=2)) -" "$TEMP_DIR/rvps-reference-values.yaml" > "$OUTPUT_FILE" +" "$yaml_path" +} + +PER_TEE_JSON_FILES=() + +for tee in "${TEES_TO_RUN[@]}"; do + OUT_DIR="${TEMP_DIR}/${tee}" + mkdir -p "$OUT_DIR" + + VERITAS_ARGS=(--platform "$PLATFORM" --tee "$tee" "$VERSION_ARG_NAME" "$VERSION_ARG_VALUE" --authfile "$PULL_SECRET") + + # XFAM CPU features only matter for TDX; only add for the tdx run to + # avoid veritas's harmless-but-noisy "only relevant for TDX" warning. + if [ "$PLATFORM" = "baremetal" ] && [ "$tee" = "tdx" ]; then + VERITAS_ARGS+=(--hw-xfam-allow x87 --hw-xfam-allow sse --hw-xfam-allow avx) + fi + + # cosign/Rekor verification only applies to the Azure branch. Default to + # --skip-tlog: Red Hat signs and logs these images against its own + # private Rekor instance, which has been unreliable. --skip-tlog still + # verifies the cosign signature against Red Hat's public key -- it only + # skips the transparency-log lookup, which cannot succeed against a + # different Rekor server anyway (the log entry only exists on Red Hat's + # instance). Pass --verify-tlog to opt back into full verification. + if [ "$PLATFORM" = "azure" ] && [ "$SKIP_TLOG" = true ]; then + VERITAS_ARGS+=(--skip-tlog) + fi + + VERITAS_ARGS+=(-o "$OUT_DIR") + + echo "Running veritas (tee=$tee)..." + echo "(This may take 2-3 minutes to download and process artifacts)" + veritas "${VERITAS_ARGS[@]}" + echo "" + + TEE_JSON="${TEMP_DIR}/${tee}.json" + extract_reference_values "${OUT_DIR}/rvps-reference-values.yaml" > "$TEE_JSON" + PER_TEE_JSON_FILES+=("$TEE_JSON") +done + +echo "Merging reference values from: ${TEES_TO_RUN[*]}..." +mkdir -p "$(dirname "$OUTPUT_FILE")" + +python3 -c " +import json, sys + +result = {} +for path in sys.argv[1:]: + with open(path) as f: + data = json.load(f) + for key, value in data.items(): + if key in result and result[key] != value: + print(f\"WARNING: key '{key}' differs between TEE runs; keeping the first value seen\", file=sys.stderr) + continue + result[key] = value + +print(json.dumps(result, indent=2)) +" "${PER_TEE_JSON_FILES[@]}" > "$OUTPUT_FILE" echo "" echo "Collected firmware reference values:" diff --git a/scripts/get-pccs-node.sh b/scripts/get-pccs-node.sh deleted file mode 100755 index 32b4313b..00000000 --- a/scripts/get-pccs-node.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -# Detects a node with Intel TDX support for PCCS deployment. -# Usage: bash scripts/get-pccs-node.sh -NODE=$(oc get nodes -l intel.feature.node.kubernetes.io/tdx=true \ - -o jsonpath='{.items[0].metadata.name}' 2>/dev/null) -if [ -z "$NODE" ]; then - echo "ERROR: No TDX-capable nodes found" >&2 - exit 1 -fi -echo "$NODE" diff --git a/scripts/get-pcr.sh b/scripts/get-pcr.sh deleted file mode 100755 index b509edbd..00000000 --- a/scripts/get-pcr.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env bash -set -e - -# Script to retrieve the sandboxed container operator CSV for the current clusterGroup -# using the pull secret for authentication if needed. - -# 1. Locate pull secret -PULL_SECRET_PATH="${HOME}/pull-secret.json" -if [ ! -f "$PULL_SECRET_PATH" ]; then - if [ -n "${PULL_SECRET}" ]; then - PULL_SECRET_PATH="${PULL_SECRET}" - if [ ! -f "$PULL_SECRET_PATH" ]; then - echo "ERROR: Pull secret file not found at path specified in PULL_SECRET: $PULL_SECRET_PATH" - exit 1 - fi - else - echo "ERROR: Pull secret not found at ~/pull-secret.json" - echo "Please either place your pull secret at ~/pull-secret.json or set the PULL_SECRET environment variable" - exit 1 - fi -fi - -echo "Using pull secret: $PULL_SECRET_PATH" - -# 2. Check for required tools -if ! command -v yq &> /dev/null; then - echo "ERROR: yq is required but not installed" - echo "Please install yq: https://github.com/mikefarah/yq#install" - exit 1 -fi - -if ! command -v skopeo &> /dev/null; then - echo "ERROR: skopeo is required but not installed" - echo "Please install skopeo: https://github.com/containers/skopeo/blob/main/install.md" - exit 1 -fi - -if ! command -v podman &> /dev/null; then - echo "ERROR: podman is required but not installed" - echo "Please install podman: https://podman.io/docs/installation" - exit 1 -fi - -# 3. Check values-global.yaml exists -if [ ! -f "values-global.yaml" ]; then - echo "ERROR: values-global.yaml not found in current directory" - echo "Please run this script from the root directory of the project" - exit 1 -fi - -# 4. Get the active clusterGroupName from values-global.yaml -CLUSTER_GROUP_NAME=$(yq eval '.main.clusterGroupName' values-global.yaml) - -if [ -z "$CLUSTER_GROUP_NAME" ] || [ "$CLUSTER_GROUP_NAME" == "null" ]; then - echo "ERROR: Could not determine clusterGroupName from values-global.yaml" - echo "Expected: main.clusterGroupName to be set" - exit 1 -fi - -echo "Active clusterGroup: $CLUSTER_GROUP_NAME" - -# 5. Locate the values file for the active clusterGroup -VALUES_FILE="values-${CLUSTER_GROUP_NAME}.yaml" - -if [ ! -f "$VALUES_FILE" ]; then - echo "ERROR: Values file for clusterGroup not found: $VALUES_FILE" - exit 1 -fi - -# 6. Get the sandboxed container operator CSV from the clusterGroup values -SANDBOX_CSV=$(yq eval '.clusterGroup.subscriptions.sandbox.csv' "$VALUES_FILE") - -if [ -z "$SANDBOX_CSV" ] || [ "$SANDBOX_CSV" == "null" ]; then - echo "WARNING: No sandboxed container operator CSV found in $VALUES_FILE" - echo "The subscription clusterGroup.subscriptions.sandbox.csv is not defined" - exit 0 -fi - -# Extract version from CSV (e.g., "sandboxed-containers-operator.v1.12.0" -> "1.12.0") -# Remove everything up to and including ".v" -SANDBOX_VERSION="${SANDBOX_CSV##*.v}" - -echo "Sandboxed container operator CSV: $SANDBOX_CSV" -echo "Version: $SANDBOX_VERSION" -# alternatively, use the operator-version tag. -# OSC_VERSION=1.12.0 -VERITY_IMAGE=registry.redhat.io/openshift-sandboxed-containers/osc-dm-verity-image - -TAG=$(skopeo inspect --authfile $PULL_SECRET_PATH docker://${VERITY_IMAGE}:${SANDBOX_VERSION} | jq -r .Digest) - -IMAGE=${VERITY_IMAGE}@${TAG} - -echo "IMAGE: $IMAGE" - -curl -L https://tuf-default.apps.rosa.rekor-prod.2jng.p3.openshiftapps.com/targets/rekor.pub -o rekor.pub -curl -L https://security.access.redhat.com/data/63405576.txt -o cosign-pub-key.pem -# export REGISTRY_AUTH_FILE=${PULL_SECRET_PATH} -# echo "REGISTRY_AUTH_FILE: $REGISTRY_AUTH_FILE" -# export SIGSTORE_REKOR_PUBLIC_KEY=${PWD}/rekor.pub -# echo "SIGSTORE_REKOR_PUBLIC_KEY: $SIGSTORE_REKOR_PUBLIC_KEY" -# cosign verify --key cosign-pub-key.pem --output json --rekor-url=https://rekor-server-default.apps.rosa.rekor-prod.2jng.p3.openshiftapps.com $IMAGE > cosign_verify.log - - -# Ensure output directory exists -mkdir -p ~/.coco-pattern - -# Clean up any existing measurement files -rm -f ~/.coco-pattern/measurements-raw.json ~/.coco-pattern/measurements.json - -# Download the measurements using podman cp (works on macOS with remote podman) -podman pull --authfile $PULL_SECRET_PATH $IMAGE - -cid=$(podman create --entrypoint /bin/true $IMAGE) -echo "CID: ${cid}" -podman cp $cid:/image/measurements.json ~/.coco-pattern/measurements-raw.json -podman rm $cid - -# Trim leading "0x" from all measurement values -jq 'walk(if type == "string" and startswith("0x") then .[2:] else . end)' \ - ~/.coco-pattern/measurements-raw.json > ~/.coco-pattern/measurements.json - -echo "Measurements saved to ~/.coco-pattern/measurements.json (0x prefixes removed)" \ No newline at end of file diff --git a/values-azure.yaml b/values-azure.yaml index 326eb181..39b6c865 100644 --- a/values-azure.yaml +++ b/values-azure.yaml @@ -90,6 +90,7 @@ clusterGroup: chartVersion: 0.9.* extraValueFiles: - '/overrides/values-trustee.yaml' + - '/overrides/values-trustee-azure.yaml' overrides: - name: global.coco.secured value: "true"