fix: paginate batch-get-secret-value in fetch-config (secrets dropped past page 1) (#24)

fetch-config materialized only the FIRST page of Secrets Manager results: the AWS CLI
does NOT auto-paginate batch-get-secret-value (the script's comment claiming it does
was wrong; --no-cli-pager only disables the output pager, not API pagination). With 28
secret shells under open-swe-<env>/ the first page returned ~10 items, stranding the
rest on later pages. Required secrets that landed past page 1 (DASHBOARD_JWT_SECRET,
TOKEN_ENCRYPTION_KEY, LANGSMITH_API_KEY_PROD) were silently dropped, tripping the
FAIL-FAST 'missing required var' guard and crash-looping open-swe.service.

Follow NextToken across pages (new batch_get_secrets_tsv helper). Verified against the
live open-swe-dev secrets: now loads all 5 populated secrets (was 2). Same per-record
base64 / exact-prefix / accept_var / emit_var hardening — only the page loop is new.
This commit is contained in:
Adam Moussa 2026-06-26 19:55:01 -04:00 • committed by GitHub
parent cdcb6625b9
commit a2877d46ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -149,7 +149,31 @@ done < <(jq -r '.Parameters[] | (.Name|@base64) + "\t" + (.Value|@base64)' <<<"$
log "loaded ${ssm_count} config param(s) from SSM"
# 2) Secrets Manager (sensitive values). batch-get-secret-value filters by name
# prefix and auto-paginates; one secret per env var, SecretString = the value.
# prefix; one secret per env var, SecretString = the value. The AWS CLI does NOT
# auto-paginate this operation (unlike list/get-parameters-by-path), and a single
# response caps well under the full set (~10 items/page) — so we MUST follow
# NextToken ourselves or secrets on later pages are silently dropped (they then
# surface as FAIL-FAST "missing required var"). `--no-cli-pager` only disables the
# OUTPUT pager, not API pagination. Each page's records are base64(name<TAB>value).
batch_get_secrets_tsv() {
local token="" page
while :; do
if [ -n "$token" ]; then
page="$(aws secretsmanager batch-get-secret-value \
--filters "Key=name,Values=${SECRET_PREFIX}" \
--region "$REGION" --no-cli-pager --output json --next-token "$token")"
else
page="$(aws secretsmanager batch-get-secret-value \
--filters "Key=name,Values=${SECRET_PREFIX}" \
--region "$REGION" --no-cli-pager --output json)"
fi
printf '%s' "$page" \
| jq -r '.SecretValues[] | select(.SecretString != null) | (.Name|@base64) + "\t" + (.SecretString|@base64)'
token="$(printf '%s' "$page" | jq -r '.NextToken // empty')"
[ -n "$token" ] || break
done
}
log "reading secrets under ${SECRET_PREFIX} ..."
secret_count=0
while IFS=$'\t' read -r nb vb; do
@ -164,14 +188,7 @@ while IFS=$'\t' read -r nb vb; do
[ -n "$key" ] || continue
accept_var "$key" "$value" "Secrets"
secret_count=$((secret_count + 1))
done < <(
aws secretsmanager batch-get-secret-value \
--filters "Key=name,Values=${SECRET_PREFIX}" \
--region "$REGION" \
--no-cli-pager \
--output json \
| jq -r '.SecretValues[] | select(.SecretString != null) | (.Name|@base64) + "\t" + (.SecretString|@base64)'
)
done < <(batch_get_secrets_tsv)
log "loaded ${secret_count} secret(s) from Secrets Manager"
# --- Sea Haven DEFAULT_REPO_OWNER hard pin -----------------------------------