Skip to content

Commit 09ac7b4

Browse files
committed
feat(s3): Allow separate logging bucket for AWS Config
For the case where the central logs bucket has Object Lock enabled, AWS Config does not support logging directly to the central logs bucket. A workaround for that issue is to create a separate bucket without Object Lock enabled and replicate everything over to the central logs bucket. This change adds the option to create that separate bucket with a replication rule into the central logs bucket and repointing AWS Config to use that separate bucket instead.
1 parent cc76ea7 commit 09ac7b4

File tree

8 files changed

+470
-2
lines changed

8 files changed

+470
-2
lines changed

source/packages/@aws-accelerator/accelerator/lib/stacks/accelerator-stack.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ export abstract class AcceleratorStack extends cdk.Stack {
108108
*/
109109
public static readonly ACCELERATOR_CONFIGURATION_REPOSITORY_NAME = 'aws-accelerator-config';
110110

111+
/**
112+
* Accelerator AWS Config bucket name prefix
113+
*/
114+
public static readonly ACCELERATOR_CONFIG_BUCKET_PREFIX = 'aws-accelerator-aws-config';
115+
111116
/**
112117
* Accelerator S3 access logs bucket name prefix
113118
*/

source/packages/@aws-accelerator/accelerator/lib/stacks/logging-stack.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,65 @@ export class LoggingStack extends AcceleratorStack {
251251
// Create VPC Flow logs destination bucket
252252
this.createVpcFlowLogsBucket(s3Key, serverAccessLogsBucket, replicationProps);
253253

254+
if (
255+
cdk.Stack.of(this).account === this.props.accountsConfig.getLogArchiveAccountId() &&
256+
this.props.securityConfig.awsConfig.enableDeliveryChannel &&
257+
this.props.securityConfig.awsConfig.useSeparateBucket
258+
) {
259+
const configBucket = new Bucket(this, 'ConfigBucket', {
260+
encryptionType: BucketEncryptionType.SSE_KMS,
261+
s3BucketName: `${AcceleratorStack.ACCELERATOR_CONFIG_BUCKET_PREFIX}-${cdk.Stack.of(this).account}-${
262+
cdk.Stack.of(this).region
263+
}`,
264+
kmsKey: this.centralLogsBucket?.getS3Bucket().getKey(),
265+
serverAccessLogsBucket: serverAccessLogsBucket.getS3Bucket(),
266+
replicationProps,
267+
s3LifeCycleRules: this.getS3LifeCycleRules(this.props.globalConfig.logging.configBucket?.lifecycleRules),
268+
});
269+
270+
// To make sure central log bucket created before elb access log bucket, this is required when logging stack executes in home region
271+
if (this.centralLogsBucket) {
272+
configBucket.node.addDependency(this.centralLogsBucket);
273+
}
274+
275+
// AwsSolutions-IAM5: The IAM entity contains wildcard permissions and does not have a cdk_nag rule suppression with evidence for those permission.
276+
NagSuppressions.addResourceSuppressionsByPath(
277+
this,
278+
`/${this.stackName}/ConfigBucket/ConfigBucketReplication/` +
279+
pascalCase(this.centralLogsBucketName) +
280+
'-ReplicationRole/DefaultPolicy/Resource',
281+
[
282+
{
283+
id: 'AwsSolutions-IAM5',
284+
reason: 'Allows only specific policy.',
285+
},
286+
],
287+
);
288+
289+
configBucket.getS3Bucket().addToResourcePolicy(
290+
new cdk.aws_iam.PolicyStatement({
291+
principals: [new cdk.aws_iam.ServicePrincipal('config.amazonaws.com')],
292+
actions: ['s3:PutObject'],
293+
resources: [configBucket.getS3Bucket().arnForObjects('*')],
294+
conditions: {
295+
StringEquals: {
296+
's3:x-amz-acl': 'bucket-owner-full-control',
297+
},
298+
},
299+
}),
300+
);
301+
302+
configBucket.getS3Bucket().addToResourcePolicy(
303+
new cdk.aws_iam.PolicyStatement({
304+
principals: [new cdk.aws_iam.ServicePrincipal('config.amazonaws.com')],
305+
actions: ['s3:GetBucketAcl', 's3:ListBucket'],
306+
resources: [configBucket.getS3Bucket().bucketArn],
307+
}),
308+
);
309+
310+
this.configBucketAddResourcePolicies(configBucket.getS3Bucket());
311+
}
312+
254313
/**
255314
* Create S3 Bucket for ELB Access Logs, this is created in log archive account
256315
* For ELB to write access logs bucket is needed to have SSE-S3 server-side encryption
@@ -1741,6 +1800,24 @@ export class LoggingStack extends AcceleratorStack {
17411800
]);
17421801
}
17431802

1803+
private configBucketAddResourcePolicies(configBucket: cdk.aws_s3.IBucket) {
1804+
this.logger.info('Adding AWS Config bucket resource policies to S3');
1805+
for (const attachment of this.props.globalConfig.logging.configBucket?.s3ResourcePolicyAttachments ?? []) {
1806+
const policyDocument = JSON.parse(
1807+
this.generatePolicyReplacements(path.join(this.props.configDirPath, attachment.policy), false),
1808+
);
1809+
// Create a statements list using the PolicyStatement factory
1810+
const statements: cdk.aws_iam.PolicyStatement[] = [];
1811+
for (const statement of policyDocument.Statement) {
1812+
statements.push(cdk.aws_iam.PolicyStatement.fromJson(statement));
1813+
}
1814+
1815+
for (const statement of statements) {
1816+
configBucket.addToResourcePolicy(statement);
1817+
}
1818+
}
1819+
}
1820+
17441821
private elbLogBucketAddResourcePolicies(elbLogBucket: cdk.aws_s3.IBucket) {
17451822
this.logger.info(`Adding elb log bucket resource policies to S3`);
17461823
for (const attachment of this.props.globalConfig.logging.elbLogBucket?.s3ResourcePolicyAttachments ?? []) {

source/packages/@aws-accelerator/accelerator/lib/stacks/security-resources-stack.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,9 @@ export class SecurityResourcesStack extends AcceleratorStack {
496496

497497
if (this.props.securityConfig.awsConfig.enableDeliveryChannel) {
498498
new config.CfnDeliveryChannel(this, 'ConfigDeliveryChannel', {
499-
s3BucketName: `${AcceleratorStack.ACCELERATOR_CENTRAL_LOGS_BUCKET_NAME_PREFIX}-${this.logArchiveAccountId}-${this.props.centralizedLoggingRegion}`,
499+
s3BucketName: this.props.securityConfig.awsConfig.useSeparateBucket
500+
? `${AcceleratorStack.ACCELERATOR_CONFIG_BUCKET_PREFIX}-${this.logArchiveAccountId}-${this.props.centralizedLoggingRegion}`
501+
: `${AcceleratorStack.ACCELERATOR_CENTRAL_LOGS_BUCKET_NAME_PREFIX}-${this.logArchiveAccountId}-${this.props.centralizedLoggingRegion}`,
500502
configSnapshotDeliveryProperties: {
501503
deliveryFrequency: 'One_Hour',
502504
},

0 commit comments

Comments
 (0)