diff --git a/ci/Dockerfile b/ci/Dockerfile index ea534d6e..2a02b586 100644 --- a/ci/Dockerfile +++ b/ci/Dockerfile @@ -1,12 +1,11 @@ FROM alpine:3.20 -# Rebuild 2026-04-19 — previous :latest index referenced missing blobs (404 on 98f718c8 / 27d5ab83) - # Pin versions to match CI requirements ARG TERRAFORM_VERSION=1.5.7 ARG TERRAGRUNT_VERSION=0.99.4 ARG SOPS_VERSION=3.9.4 ARG KUBECTL_VERSION=1.34.0 +ARG VAULT_VERSION=1.18.1 # Install system packages (single layer) RUN apk add --no-cache \ @@ -36,6 +35,16 @@ RUN curl -fsSL "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/amd64/ku -o /usr/local/bin/kubectl \ && chmod +x /usr/local/bin/kubectl +# Vault CLI — required by scripts/tg for Tier 1 stack PG credential reads +# and Tier 0 advisory locks. Pinned to server version (1.18.1). Without this +# the CI pipeline surfaces the misleading "Cannot read PG credentials" error +# because scripts/tg swallows stderr ("vault: not found"). +RUN curl -fsSL "https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip" \ + -o /tmp/vault.zip \ + && unzip /tmp/vault.zip -d /usr/local/bin/ \ + && rm /tmp/vault.zip \ + && vault version + # Provider cache directory (shared across stacks) ENV TF_PLUGIN_CACHE_DIR=/tmp/terraform-plugin-cache ENV TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE=1 diff --git a/scripts/tg b/scripts/tg index 8cb38e20..15cea845 100755 --- a/scripts/tg +++ b/scripts/tg @@ -72,12 +72,23 @@ if [ -n "$STACK_NAME" ]; then else # Tier 1: PG backend — fetch credentials from Vault if [ -z "${PG_CONN_STR:-}" ]; then - PG_CREDS=$(vault read -format=json database/static-creds/pg-terraform-state 2>/dev/null) || { - echo "ERROR: Cannot read PG credentials from Vault. Run: vault login -method=oidc" >&2 + # Pre-flight: vault CLI must be available. Previously CI failed with a + # misleading "Cannot read PG credentials" message because the Alpine CI + # image lacked the vault binary — the 2>/dev/null below swallowed the + # real "vault: not found" error. Fail fast with a clear message instead. + if ! command -v vault >/dev/null 2>&1; then + echo "ERROR: vault CLI not found on PATH. Install it or use an image that includes it (ci/Dockerfile)." >&2 + exit 1 + fi + VAULT_OUT=$(vault read -format=json database/static-creds/pg-terraform-state 2>&1) || { + echo "ERROR: Cannot read PG credentials from Vault. Vault output follows:" >&2 + echo "$VAULT_OUT" >&2 + echo "" >&2 + echo "Hint: humans run 'vault login -method=oidc'; CI auths via K8s SA (role=ci)." >&2 exit 1 } - PG_USER=$(echo "$PG_CREDS" | jq -r .data.username) - PG_PASS=$(echo "$PG_CREDS" | jq -r .data.password) + PG_USER=$(echo "$VAULT_OUT" | jq -r .data.username) + PG_PASS=$(echo "$VAULT_OUT" | jq -r .data.password) export PG_CONN_STR="postgres://${PG_USER}:${PG_PASS}@10.0.20.200:5432/terraform_state?sslmode=disable" fi fi