diff --git a/Makefile b/Makefile index 358444c4..73b0e22a 100644 --- a/Makefile +++ b/Makefile @@ -69,6 +69,10 @@ gen-mirror-helm-secret: ## Generate mirror-registry Helm OCI password file from @read -r MRPASS; printf '%s' "$$MRPASS" > ~/.coco-pattern/mirror-registry-password; chmod 600 ~/.coco-pattern/mirror-registry-password @echo " Saved to ~/.coco-pattern/mirror-registry-password" +.PHONY: enable-airgap-secrets +enable-airgap-secrets: ## Uncomment disconnected-mirror secrets (registryCaCert, bootstrap_secrets) in the generated values-secret file + @scripts/enable-airgap-secrets.sh + .PHONY: pck-register pck-register: ## Register PCK certificates with Intel PCS (requires INTEL_PCS_API_KEY) @if [ -z "$(INTEL_PCS_API_KEY)" ]; then \ diff --git a/README.md b/README.md index 65e2447c..4a6ece1b 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ These scripts generate the cryptographic material and attestation reference valu 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`. + - **Bare metal:** `make collect-firmware-refvals` — computes firmware measurements from OCP release artifacts via veritas. Saves to `~/.coco-pattern/firmware-reference-values.json`. `pcrStash` and `firmwareReferenceValues` are both enabled by default in `~/values-secret-coco-pattern.yaml`, so nothing needs to be uncommented — the collection script automatically writes an empty `{}` placeholder for the platform you're not using. - See [docs/firmware-reference-values.md](docs/firmware-reference-values.md) for detailed workflow and options. 3. Review and customise `~/values-secret-coco-pattern.yaml` — this file is loaded into Vault and provides secrets to the pattern. diff --git a/airgap/DEPLOY-RUNBOOK.md b/airgap/DEPLOY-RUNBOOK.md index d15579f4..b3e8ea2c 100644 --- a/airgap/DEPLOY-RUNBOOK.md +++ b/airgap/DEPLOY-RUNBOOK.md @@ -910,6 +910,12 @@ make cache-keys 2>&1 | tee -a "$LOG" make cache-registry-ca 2>&1 | tee -a "$LOG" ./scripts/gen-secrets.sh 2>&1 | tee -a "$LOG" +# registryCaCert and bootstrap_secrets (mirror-registry-helm-oci) are +# commented out by default in values-secret.yaml.template (they only apply +# to airgap deployments). Uncomment both blocks in the generated +# values-secret file now that cache-registry-ca has populated the CA cert. +make enable-airgap-secrets 2>&1 | tee -a "$LOG" + # Strip trailing newline from mirror-registry-password. # load-bootstrap reads this file verbatim via the values-secret.yaml path: field and # the Ansible role does not strip whitespace. A trailing \n causes Helm to send diff --git a/docs/firmware-reference-values.md b/docs/firmware-reference-values.md index 0f225f02..bb4e135d 100644 --- a/docs/firmware-reference-values.md +++ b/docs/firmware-reference-values.md @@ -90,18 +90,17 @@ Pass `--tee tdx` or `--tee snp` explicitly to collect a single architecture only ### Step 1: Configure values-secret.yaml -Azure reference values use the `pcrStash` secret (already enabled by default in `~/values-secret-coco-pattern.yaml`). - -Bare metal reference values use the `firmwareReferenceValues` secret. Uncomment this section in `~/values-secret-coco-pattern.yaml`: - -```yaml -- name: firmwareReferenceValues - vaultPrefixes: - - hub - fields: - - name: json - path: ~/.coco-pattern/firmware-reference-values.json -``` +Azure reference values use the `pcrStash` secret and bare metal reference +values use the `firmwareReferenceValues` secret. Both are enabled by default +in `~/values-secret-coco-pattern.yaml`, so the same file works unmodified on +either topology — nothing needs to be uncommented. + +`collect-firmware-refvals.sh` automatically creates an empty `{}` placeholder +for whichever of `~/.coco-pattern/measurements.json` / +`~/.coco-pattern/firmware-reference-values.json` you are *not* collecting, so +`make load-secrets` never fails with a missing-file error regardless of +platform. Real collected data always overwrites the placeholder for the +platform you actually run. ### Step 2: Push to Vault diff --git a/scripts/collect-firmware-refvals.sh b/scripts/collect-firmware-refvals.sh index 2a948995..95bc0cc3 100755 --- a/scripts/collect-firmware-refvals.sh +++ b/scripts/collect-firmware-refvals.sh @@ -314,9 +314,24 @@ echo "Saved to: $OUTPUT_FILE" echo "" if [ "$PLATFORM" = "azure" ]; then VAULT_KEY="pcrStash" + SIBLING_FILE="${HOME}/.coco-pattern/firmware-reference-values.json" else VAULT_KEY="firmwareReferenceValues" + SIBLING_FILE="${HOME}/.coco-pattern/measurements.json" fi + +# The values-secret template enables pcrStash (Azure) and +# firmwareReferenceValues (bare metal) unconditionally so the same file works +# on either topology. Ensure the *other* platform's file also exists (as an +# empty '{}' placeholder) so 'make load-secrets' doesn't fail on a topology +# that only ever collects reference values for one platform. This never +# overwrites real, previously-collected data. +if [ ! -f "$SIBLING_FILE" ]; then + echo '{}' > "$SIBLING_FILE" + echo "Created empty placeholder for the other platform: $SIBLING_FILE" + echo "" +fi + echo "Next steps:" echo "1. Review the collected values: cat $OUTPUT_FILE" echo "2. Ensure '$VAULT_KEY' is configured in ~/values-secret-coco-pattern.yaml" diff --git a/scripts/enable-airgap-secrets.sh b/scripts/enable-airgap-secrets.sh new file mode 100755 index 00000000..83c521e6 --- /dev/null +++ b/scripts/enable-airgap-secrets.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Uncomments the disconnected/airgap-only secrets in a generated +# values-secret file: registryCaCert and bootstrap_secrets +# (mirror-registry-helm-oci). Both are commented out by default in +# values-secret.yaml.template because they only apply to airgap +# (disconnected mirror) deployments and reference local files +# (~/.coco-pattern/mirror-registry-ca-cert.pem, +# ~/.coco-pattern/mirror-registry-password) that don't exist on connected +# deployments. +# +# Usage: +# ./scripts/enable-airgap-secrets.sh [path-to-values-secret-file] +# +# Idempotent: safe to run more than once against the same file. + +set -euo pipefail + +VALUES_FILE="${1:-${HOME}/values-secret-coco-pattern.yaml}" + +if [ ! -f "${VALUES_FILE}" ]; then + echo "ERROR: ${VALUES_FILE} not found." >&2 + echo " Run 'make gen-secrets' first, or pass the path explicitly:" >&2 + echo " $0 " >&2 + exit 1 +fi + +if ! grep -q "AIRGAP-MIRROR-SECRETS-START" "${VALUES_FILE}"; then + echo "ERROR: ${VALUES_FILE} has no AIRGAP-MIRROR-SECRETS markers." >&2 + echo " Was it generated from an older values-secret.yaml.template? Regenerate with 'make gen-secrets'." >&2 + exit 1 +fi + +sed -i.bak ' +/# AIRGAP-MIRROR-SECRETS-START/,/# AIRGAP-MIRROR-SECRETS-END/ { + /AIRGAP-MIRROR-SECRETS-START/b + /AIRGAP-MIRROR-SECRETS-END/b + s/^\([[:space:]]*\)#/\1/ +} +' "${VALUES_FILE}" +rm -f "${VALUES_FILE}.bak" + +echo "Uncommented airgap mirror secrets (registryCaCert, bootstrap_secrets) in ${VALUES_FILE}" +echo +echo "Make sure these exist before 'make load-secrets' / 'make load-bootstrap':" +echo " ~/.coco-pattern/mirror-registry-ca-cert.pem (make cache-registry-ca)" +echo " ~/.coco-pattern/mirror-registry-password (make gen-mirror-helm-secret)" diff --git a/scripts/gen-secrets.sh b/scripts/gen-secrets.sh index a042b193..50995e77 100755 --- a/scripts/gen-secrets.sh +++ b/scripts/gen-secrets.sh @@ -9,6 +9,20 @@ VALUES_FILE="${HOME}/values-secret-coco-pattern.yaml" mkdir -p ${COCO_SECRETS_DIR} +## Ensure both platform-specific reference-value files exist. The +## values-secret template enables pcrStash (Azure) and firmwareReferenceValues +## (bare metal) unconditionally so the same file works on either topology. +## This pre-touches an empty '{}' placeholder for whichever platform's file +## doesn't exist yet, so 'make load-secrets' won't fail with a missing-file +## error before collect-firmware-refvals.sh has been run for your platform. +## Real collected data (from collect-firmware-refvals.sh) always overwrites +## these placeholders. +for refval_file in measurements.json firmware-reference-values.json; do + if [ ! -f "${COCO_SECRETS_DIR}/${refval_file}" ]; then + echo '{}' >"${COCO_SECRETS_DIR}/${refval_file}" + fi +done + SSH_KEY_FILE="${COCO_SECRETS_DIR}/id_rsa" if [ "${COCO_ENABLE_SSH_DEBUG:-false}" = "true" ]; then @@ -47,19 +61,24 @@ if [ ! -f "${VALUES_FILE}" ]; then echo "ACTION REQUIRED: Review and customize this file before deploying:" echo echo " For Azure deployments:" + echo " - Run 'make collect-azure-refvals' to collect PCR measurements" + echo " - pcrStash is already enabled by default; no need to uncomment anything" echo " - SSH debug is optional (uncomment sshKey if needed)" - echo " - DCAP collateral section can remain commented out" + echo " - DCAP collateral (tdxCollateral) is bare-metal-TDX-only; leave commented out" echo echo " For Bare Metal deployments:" echo " - Run 'make collect-firmware-refvals' to collect firmware measurements" - echo " - Uncomment firmwareReferenceValues in values-secret file" - echo " - For Intel TDX: run 'make collect-dcap-collateral' for offline attestation" + echo " - firmwareReferenceValues is already enabled by default; no need to uncomment anything" + echo " - For Intel TDX: run 'make collect-dcap-collateral', then uncomment tdxCollateral" + echo " in the values-secret file for offline attestation" echo " - SSH debug is optional (uncomment sshKey if needed)" echo " - See docs/firmware-reference-values.md for reference value collection" echo echo " For airgap (disconnected) deployments:" - echo " - Bootstrap secrets (mirror-registry-helm-oci) are pre-configured" - echo " - Run 'make cache-registry-ca' to cache the mirror registry CA cert" + echo " - registryCaCert and bootstrap_secrets (mirror-registry-helm-oci) are" + echo " commented out by default -- run 'make cache-registry-ca' and" + echo " 'make gen-mirror-helm-secret', then 'make enable-airgap-secrets' to" + echo " uncomment both blocks in the generated values-secret file" echo " - See airgap/DEPLOY-RUNBOOK.md for the full deployment procedure" echo echo " Security policies:" diff --git a/values-secret.yaml.template b/values-secret.yaml.template index 2d2a0ab7..6f3fa2bb 100644 --- a/values-secret.yaml.template +++ b/values-secret.yaml.template @@ -183,10 +183,17 @@ secrets: # path: ~/.coco-pattern/cosign-key-0.pub - # PCR measurements for attestation. - # Azure: run ./scripts/get-pcr.sh to extract from peer-pod image - # Bare metal: manually collect from running confidential VM - # See docs/pcr-reference-values-bare-metal.md for collection procedure + # PCR measurements for attestation (Azure) and firmware reference values + # (bare metal / Intel TDX / AMD SEV-SNP) are both enabled by default so the + # SAME values-secret file works unmodified on either topology. + # Azure: make collect-azure-refvals -> ~/.coco-pattern/measurements.json + # Bare metal: make collect-firmware-refvals -> ~/.coco-pattern/firmware-reference-values.json + # See docs/firmware-reference-values.md and docs/pcr-reference-values-bare-metal.md + # collect-firmware-refvals.sh (and gen-secrets.sh as a first-run safety net) + # automatically create an empty '{}' placeholder for whichever of these two + # files you are NOT using, so 'make load-secrets' never fails with a + # missing-file error regardless of platform. Real collected data always + # overwrites the placeholder for the platform you actually run. - name: pcrStash vaultPrefixes: - hub @@ -194,10 +201,6 @@ secrets: - name: json path: ~/.coco-pattern/measurements.json - # Firmware reference values for bare metal attestation. - # Required for bare metal deployments (Intel TDX / AMD SEV-SNP). - # Collect by running: make collect-firmware-refvals - # See docs/firmware-reference-values.md for detailed workflow. - name: firmwareReferenceValues vaultPrefixes: - hub @@ -207,18 +210,30 @@ secrets: # =================================================================== - # Optional - Private Registry CA Certificate + # Optional - Disconnected/Airgap Mirror Registry Configuration # =================================================================== + # Everything between the AIRGAP-MIRROR-SECRETS markers below (this block + # plus the bootstrap_secrets block near the end of this file) only applies + # to airgap (disconnected mirror) deployments and is commented out by + # default so connected deployments (Azure, connected bare metal) don't hit + # 'make load-secrets' failures for files that don't exist. + # + # For airgap deployments, run 'make cache-registry-ca' and + # 'make gen-mirror-helm-secret' first, then run: + # make enable-airgap-secrets + # which uncomments both blocks automatically (see airgap/DEPLOY-RUNBOOK.md). # Private registry CA certificate chain (PEM format). # Copy your registry CA chain to the path above before running 'make load-secrets'. # Use 'make cache-registry-ca' for APAC lab Quay. - - name: registryCaCert - vaultPrefixes: - - hub - fields: - - name: pem - path: ~/.coco-pattern/mirror-registry-ca-cert.pem + # AIRGAP-MIRROR-SECRETS-START + #- name: registryCaCert + # vaultPrefixes: + # - hub + # fields: + # - name: pem + # path: ~/.coco-pattern/mirror-registry-ca-cert.pem + # AIRGAP-MIRROR-SECRETS-END # =================================================================== # Optional - SSH Debug Access @@ -245,12 +260,13 @@ secrets: # Collected via: make collect-dcap-collateral FMSPC= INTEL_PCS_API_KEY= # Loaded into Vault, delivered to KBS via ESO + kbsLocalCertCacheSpec # Refresh when collateral expires (~30-90 days) - - name: tdxCollateral - vaultPrefixes: - - hub - fields: - - name: platform_collaterals.json - path: ~/.coco-pattern/dcap-offline/platform_collaterals.json + # Uncomment after running 'make collect-dcap-collateral': + #- name: tdxCollateral + # vaultPrefixes: + # - hub + # fields: + # - name: platform_collaterals.json + # path: ~/.coco-pattern/dcap-offline/platform_collaterals.json # =================================================================== # Optional - Bare Metal AMD SEV-SNP (VCEK Certificates) @@ -273,30 +289,37 @@ secrets: # =================================================================== # Bootstrap Secrets (Phase 23 DEL-2) — ArgoCD OCI Helm registry auth # =================================================================== +# Airgap (disconnected mirror) deployments only. Commented out by default — +# see the "Disconnected/Airgap Mirror Registry Configuration" note above. # Pre-seeds ArgoCD with credentials to pull OCI Helm charts from mirror-registry # before Vault is initialized. Loaded via: make load-bootstrap # Secret name: mirror-registry-helm-oci # Registry: MIRROR_REGISTRY_HOST:PORT (mirror-registry — sole airgap chart target) # Credentials: mirror-registry init user; password in ~/.coco-pattern/mirror-registry-password # -bootstrap_secrets: - - name: mirror-registry-helm-oci - targetNamespaces: - - vp-gitops - labels: - argocd.argoproj.io/secret-type: repository - fields: - - name: type - value: helm - - name: enableOCI - value: "true" - - name: url - value: MIRROR_REGISTRY_HOST:PORT/validatedpatterns - - name: name - value: mirror-registry-charts - - name: username - value: init - - name: password - path: ~/.coco-pattern/mirror-registry-password - onMissingValue: error +# Uncommented automatically by 'make enable-airgap-secrets' (see +# airgap/DEPLOY-RUNBOOK.md), which uncomments this block together with +# registryCaCert above. +# AIRGAP-MIRROR-SECRETS-START +#bootstrap_secrets: +# - name: mirror-registry-helm-oci +# targetNamespaces: +# - vp-gitops +# labels: +# argocd.argoproj.io/secret-type: repository +# fields: +# - name: type +# value: helm +# - name: enableOCI +# value: "true" +# - name: url +# value: MIRROR_REGISTRY_HOST:PORT/validatedpatterns +# - name: name +# value: mirror-registry-charts +# - name: username +# value: init +# - name: password +# path: ~/.coco-pattern/mirror-registry-password +# onMissingValue: error +# AIRGAP-MIRROR-SECRETS-END