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)"); } }