Skip to content

Commit f8bb85f

Browse files
authored
fix(synthetics): generated role has incorrect permissions for cloudwatch logs (#18946)
The generated role did not have the correct permissions to create cloudwatch logs, so even if the canary successfully deployed and ran, no cloudwatch streams were generated for the resource. This seems to be a long-standing bug in the synthetics module. What was missing was the region and account id, which should be the same region/account as the created canary. Fixes #18910. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 072e1b9 commit f8bb85f

File tree

3 files changed

+150
-7
lines changed

3 files changed

+150
-7
lines changed

packages/@aws-cdk/aws-synthetics/lib/canary.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,6 @@ export class Canary extends cdk.Resource {
290290
* Returns a default role for the canary
291291
*/
292292
private createDefaultRole(prefix?: string): iam.IRole {
293-
const { partition } = cdk.Stack.of(this);
294293
// Created role will need these policies to run the Canary.
295294
// https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html#cfn-synthetics-canary-executionrolearn
296295
const policy = new iam.PolicyDocument({
@@ -313,7 +312,7 @@ export class Canary extends cdk.Resource {
313312
conditions: { StringEquals: { 'cloudwatch:namespace': 'CloudWatchSynthetics' } },
314313
}),
315314
new iam.PolicyStatement({
316-
resources: [`arn:${partition}:logs:::*`],
315+
resources: [this.logGroupArn()],
317316
actions: ['logs:CreateLogStream', 'logs:CreateLogGroup', 'logs:PutLogEvents'],
318317
}),
319318
],
@@ -327,6 +326,15 @@ export class Canary extends cdk.Resource {
327326
});
328327
}
329328

329+
private logGroupArn() {
330+
return cdk.Stack.of(this).formatArn({
331+
service: 'logs',
332+
resource: 'log-group',
333+
arnFormat: cdk.ArnFormat.COLON_RESOURCE_NAME,
334+
resourceName: '/aws/lambda/cwsyn-*',
335+
});
336+
}
337+
330338
/**
331339
* Returns the code object taken in by the canary resource.
332340
*/

packages/@aws-cdk/aws-synthetics/test/canary.test.ts

+95
Original file line numberDiff line numberDiff line change
@@ -440,3 +440,98 @@ test('can specify custom test', () => {
440440
},
441441
});
442442
});
443+
444+
test('Role policy generated as expected', () => {
445+
// GIVEN
446+
const stack = new Stack();
447+
448+
// WHEN
449+
new synthetics.Canary(stack, 'Canary', {
450+
test: synthetics.Test.custom({
451+
handler: 'index.handler',
452+
code: synthetics.Code.fromInline('/* Synthetics handler code */'),
453+
}),
454+
runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_3,
455+
});
456+
457+
// THEN
458+
Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', {
459+
Policies: [{
460+
PolicyDocument: {
461+
Statement: [
462+
{
463+
Action: 's3:ListAllMyBuckets',
464+
Effect: 'Allow',
465+
Resource: '*',
466+
},
467+
{
468+
Action: 's3:GetBucketLocation',
469+
Effect: 'Allow',
470+
Resource: {
471+
'Fn::GetAtt': [
472+
'CanaryArtifactsBucket4A60D32B',
473+
'Arn',
474+
],
475+
},
476+
},
477+
{
478+
Action: 's3:PutObject',
479+
Effect: 'Allow',
480+
Resource: {
481+
'Fn::Join': [
482+
'',
483+
[
484+
{
485+
'Fn::GetAtt': [
486+
'CanaryArtifactsBucket4A60D32B',
487+
'Arn',
488+
],
489+
},
490+
'/*',
491+
],
492+
],
493+
},
494+
},
495+
{
496+
Action: 'cloudwatch:PutMetricData',
497+
Condition: {
498+
StringEquals: {
499+
'cloudwatch:namespace': 'CloudWatchSynthetics',
500+
},
501+
},
502+
Effect: 'Allow',
503+
Resource: '*',
504+
},
505+
{
506+
Action: [
507+
'logs:CreateLogStream',
508+
'logs:CreateLogGroup',
509+
'logs:PutLogEvents',
510+
],
511+
Effect: 'Allow',
512+
Resource: {
513+
'Fn::Join': [
514+
'',
515+
[
516+
'arn:',
517+
{
518+
Ref: 'AWS::Partition',
519+
},
520+
':logs:',
521+
{
522+
Ref: 'AWS::Region',
523+
},
524+
':',
525+
{
526+
Ref: 'AWS::AccountId',
527+
},
528+
':log-group:/aws/lambda/cwsyn-*',
529+
],
530+
],
531+
},
532+
},
533+
],
534+
},
535+
}],
536+
});
537+
});

packages/@aws-cdk/aws-synthetics/test/integ.canary.expected.json

+45-5
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,15 @@
8282
{
8383
"Ref": "AWS::Partition"
8484
},
85-
":logs:::*"
85+
":logs:",
86+
{
87+
"Ref": "AWS::Region"
88+
},
89+
":",
90+
{
91+
"Ref": "AWS::AccountId"
92+
},
93+
":log-group:/aws/lambda/cwsyn-*"
8694
]
8795
]
8896
}
@@ -269,7 +277,15 @@
269277
{
270278
"Ref": "AWS::Partition"
271279
},
272-
":logs:::*"
280+
":logs:",
281+
{
282+
"Ref": "AWS::Region"
283+
},
284+
":",
285+
{
286+
"Ref": "AWS::AccountId"
287+
},
288+
":log-group:/aws/lambda/cwsyn-*"
273289
]
274290
]
275291
}
@@ -490,7 +506,15 @@
490506
{
491507
"Ref": "AWS::Partition"
492508
},
493-
":logs:::*"
509+
":logs:",
510+
{
511+
"Ref": "AWS::Region"
512+
},
513+
":",
514+
{
515+
"Ref": "AWS::AccountId"
516+
},
517+
":log-group:/aws/lambda/cwsyn-*"
494518
]
495519
]
496520
}
@@ -711,7 +735,15 @@
711735
{
712736
"Ref": "AWS::Partition"
713737
},
714-
":logs:::*"
738+
":logs:",
739+
{
740+
"Ref": "AWS::Region"
741+
},
742+
":",
743+
{
744+
"Ref": "AWS::AccountId"
745+
},
746+
":log-group:/aws/lambda/cwsyn-*"
715747
]
716748
]
717749
}
@@ -932,7 +964,15 @@
932964
{
933965
"Ref": "AWS::Partition"
934966
},
935-
":logs:::*"
967+
":logs:",
968+
{
969+
"Ref": "AWS::Region"
970+
},
971+
":",
972+
{
973+
"Ref": "AWS::AccountId"
974+
},
975+
":log-group:/aws/lambda/cwsyn-*"
936976
]
937977
]
938978
}

0 commit comments

Comments
 (0)