diff --git a/deploy/render-secrets.sh b/deploy/render-secrets.sh index 7d2d421..43f0cc9 100755 --- a/deploy/render-secrets.sh +++ b/deploy/render-secrets.sh @@ -36,24 +36,40 @@ render_thermograph_secrets() { fi echo "==> Rendering /etc/thermograph.env from deploy/secrets (common + ${env_name})" + # The age private key is root-owned (0400). Read it directly if we can, else via + # sudo into SOPS_AGE_KEY — so the key never has to be readable by the deploy user. + # (The render needs sudo to write /etc/thermograph.env below anyway.) + local key_env=() + if [ -r "$key" ]; then + key_env=("SOPS_AGE_KEY_FILE=$key") + else + local keymat; keymat=$(sudo cat "$key" 2>/dev/null | grep '^AGE-SECRET-KEY-' || true) + [ -n "$keymat" ] || { echo "!! cannot read age key at $key (need sudo)" >&2; return 1; } + key_env=("SOPS_AGE_KEY=$keymat") + fi local tmp; tmp=$(mktemp) : > "$tmp" # set -e in the caller makes a decrypt failure fatal here (no partial env). common # first, host second, so a host value overrides a shared one (last-wins). if [ -f "$repo/deploy/secrets/common.yaml" ]; then - SOPS_AGE_KEY_FILE="$key" sops -d --input-type yaml --output-type dotenv \ + env "${key_env[@]}" sops -d --input-type yaml --output-type dotenv \ "$repo/deploy/secrets/common.yaml" >> "$tmp" fi - SOPS_AGE_KEY_FILE="$key" sops -d --input-type yaml --output-type dotenv \ + env "${key_env[@]}" sops -d --input-type yaml --output-type dotenv \ "$repo/deploy/secrets/${env_name}.yaml" >> "$tmp" - # /etc/thermograph.env is in the root-owned /etc: write it directly if we can, else - # via sudo. Fail loudly rather than deploy against stale secrets. - if install -m 0640 "$tmp" /etc/thermograph.env 2>/dev/null; then : + # Write /etc/thermograph.env. Prefer an in-place write when the existing file is + # writable by us (e.g. a group-writable 0660 root: on a box whose CI + # deploy user isn't root and has no broad sudo — beta's `deploy`), since that needs + # only file write, not /etc dir write or sudo. Else install; else sudo install (a + # root/agent deploy). Fail loudly rather than deploy against stale secrets. + if [ -f /etc/thermograph.env ] && [ -w /etc/thermograph.env ]; then + cat "$tmp" > /etc/thermograph.env + elif install -m 0640 "$tmp" /etc/thermograph.env 2>/dev/null; then : elif sudo install -m 0640 "$tmp" /etc/thermograph.env 2>/dev/null; then : else rm -f "$tmp" - echo "!! cannot write /etc/thermograph.env (need write access or passwordless sudo)" >&2 + echo "!! cannot write /etc/thermograph.env (need file write access or passwordless sudo)" >&2 return 1 fi rm -f "$tmp"