From f4e88b094c3fc952717e502f4b2725dc25466867 Mon Sep 17 00:00:00 2001 From: danielntmd Date: Fri, 20 Feb 2026 18:23:55 +0000 Subject: [PATCH] feat(spartan): enable admin API key auth for next-scenario network Generates a fresh random admin API key on each nightly scenario deploy, stores the SHA-256 hash on validator pods via AZTEC_ADMIN_API_KEY_HASH, and makes the raw key available to the test runner via a K8s Secret. The raw key is never logged. - deploy_network.sh: generate key + hash with openssl/sha256sum, store raw key as 'aztec-admin-api-key' K8s Secret, pass hash to Terraform - variables.tf: add ADMIN_API_KEY_HASH (defaults to , keeping auth disabled for all other environments) - main.tf: set validator.node.adminApiKeyHash on all validator releases; empty string is falsy in Helm so other envs keep disableAdminApiKey=true - bootstrap.sh: read raw key from K8s Secret before tests run, export as AZTEC_ADMIN_API_KEY - config.ts: add AZTEC_ADMIN_API_KEY to test config schema - nodes.ts: pass key to createAztecNodeAdminClient as x-api-key header --- spartan/bootstrap.sh | 6 ++++++ spartan/scripts/deploy_network.sh | 15 +++++++++++++++ spartan/terraform/deploy-aztec-infra/main.tf | 1 + spartan/terraform/deploy-aztec-infra/variables.tf | 6 ++++++ .../end-to-end/src/spartan/utils/config.ts | 1 + .../end-to-end/src/spartan/utils/nodes.ts | 2 +- 6 files changed, 30 insertions(+), 1 deletion(-) diff --git a/spartan/bootstrap.sh b/spartan/bootstrap.sh index d769085d45ad..45e2144182df 100755 --- a/spartan/bootstrap.sh +++ b/spartan/bootstrap.sh @@ -99,6 +99,12 @@ function run_network_tests { source_network_env "$env_file" gcp_auth export SCENARIO_TESTS=1 + # Retrieve the admin API key stored as a K8s Secret during deployment. + # Exported so the test runner can authenticate against the admin RPC endpoint. + export AZTEC_ADMIN_API_KEY + AZTEC_ADMIN_API_KEY=$(kubectl get secret aztec-admin-api-key \ + --namespace "$NAMESPACE" \ + -o jsonpath='{.data.key}' 2>/dev/null | base64 -d 2>/dev/null || true) local failed=() for test_file in "$@"; do echo_header "Running $test_file" diff --git a/spartan/scripts/deploy_network.sh b/spartan/scripts/deploy_network.sh index 6c397c9fd1d7..985b5fd9a625 100755 --- a/spartan/scripts/deploy_network.sh +++ b/spartan/scripts/deploy_network.sh @@ -459,6 +459,20 @@ else fi +# ------------------------------- +# Generate admin API key +# ------------------------------- +# Generate a fresh key on every deploy; the hash goes to validators and the +# raw key is stored as a K8s Secret for the test runner to retrieve later. +# The raw key is never logged. +ADMIN_API_KEY=$(openssl rand -hex 32) +ADMIN_API_KEY_HASH=$(printf '%s' "$ADMIN_API_KEY" | sha256sum | cut -d' ' -f1) +kubectl create secret generic aztec-admin-api-key \ + --from-literal=key="$ADMIN_API_KEY" \ + --namespace "${NAMESPACE}" \ + --dry-run=client -o yaml | kubectl apply -f - +unset ADMIN_API_KEY + # ------------------------------- # Deploy Aztec infra # ------------------------------- @@ -612,6 +626,7 @@ PROVER_AGENT_PROOF_TYPES = ${PROVER_AGENT_PROOF_TYPES:-[]} DEBUG_FORCE_TX_PROOF_VERIFICATION = ${DEBUG_FORCE_TX_PROOF_VERIFICATION:-false} WAIT_FOR_PROVER_DEPLOY = ${WAIT_FOR_PROVER_DEPLOY:-null} +ADMIN_API_KEY_HASH = "${ADMIN_API_KEY_HASH}" EOF k8s_denoise "tf_run "${DEPLOY_AZTEC_INFRA_DIR}" "${DESTROY_AZTEC_INFRA}" "${CREATE_AZTEC_INFRA}"" diff --git a/spartan/terraform/deploy-aztec-infra/main.tf b/spartan/terraform/deploy-aztec-infra/main.tf index 14194ae4a5cf..864af358487f 100644 --- a/spartan/terraform/deploy-aztec-infra/main.tf +++ b/spartan/terraform/deploy-aztec-infra/main.tf @@ -223,6 +223,7 @@ locals { "validator.node.env.WS_NUM_HISTORIC_CHECKPOINTS" = var.WS_NUM_HISTORIC_CHECKPOINTS "validator.node.env.TX_COLLECTION_FILE_STORE_URLS" = var.TX_COLLECTION_FILE_STORE_URLS "validator.node.env.SEQ_SKIP_CHECKPOINT_PUBLISH_PERCENT" = var.SEQ_SKIP_CHECKPOINT_PUBLISH_PERCENT + "validator.node.adminApiKeyHash" = var.ADMIN_API_KEY_HASH } # Note: nonsensitive() is required here because helm_releases is used in for_each, diff --git a/spartan/terraform/deploy-aztec-infra/variables.tf b/spartan/terraform/deploy-aztec-infra/variables.tf index 790bf238a9ff..fadca17716b5 100644 --- a/spartan/terraform/deploy-aztec-infra/variables.tf +++ b/spartan/terraform/deploy-aztec-infra/variables.tf @@ -229,6 +229,12 @@ variable "VALIDATOR_HA_REPLICAS" { default = 0 } +variable "ADMIN_API_KEY_HASH" { + description = "SHA-256 hex hash of the admin API key. When set, enables admin API authentication on validator nodes. Leave empty to disable admin auth (default)." + type = string + default = "" +} + variable "PROVER_MNEMONIC" { description = "The prover mnemonic" type = string diff --git a/yarn-project/end-to-end/src/spartan/utils/config.ts b/yarn-project/end-to-end/src/spartan/utils/config.ts index 3794cba69156..f4dd9e885205 100644 --- a/yarn-project/end-to-end/src/spartan/utils/config.ts +++ b/yarn-project/end-to-end/src/spartan/utils/config.ts @@ -16,6 +16,7 @@ const testConfigSchema = z.object({ AZTEC_PROOF_SUBMISSION_WINDOW: z.coerce.number().optional().default(5), AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET: z.coerce.number().optional().default(2), FUNDING_PRIVATE_KEY: z.string().optional(), + AZTEC_ADMIN_API_KEY: z.string().optional(), }); export type TestConfig = z.infer; diff --git a/yarn-project/end-to-end/src/spartan/utils/nodes.ts b/yarn-project/end-to-end/src/spartan/utils/nodes.ts index 0a3166395afd..e452a434b636 100644 --- a/yarn-project/end-to-end/src/spartan/utils/nodes.ts +++ b/yarn-project/end-to-end/src/spartan/utils/nodes.ts @@ -173,7 +173,7 @@ export async function withSequencersAdmin(env: TestConfig, fn: (node: AztecNo if (statusRes.status !== 200) { throw new Error(`Admin endpoint returned status ${statusRes.status}`); } - const client = createAztecNodeAdminClient(url); + const client = createAztecNodeAdminClient(url, {}, undefined, env.AZTEC_ADMIN_API_KEY); return { result: await fn(client), process }; } catch (err) { // Kill the port-forward before retrying