From ea1a1b038f288766bef3fafbff052482d2ec3fa4 Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Thu, 31 Mar 2022 18:19:57 -0700 Subject: [PATCH] fix(codedeploy): the Service Principal is wrong in isolated regions Turns out, the Service Principal for CodeDeploy in the isolated regions is not regional like in all other regions, but rather universal (`codedeploy.amazonaws.com`). Fixes #19399 --- .../test/lambda/deployment-group.test.ts | 27 ++++++++++++++++++- packages/@aws-cdk/aws-iam/lib/principals.ts | 10 ++----- .../@aws-cdk/region-info/lib/aws-entities.ts | 11 -------- packages/@aws-cdk/region-info/lib/default.ts | 11 ++++---- packages/@aws-cdk/region-info/lib/fact.ts | 2 +- .../__snapshots__/region-info.test.js.snap | 6 ++--- 6 files changed, 38 insertions(+), 29 deletions(-) diff --git a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-group.test.ts b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-group.test.ts index c6ecfde1ae2de..5ca7e0d5c6b72 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-group.test.ts +++ b/packages/@aws-cdk/aws-codedeploy/test/lambda/deployment-group.test.ts @@ -115,7 +115,6 @@ describe('CodeDeploy Lambda DeploymentGroup', () => { }); }); - test('can be created with explicit name', () => { const stack = new cdk.Stack(); const application = new codedeploy.LambdaApplication(stack, 'MyApp'); @@ -565,6 +564,32 @@ describe('CodeDeploy Lambda DeploymentGroup', () => { }, }); }); + + test('uses the correct Service Principal in the us-isob-east-1 region', () => { + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'CodeDeployLambdaStack', { + env: { region: 'us-isob-east-1' }, + }); + const alias = mockAlias(stack); + new codedeploy.LambdaDeploymentGroup(stack, 'MyDG', { + alias, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'codedeploy.amazonaws.com', + }, + }, + ], + Version: '2012-10-17', + }, + }); + }); }); describe('imported with fromLambdaDeploymentGroupAttributes', () => { diff --git a/packages/@aws-cdk/aws-iam/lib/principals.ts b/packages/@aws-cdk/aws-iam/lib/principals.ts index aecd493192142..a52e8d1e0dda2 100644 --- a/packages/@aws-cdk/aws-iam/lib/principals.ts +++ b/packages/@aws-cdk/aws-iam/lib/principals.ts @@ -767,14 +767,8 @@ class ServicePrincipalToken implements cdk.IResolvable { public resolve(ctx: cdk.IResolveContext) { if (this.opts.region) { // Special case, handle it separately to not break legacy behavior. - return ( - RegionInfo.get(this.opts.region).servicePrincipal(this.service) ?? - Default.servicePrincipal( - this.service, - this.opts.region, - cdk.Aws.URL_SUFFIX, - ) - ); + return RegionInfo.get(this.opts.region).servicePrincipal(this.service) ?? + Default.servicePrincipal(this.service, this.opts.region, cdk.Aws.URL_SUFFIX); } const stack = cdk.Stack.of(ctx.scope); diff --git a/packages/@aws-cdk/region-info/lib/aws-entities.ts b/packages/@aws-cdk/region-info/lib/aws-entities.ts index 9c14e89605607..0c28399449434 100644 --- a/packages/@aws-cdk/region-info/lib/aws-entities.ts +++ b/packages/@aws-cdk/region-info/lib/aws-entities.ts @@ -133,14 +133,3 @@ export function partitionInformation(region: string): Region { } return PARTITION_MAP.default; } - -/** - * Build a lookup map for all regions - */ -export function generateRegionMap(cb: (region: string) => string): Record { - const ret: Record = {}; - for (const region of AWS_REGIONS) { - ret[region] = cb(region); - } - return ret; -} diff --git a/packages/@aws-cdk/region-info/lib/default.ts b/packages/@aws-cdk/region-info/lib/default.ts index e306bd8c1fc25..c4e02d42bca3d 100644 --- a/packages/@aws-cdk/region-info/lib/default.ts +++ b/packages/@aws-cdk/region-info/lib/default.ts @@ -35,10 +35,10 @@ export class Default { } function determineConfiguration(service: string): (service: string, region: string, urlSuffix: string) => string { - function universal(s: string) { return `${s}.amazonaws.com`; }; - function partitional(s: string, _: string, u: string) { return `${s}.${u}`; }; - function regional(s: string, r: string) { return `${s}.${r}.amazonaws.com`; }; - function regionalPartitional(s: string, r: string, u: string) { return `${s}.${r}.${u}`; }; + function universal(s: string) { return `${s}.amazonaws.com`; } + function partitional(s: string, _: string, u: string) { return `${s}.${u}`; } + function regional(s: string, r: string) { return `${s}.${r}.amazonaws.com`; } + function regionalPartitional(s: string, r: string, u: string) { return `${s}.${r}.${u}`; } // Exceptions for Service Principals in us-iso-* const US_ISO_EXCEPTIONS = new Set([ @@ -91,7 +91,8 @@ export class Default { case 'codedeploy': return region.startsWith('cn-') ? regionalPartitional - : regional; + // ...except in the isolated regions, where it's universal + : (region.startsWith('us-iso') ? universal : regional); // Services with a regional AND partitional principal case 'logs': diff --git a/packages/@aws-cdk/region-info/lib/fact.ts b/packages/@aws-cdk/region-info/lib/fact.ts index 9c2831f67d2c6..583a4ac68450f 100644 --- a/packages/@aws-cdk/region-info/lib/fact.ts +++ b/packages/@aws-cdk/region-info/lib/fact.ts @@ -182,7 +182,7 @@ export class FactName { * The `.amazonaws.com` and `.amazonaws.com.cn` domains are stripped from service names, so they are * canonicalized in that respect. */ - public static servicePrincipal(service: string) { + public static servicePrincipal(service: string): string { return `service-principal:${service.replace(/\.amazonaws\.com(\.cn)?$/, '')}`; } } diff --git a/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap b/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap index 678a65fb4ccc3..5a3c0e2683c2c 100644 --- a/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap +++ b/packages/@aws-cdk/region-info/test/__snapshots__/region-info.test.js.snap @@ -795,7 +795,7 @@ Object { "servicePrincipals": Object { "application-autoscaling": "application-autoscaling.amazonaws.com", "autoscaling": "autoscaling.amazonaws.com", - "codedeploy": "codedeploy.us-iso-east-1.amazonaws.com", + "codedeploy": "codedeploy.amazonaws.com", "ec2": "ec2.c2s.ic.gov", "events": "events.amazonaws.com", "lambda": "lambda.amazonaws.com", @@ -826,7 +826,7 @@ Object { "servicePrincipals": Object { "application-autoscaling": "application-autoscaling.amazonaws.com", "autoscaling": "autoscaling.amazonaws.com", - "codedeploy": "codedeploy.us-iso-west-1.amazonaws.com", + "codedeploy": "codedeploy.amazonaws.com", "ec2": "ec2.c2s.ic.gov", "events": "events.amazonaws.com", "lambda": "lambda.amazonaws.com", @@ -857,7 +857,7 @@ Object { "servicePrincipals": Object { "application-autoscaling": "application-autoscaling.amazonaws.com", "autoscaling": "autoscaling.amazonaws.com", - "codedeploy": "codedeploy.us-isob-east-1.amazonaws.com", + "codedeploy": "codedeploy.amazonaws.com", "ec2": "ec2.sc2s.sgov.gov", "events": "events.amazonaws.com", "lambda": "lambda.amazonaws.com",