Skip to content

Instantly share code, notes, and snippets.

@cwood
Created October 29, 2025 20:38
Show Gist options
  • Save cwood/aaa93db6e3e91bf173d47b75bb3422b2 to your computer and use it in GitHub Desktop.
Save cwood/aaa93db6e3e91bf173d47b75bb3422b2 to your computer and use it in GitHub Desktop.
ECS Secrets Share
┌─────────────────────────────────────────────────────────────────────────────┐
│ DEPLOYMENT FLOW (Deploy Time) │
└─────────────────────────────────────────────────────────────────────────────┘
SOURCE ACCOUNT (Ephemeral Env) TARGET ACCOUNT (Production)
┌──────────────────────────┐ ┌──────────────────────────┐
│ │ │ │
│ 1. User runs deploy │ │ │
│ ephemeral deploy │ │ │
│ │ │ │
└────────────┬─────────────┘ └──────────────────────────┘
┌────────────▼─────────────┐
│ 2. Parse alma.sd.yaml │
│ - inherit-from │
│ - role-arn │
└────────────┬─────────────┘
┌────────────▼─────────────┐ ┌──────────────────────────┐
│ 3. Assume Role │───────STS────▶ │ EphemeralSecretsAccess │
│ (via role-arn) │ AssumeRole │ Role (trust policy │
│ │◀───temp creds──│ allows source account) │
└────────────┬─────────────┘ └──────────────────────────┘
┌────────────▼─────────────┐ ┌──────────────────────────┐
│ 4. Fetch Secrets │ │ │
│ (Pulumi Provider │─────List──────▶│ production/myapp/* │
│ with assumed role) │ Secrets │ (Secrets Manager) │
│ │◀──Secret ARNs──│ │
└────────────┬─────────────┘ └──────────────────────────┘
┌────────────▼─────────────┐
│ 5. Create IAM Resources │
│ - Execution Role │
│ - Task Role │
│ execution-role ARN │
│ = arn:...:role/ │
│ pr-123-ecs-exec... │
└────────────┬─────────────┘
┌────────────▼─────────────┐
│ 6. Create Execution │
│ Role Policy │
│ Allow GetSecretValue │
│ on cross-acct ARNs │
└────────────┬─────────────┘
│ ┌──────────────────────────┐
┌────────────▼─────────────┐ │ Each Secret │
│ 7. Grant Cross-Account │ │ ┌────────────────────┐ │
│ Access (AWS SDK) │────Assume─────▶│ │ Resource Policy: │ │
│ │ Role │ │ { │ │
│ For each secret ARN: │────Put────────▶│ │ Principal: { │ │
│ - GetResourcePolicy │ Resource │ │ AWS: [ │ │
│ - Merge principals │ Policy │ │ pr-123-exec │ │
│ - PutResourcePolicy │ │ │ ] │ │
│ │ │ │ } │ │
│ │ │ │ Action: │ │
│ │ │ │ GetSecretValue │ │
│ │ │ │ } │ │
└──────────────────────────┘ │ └────────────────────┘ │
└──────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ RUNTIME FLOW (Container Startup) │
└─────────────────────────────────────────────────────────────────────────────┘
SOURCE ACCOUNT TARGET ACCOUNT
┌──────────────────────────┐ ┌──────────────────────────┐
│ ECS Service │ │ │
│ ┌────────────────────┐ │ │ │
│ │ ECS Control Plane │ │ │ │
│ │ (uses Execution │ │────Get────────▶│ production/myapp/* │
│ │ Role) │ │ Secret │ (checks resource policy)│
│ │ │ │ Value │ │
│ │ ✓ Has identity- │ │◀───Secret──────│ ✓ Allows pr-123-exec │
│ │ based policy │ │ Value │ role │
│ └─────────┬──────────┘ │ │ │
│ │ │ └──────────────────────────┘
│ │ inject │
│ │ env vars │
│ ┌─────────▼──────────┐ │
│ │ App Container │ │
│ │ (Task Role) │ │
│ │ │ │
│ │ DATABASE_URL=... │ │
│ │ API_KEY=... │ │
│ └────────────────────┘ │
└──────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ DESTROY FLOW (Cleanup) │
└─────────────────────────────────────────────────────────────────────────────┘
SOURCE ACCOUNT TARGET ACCOUNT
┌──────────────────────────┐
│ 1. User runs destroy │
│ ephemeral destroy │
└────────────┬─────────────┘
┌────────────▼─────────────┐
│ 2. Get Stack Outputs │
│ - secret ARNs │
│ - execution role ARN │
│ - cross-acct role │
└────────────┬─────────────┘
┌────────────▼─────────────┐ ┌──────────────────────────┐
│ 3. Revoke Cross-Acct │ │ Each Secret │
│ Access (best-effort) │────Assume─────▶│ ┌────────────────────┐ │
│ │ Role │ │ Resource Policy: │ │
│ For each secret ARN: │────Put────────▶│ │ Remove pr-123-exec │ │
│ - GetResourcePolicy │ Resource │ │ from principals │ │
│ - Remove exec role │ Policy │ │ │ │
│ - PutResourcePolicy │ │ │ (or delete policy │ │
│ (log on failure) │ │ │ if last principal)│ │
└────────────┬─────────────┘ │ └────────────────────┘ │
│ └──────────────────────────┘
┌────────────▼─────────────┐
│ 4. Pulumi Destroy │
│ (removes all infra) │
│ - Execution Role │
│ - Task Role │
│ - ECS Service │
└──────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ KEY PERMISSIONS │
└─────────────────────────────────────────────────────────────────────────────┘
SOURCE ACCOUNT:
┌────────────────────────────────────────────────────────────────┐
│ GitHub Actions Role / Deployment User │
│ - sts:AssumeRole on TARGET_ACCOUNT:role/EphemeralSecretsAccess│
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ ECS Execution Role (pr-123-ecs-execution-role) │
│ - secretsmanager:GetSecretValue on TARGET_ACCOUNT secrets │
└────────────────────────────────────────────────────────────────┘
TARGET ACCOUNT:
┌────────────────────────────────────────────────────────────────┐
│ EphemeralSecretsAccess Role │
│ Trust Policy: Allow SOURCE_ACCOUNT:root to AssumeRole │
│ Permissions: │
│ - secretsmanager:GetSecretValue │
│ - secretsmanager:ListSecrets │
│ - secretsmanager:GetResourcePolicy │
│ - secretsmanager:PutResourcePolicy │
│ - secretsmanager:DeleteResourcePolicy │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ Each Secret Resource Policy (managed by tool) │
│ Principal: arn:aws:iam::SOURCE:role/pr-123-ecs-execution-role│
│ Action: secretsmanager:GetSecretValue │
└────────────────────────────────────────────────────────────────┘
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment