Skip to content

Commit ed4a4b4

Browse files
authoredDec 10, 2021
fix(iam): AWS Managed Policy ARNs are not deduped (#17623)
Managed Policy ARNs should be deduped when added to a Role, otherwise the deployment is going to fail. Remove the unnecessary use of `Lazy.uncachedString` to make sure that the ARNs of two `ManagedPolicy.fromAwsManagedPolicyName()` policies are consistent. Fixes #17552. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 450f7ca commit ed4a4b4

File tree

4 files changed

+33
-15
lines changed

4 files changed

+33
-15
lines changed
 

‎packages/@aws-cdk/aws-iam/lib/managed-policy.ts

+8-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ArnFormat, IResolveContext, Lazy, Resource, Stack } from '@aws-cdk/core';
1+
import { ArnFormat, Resource, Stack, Arn, Aws } from '@aws-cdk/core';
22
import { Construct } from 'constructs';
33
import { IGroup } from './group';
44
import { CfnManagedPolicy } from './iam.generated';
@@ -156,16 +156,13 @@ export class ManagedPolicy extends Resource implements IManagedPolicy {
156156
*/
157157
public static fromAwsManagedPolicyName(managedPolicyName: string): IManagedPolicy {
158158
class AwsManagedPolicy implements IManagedPolicy {
159-
public readonly managedPolicyArn = Lazy.uncachedString({
160-
produce(ctx: IResolveContext) {
161-
return Stack.of(ctx.scope).formatArn({
162-
service: 'iam',
163-
region: '', // no region for managed policy
164-
account: 'aws', // the account for a managed policy is 'aws'
165-
resource: 'policy',
166-
resourceName: managedPolicyName,
167-
});
168-
},
159+
public readonly managedPolicyArn = Arn.format({
160+
partition: Aws.PARTITION,
161+
service: 'iam',
162+
region: '', // no region for managed policy
163+
account: 'aws', // the account for a managed policy is 'aws'
164+
resource: 'policy',
165+
resourceName: managedPolicyName,
169166
});
170167
}
171168
return new AwsManagedPolicy();

‎packages/@aws-cdk/aws-iam/test/managed-policy.test.ts

+7
Original file line numberDiff line numberDiff line change
@@ -614,3 +614,10 @@ describe('managed policy', () => {
614614
});
615615
});
616616
});
617+
618+
test('ARN for two instances of the same AWS Managed Policy is the same', () => {
619+
const mp1 = ManagedPolicy.fromAwsManagedPolicyName('foo/bar');
620+
const mp2 = ManagedPolicy.fromAwsManagedPolicyName('foo/bar');
621+
622+
expect(mp1.managedPolicyArn).toEqual(mp2.managedPolicyArn);
623+
});

‎packages/@aws-cdk/core/lib/arn.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,16 @@ export class Arn {
130130
* the 'scope' is attached to. If all ARN pieces are supplied, the supplied scope
131131
* can be 'undefined'.
132132
*/
133-
public static format(components: ArnComponents, stack: Stack): string {
134-
const partition = components.partition ?? stack.partition;
135-
const region = components.region ?? stack.region;
136-
const account = components.account ?? stack.account;
133+
public static format(components: ArnComponents, stack?: Stack): string {
134+
const partition = components.partition ?? stack?.partition;
135+
const region = components.region ?? stack?.region;
136+
const account = components.account ?? stack?.account;
137+
138+
// Catch both 'null' and 'undefined'
139+
if (partition == null || region == null || account == null) {
140+
throw new Error(`Arn.format: partition (${partition}), region (${region}), and account (${account}) must all be passed if stack is not passed.`);
141+
}
142+
137143
const sep = components.sep ?? (components.arnFormat === ArnFormat.COLON_RESOURCE_NAME ? ':' : '/');
138144

139145
const values = [

‎packages/@aws-cdk/core/test/arn.test.ts

+8
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ describe('arn', () => {
2020

2121
});
2222

23+
test('cannot rely on defaults when stack not known', () => {
24+
expect(() =>
25+
Arn.format({
26+
service: 'sqs',
27+
resource: 'myqueuename',
28+
})).toThrow(/must all be passed if stack is not/);
29+
});
30+
2331
test('create from components with specific values for the various components', () => {
2432
const stack = new Stack();
2533

0 commit comments

Comments
 (0)
Please sign in to comment.