#!/usr/bin/env bash # put-config.sh — out-of-band populator for the open-swe config store. # # T11 (CDK) creates the RESOURCE SHELLS: # - 28 Secrets Manager secrets open-swe-/ (value-LESS shells) # - the IaC-managed SSM params /open-swe-/ (real values, owned in CDK) # This script sets the values that CANNOT live in IaC — every secret value, plus # the out-of-band SSM params (operationally-variable / env-specific-unknown). Run # it AFTER `cdk deploy open-swe-` and BEFORE the EC2/T12 box first boots, so # fetch-config.sh finds every REQUIRED var populated and never writes a partial .env. # # The secret list below mirrors config-store.ts SECRET_VARS (28 names — the # inventory's "29" double-counted JUDGE_ANTHROPIC_BASE_URL, which is config # (SSM), not a secret). Keep the two lists in lockstep. # # SAFETY: # - NO real secret values live in this file — every secret is a placeholder. # Replace inline at run time, pipe from a vault, or export the # matching OPENSWE_PUT_ env var; NEVER commit real values. # - It does NOT touch the IaC-managed SSM params (SANDBOX_TYPE, DEFAULT_REPO_OWNER, # ALLOWED_GITHUB_ORGS, DEFAULT_REPO_NAME, DASHBOARD_*_URL/ORIGINS, LLM_MODEL_ID) # — CDK owns those; setting them here would cause drift. # - Secrets go to Secrets Manager; the box's instance role grants read on # open-swe-/* and /open-swe-/* (no kms:Decrypt — AWS-managed keys). # # Idempotent: put-secret-value adds a new AWSCURRENT version; put-parameter # --overwrite updates in place. set -euo pipefail ENV="${1:-}" case "$ENV" in dev | prod) ;; *) echo "usage: put-config.sh " >&2 exit 2 ;; esac REGION="${AWS_REGION:-${AWS_DEFAULT_REGION:-us-east-1}}" SECRET_PREFIX="open-swe-${ENV}/" SSM_PREFIX="/open-swe-${ENV}/" command -v aws >/dev/null 2>&1 || { echo "put-config: 'aws' not found on PATH" >&2; exit 3; } # --- helpers ----------------------------------------------------------------- # put_secret VAR : set the value of an EXISTING secret shell open-swe-/VAR. # Resolution order for the value: $OPENSWE_PUT_ env var, else the literal # placeholder (which aborts so an unset secret is never silently shipped). put_secret() { local var="$1" local override_name="OPENSWE_PUT_${var}" local value="${!override_name:-}" if [ "$value" = "" ]; then echo "put-config[$ENV]: SKIP secret ${var} (no value; set ${override_name} or edit inline)" >&2 return 0 fi aws secretsmanager put-secret-value \ --secret-id "${SECRET_PREFIX}${var}" \ --secret-string "$value" \ --region "$REGION" \ --no-cli-pager >/dev/null echo "put-config[$ENV]: set secret ${var}" } # put_param VAR [TYPE] : create/update an out-of-band SSM param /open-swe-/VAR. # TYPE defaults to String; pass SecureString for anything sensitive-but-not-a-secret. put_param() { local var="$1" type="${2:-String}" local override_name="OPENSWE_PUT_${var}" local value="${!override_name:-}" if [ "$value" = "" ]; then echo "put-config[$ENV]: SKIP param ${var} (no value; set ${override_name} or edit inline)" >&2 return 0 fi aws ssm put-parameter \ --name "${SSM_PREFIX}${var}" \ --value "$value" \ --type "$type" \ --overwrite \ --region "$REGION" \ --no-cli-pager >/dev/null echo "put-config[$ENV]: set param ${var} (${type})" } # --- 1) Secrets (open-swe-/) — 28 shells from config-store.ts ------- # REQUIRED at boot (fetch-config fail-fast): DASHBOARD_JWT_SECRET, # TOKEN_ENCRYPTION_KEY, GITHUB_APP_PRIVATE_KEY/CLIENT_SECRET, the active provider # key(s) (ANTHROPIC_API_KEY + OPENAI_API_KEY by default), LANGSMITH_API_KEY_PROD, # and (prod) GITHUB_WEBHOOK_SECRET + SLACK_SIGNING_SECRET. put_secret ANTHROPIC_API_KEY # REQUIRED — primary builder provider key put_secret OPENAI_API_KEY # REQUIRED — default reviewer provider key put_secret DASHBOARD_JWT_SECRET # REQUIRED — dashboard session JWT signing put_secret TOKEN_ENCRYPTION_KEY # REQUIRED — Fernet key(s) for GH-token crypto put_secret GITHUB_APP_PRIVATE_KEY # REQUIRED — GitHub App PEM (multiline; quote it) put_secret GITHUB_APP_CLIENT_SECRET # REQUIRED — dashboard OAuth login put_secret LANGSMITH_API_KEY_PROD # REQUIRED (langsmith sandbox) — prod key put_secret GITHUB_WEBHOOK_SECRET # prod-REQUIRED — GitHub webhook signature put_secret SLACK_SIGNING_SECRET # prod-REQUIRED — Slack webhook signature put_secret LINEAR_WEBHOOK_SECRET # required only when Linear is wired # Optional / conditional secrets — set the ones this deployment actually uses. put_secret CORRIDOR_API_TOKEN # optional — Corridor MCP put_secret CORRIDOR_MCP_TOKEN # optional — Corridor MCP (alt name) put_secret CORRIDOR_TOKEN # optional — Corridor MCP (alt name) put_secret DAYTONA_API_KEY # only if SANDBOX_TYPE=daytona put_secret EXA_API_KEY # optional — Exa web search put_secret FIREWORKS_API_KEY # only if a fireworks: model is used put_secret GITHUB_PAT # optional — PAT fallback put_secret GOOGLE_API_KEY # only if a google_genai: model is used put_secret GROQ_API_KEY # only if a groq: model is used put_secret JUDGE_ANTHROPIC_API_KEY # optional — eval judge (falls back to ANTHROPIC) put_secret LANGSMITH_API_KEY # optional — LangSmith (dev) put_secret LANGCHAIN_API_KEY # optional — LangSmith alt name put_secret LINEAR_API_KEY # optional — Linear API put_secret RUNLOOP_API_KEY # only if SANDBOX_TYPE=runloop put_secret SLACK_BOT_TOKEN # optional — Slack bot token put_secret SLACK_CLIENT_SECRET # optional — Slack OAuth put_secret USER_ID_API_KEY_MAP # optional — JSON map user id -> API key (per-user auth) put_secret X_SERVICE_AUTH_JWT_SECRET # optional — service-auth JWT # --- 2) Out-of-band SSM params (/open-swe-/) ------------------------ # These are NOT created by CDK (operationally-variable / env-specific-unknown). # put_param creates them on first run. put_param DEFAULT_SANDBOX_SNAPSHOT_ID # REQUIRED (langsmith) — changes every rebuild put_param GITHUB_APP_ID # REQUIRED — GitHub App numeric id put_param GITHUB_APP_INSTALLATION_ID # REQUIRED — GitHub App installation id put_param GITHUB_APP_CLIENT_ID # REQUIRED — dashboard OAuth client id put_param GITHUB_OAUTH_PROVIDER_ID # GitHub OAuth provider id put_param LANGSMITH_TENANT_ID_PROD # LangSmith prod tenant id put_param LANGSMITH_URL_PROD # LangSmith prod URL put_param LANGSMITH_ENDPOINT # LangSmith API endpoint put_param LANGSMITH_ENDPOINT_PROD # LangSmith prod API endpoint put_param LANGSMITH_HOST_API_URL # LangSmith host API URL put_param LANGGRAPH_URL # LangGraph server URL put_param LANGGRAPH_URL_PROD # LangGraph server URL (prod) put_param LANGCHAIN_REVISION_ID # LangChain revision id put_param SLACK_CLIENT_ID # Slack OAuth client id put_param SLACK_TEAM_ID # Slack workspace/team id put_param SLACK_BOT_USER_ID # Slack bot user id put_param SLACK_BOT_USERNAME # Slack bot username put_param SLACK_REPO_OWNER # Slack default repo owner put_param SLACK_REPO_NAME # Slack default repo name put_param CONFIGURED_ADMINS # dashboard admin GitHub logins (comma list) put_param OBSERVABILITY_AUTHORIZED_EMAILS # observability allowlist (comma list) put_param PUBLIC_REPO_ORG_GATE # public-repo trigger gate (org name; empty=off) put_param ALLOWED_GITHUB_REPOS # extra repo allowlist (comma list) put_param LLM_FALLBACK_MODEL_ID # optional — model fallback id put_param DATADOG_MCP_TOOLSETS # optional — Datadog MCP toolsets put_param NOTION_MCP_CLIENT_NAME # optional — Notion MCP client name put_param API_STANDARDS_SKILL_HANDLE # optional — API standards skill handle put_param REPO_SNAPSHOT_BASE_IMAGE # optional — repo snapshot base image put_param REPO_SNAPSHOT_BUILD_TIMEOUT_SECONDS # optional — snapshot build timeout put_param REPO_SNAPSHOT_STALE_BUILD_SECONDS # optional — snapshot stale threshold echo "put-config[$ENV]: done. Verify with fetch-config.sh ${ENV} before first boot."