Skip to content

Commit 816cfc0

Browse files
authored
fix(cloudtrail): Invalid resource for policy when using sendToCloudWatchLogs (#1851)
Sets `this.cloudWatchLogsGroupArn` before using it, such that a correct resource ARN is used in the policy generated for CloudTrail to be able to create and use the required log stream. Fixes #1848
1 parent cec8564 commit 816cfc0

File tree

2 files changed

+21
-12
lines changed

2 files changed

+21
-12
lines changed

packages/@aws-cdk/aws-cloudtrail/lib/index.ts

+7-10
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,6 @@ export enum LogRetention {
122122
export class CloudTrail extends cdk.Construct {
123123

124124
public readonly cloudTrailArn: string;
125-
private readonly cloudWatchLogsRoleArn?: string;
126-
private readonly cloudWatchLogsGroupArn?: string;
127125
private eventSelectors: EventSelector[] = [];
128126

129127
constructor(scope: cdk.Construct, id: string, props: CloudTrailProps = {}) {
@@ -143,20 +141,19 @@ export class CloudTrail extends cdk.Construct {
143141
.addServicePrincipal(cloudTrailPrincipal)
144142
.setCondition("StringEquals", {'s3:x-amz-acl': "bucket-owner-full-control"}));
145143

144+
let logGroup: logs.CfnLogGroup | undefined;
145+
let logsRole: iam.IRole | undefined;
146146
if (props.sendToCloudWatchLogs) {
147-
const logGroup = new logs.CfnLogGroup(this, "LogGroup", {
147+
logGroup = new logs.CfnLogGroup(this, "LogGroup", {
148148
retentionInDays: props.cloudWatchLogsRetentionTimeDays || LogRetention.OneYear
149149
});
150-
this.cloudWatchLogsGroupArn = logGroup.logGroupArn;
151150

152-
const logsRole = new iam.Role(this, 'LogsRole', {assumedBy: new iam.ServicePrincipal(cloudTrailPrincipal) });
151+
logsRole = new iam.Role(this, 'LogsRole', { assumedBy: new iam.ServicePrincipal(cloudTrailPrincipal) });
153152

154-
const streamArn = `${this.cloudWatchLogsRoleArn}:log-stream:*`;
153+
const streamArn = `${logsRole.roleArn}:log-stream:*`;
155154
logsRole.addToPolicy(new iam.PolicyStatement()
156155
.addActions("logs:PutLogEvents", "logs:CreateLogStream")
157156
.addResource(streamArn));
158-
this.cloudWatchLogsRoleArn = logsRole.roleArn;
159-
160157
}
161158
if (props.managementEvents) {
162159
const managementEvent = {
@@ -176,8 +173,8 @@ export class CloudTrail extends cdk.Construct {
176173
kmsKeyId: props.kmsKey && props.kmsKey.keyArn,
177174
s3BucketName: s3bucket.bucketName,
178175
s3KeyPrefix: props.s3KeyPrefix,
179-
cloudWatchLogsLogGroupArn: this.cloudWatchLogsGroupArn,
180-
cloudWatchLogsRoleArn: this.cloudWatchLogsRoleArn,
176+
cloudWatchLogsLogGroupArn: logGroup && logGroup.logGroupArn,
177+
cloudWatchLogsRoleArn: logsRole && logsRole.roleArn,
181178
snsTopicName: props.snsTopic,
182179
eventSelectors: this.eventSelectors
183180
});

packages/@aws-cdk/aws-cloudtrail/test/test.cloudtrail.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,20 @@ export = {
7575
expect(stack).to(haveResource("AWS::S3::BucketPolicy", ExpectedBucketPolicyProperties));
7676
expect(stack).to(haveResource("AWS::Logs::LogGroup"));
7777
expect(stack).to(haveResource("AWS::IAM::Role"));
78-
expect(stack).to(haveResource("AWS::Logs::LogGroup", {
79-
RetentionInDays: 365
78+
expect(stack).to(haveResource("AWS::Logs::LogGroup", { RetentionInDays: 365 }));
79+
expect(stack).to(haveResource("AWS::IAM::Policy", {
80+
PolicyDocument: {
81+
Version: '2012-10-17',
82+
Statement: [{
83+
Effect: 'Allow',
84+
Action: ['logs:PutLogEvents', 'logs:CreateLogStream'],
85+
Resource: {
86+
'Fn::Join': ['', [{ 'Fn::GetAtt': ['MyAmazingCloudTrailLogsRoleF2CCF977', 'Arn'] }, ':log-stream:*']],
87+
}
88+
}]
89+
},
90+
PolicyName: 'MyAmazingCloudTrailLogsRoleDefaultPolicy61DC49E7',
91+
Roles: [{ Ref: 'MyAmazingCloudTrailLogsRoleF2CCF977' }],
8092
}));
8193
const trail: any = stack.toCloudFormation().Resources.MyAmazingCloudTrail54516E8D;
8294
test.deepEqual(trail.DependsOn, ['MyAmazingCloudTrailS3Policy39C120B0']);

0 commit comments

Comments
 (0)