diff --git a/lib/org-governance-stack.ts b/lib/org-governance-stack.ts index bfb80f6..d4d4035 100644 --- a/lib/org-governance-stack.ts +++ b/lib/org-governance-stack.ts @@ -56,9 +56,13 @@ const scpContent = (name: string): Record => * decision as the external-dev guardrails): it is the only generic * cross-account expression for CDK exec roles; member baselines protect * those roles from takeover (ProtectPrivilegedRoles pattern). - * - Region-lock NotAction list deliberately matches battle-tested - * p-i59g24mz; regional services (s3, kms, logs, ssm...) stay region-locked - * BY DESIGN — do not add them to NotAction (that would exempt them). + * - Region-lock NotAction list extends battle-tested p-i59g24mz with + * bedrock:InvokeModel/InvokeModelWithResponseStream/Converse/ConverseStream + * to allow cross-region inference profiles (us.anthropic.*) that route to + * us-east-2; a companion DenyBedrockInvokeOutsideInference statement + * re-denies those actions outside {us-east-1, us-west-2, us-east-2}. + * Regional services (s3, kms, logs, ssm...) stay region-locked BY DESIGN + * — do not add them to NotAction (that would exempt them). */ export class OrgGovernanceStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { @@ -116,7 +120,10 @@ export class OrgGovernanceStack extends cdk.Stack { // Region lock for workload accounts: us-east-1 (primary) + us-west-2 // (offsite backup/DR). Global services exempted via NotAction — the same - // list proven on the external-dev region lock. + // list proven on the external-dev region lock. Bedrock Invoke/Converse + // are carved out of the general deny and re-denied only outside + // {us-east-1, us-west-2, us-east-2} so cross-region inference profiles + // (us.anthropic.*) that route to us-east-2 are not blocked. const workloadsRegionLock = new organizations.CfnPolicy(this, "WorkloadsRegionLock", { name: "workloads-region-lock", type: "SERVICE_CONTROL_POLICY", @@ -135,6 +142,8 @@ export class OrgGovernanceStack extends cdk.Stack { "globalaccelerator:*", "budgets:*", "ce:*", "cur:*", "health:*", "support:*", "supportplans:*", "trustedadvisor:*", "artifact:*", "aws-portal:*", + "bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream", + "bedrock:Converse", "bedrock:ConverseStream", ], Resource: "*", Condition: { @@ -143,6 +152,20 @@ export class OrgGovernanceStack extends cdk.Stack { }, }, }, + { + Sid: "DenyBedrockInvokeOutsideInference", + Effect: "Deny", + Action: [ + "bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream", + "bedrock:Converse", "bedrock:ConverseStream", + ], + Resource: "*", + Condition: { + StringNotEquals: { + "aws:RequestedRegion": ["us-east-1", "us-west-2", "us-east-2"], + }, + }, + }, ], }, });