open-swe/infra/lib/open-swe-iam-stack.ts

39 lines
1.8 KiB
TypeScript
Raw Normal View History

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import { GithubDeployRoles } from "./constructs/github-deploy-roles";
/**
* Account-level IAM stack: the per-ENV GitHub OIDC deploy roles
* (githubdeploy-open-swe-{infra,app}-{dev,prod} — four roles).
*
* T5 OSWE-IAC-01/02 fix: roles are split per env with env-scoped OIDC trust, so
* a dev-branch token cannot reach prod (prod roles require the GitHub
* `prod` Environment manual-approval gate). They live in this dedicated stack
* rather than the env stacks because IAM roles are global and this stack ships
* FIRST (TODO.md BLOCK#3): the infra OIDC roles + the repo deploy-role-ARN
* secrets must exist before any infra/secrets CI step. Synth-only until the
* Phase-1 security gate (T4 + T5) clears (T6).
*/
export class OpenSweIamStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const dev = new GithubDeployRoles(this, "DeployRolesDev", "dev");
const prod = new GithubDeployRoles(this, "DeployRolesProd", "prod");
cdk.Tags.of(this).add("project", "open-swe");
cdk.Tags.of(this).add("ManagedBy", "cdk");
const out = (id: string, role: { roleName?: string }, env: string, kind: string) =>
new cdk.CfnOutput(this, id, {
value: `arn:aws:iam::${this.account}:role/${role.roleName}`,
description: `OIDC role ARN for ${env} ${kind} deploys — set as the ${env} deploy-role secret.`,
});
out("InfraDeployRoleDevArn", dev.infraRole, "dev", "infra (CDK)");
out("AppDeployRoleDevArn", dev.appRole, "dev", "app (tag-scoped SSM + S3)");
out("InfraDeployRoleProdArn", prod.infraRole, "prod", "infra (CDK)");
out("AppDeployRoleProdArn", prod.appRole, "prod", "app (tag-scoped SSM + S3)");
}
}