diff --git a/packages/@aws-cdk/custom-resource-handlers/lib/aws-logs/log-retention-handler/index.ts b/packages/@aws-cdk/custom-resource-handlers/lib/aws-logs/log-retention-handler/index.ts index 9422e81f7ef80..30ec30f88c98d 100644 --- a/packages/@aws-cdk/custom-resource-handlers/lib/aws-logs/log-retention-handler/index.ts +++ b/packages/@aws-cdk/custom-resource-handlers/lib/aws-logs/log-retention-handler/index.ts @@ -11,17 +11,18 @@ interface LogRetentionEvent extends Omit Promise) => Promise) { +async function createLogGroupSafe(logGroupName: string, client: Logs.CloudWatchLogsClient, withDelay: (block: () => Promise) => Promise, kmsKeyId?: string) { await withDelay(async () => { try { - const params = { logGroupName }; + const params = { logGroupName, kmsKeyId }; const command = new Logs.CreateLogGroupCommand(params); await client.send(command); @@ -90,6 +91,9 @@ export async function handler(event: LogRetentionEvent, context: AWSLambda.Conte // The region of the target log group const logGroupRegion = event.ResourceProperties.LogGroupRegion; + // The kms key used to encrypt the log group + const kmsKeyId = event.ResourceProperties.KmsKeyId; + // Parse to AWS SDK retry options const maxRetries = parseIntOptional(event.ResourceProperties.SdkRetry?.maxRetries) ?? 5; const withDelay = makeWithDelay(maxRetries); @@ -103,7 +107,7 @@ export async function handler(event: LogRetentionEvent, context: AWSLambda.Conte if (event.RequestType === 'Create' || event.RequestType === 'Update') { // Act on the target log group - await createLogGroupSafe(logGroupName, client, withDelay); + await createLogGroupSafe(logGroupName, client, withDelay, kmsKeyId); await setRetentionPolicy(logGroupName, client, withDelay, parseIntOptional(event.ResourceProperties.RetentionInDays)); // Configure the Log Group for the Custom Resource function itself @@ -116,7 +120,7 @@ export async function handler(event: LogRetentionEvent, context: AWSLambda.Conte // Due to the async nature of the log group creation, the log group for this function might // still be not created yet at this point. Therefore we attempt to create it. // In case it is being created, createLogGroupSafe will handle the conflict. - await createLogGroupSafe(`/aws/lambda/${context.functionName}`, clientForCustomResourceFunction, withDelay); + await createLogGroupSafe(`/aws/lambda/${context.functionName}`, clientForCustomResourceFunction, withDelay, kmsKeyId); // If createLogGroupSafe fails, the log group is not created even after multiple attempts. // In this case we have nothing to set the retention policy on but an exception will skip // the next line. diff --git a/packages/aws-cdk-lib/aws-logs/lib/log-retention.ts b/packages/aws-cdk-lib/aws-logs/lib/log-retention.ts index a1c5432560c8f..d1caf92d6a739 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/log-retention.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/log-retention.ts @@ -5,6 +5,7 @@ import * as iam from '../../aws-iam'; import * as s3_assets from '../../aws-s3-assets'; import * as cdk from '../../core'; import { ArnFormat } from '../../core'; +import {IKey} from "../../aws-kms"; /** * Construction properties for a LogRetention. @@ -45,6 +46,12 @@ export interface LogRetentionProps { * @default RemovalPolicy.RETAIN */ readonly removalPolicy?: cdk.RemovalPolicy; + + /** + * The KMS key used to encrypt the log group upon creation + * @default Log group will not be encrypted + */ + readonly kmsKey?: IKey; } /** @@ -105,6 +112,7 @@ export class LogRetention extends Construct { } : undefined, RetentionInDays: props.retention === RetentionDays.INFINITE ? undefined : props.retention, RemovalPolicy: props.removalPolicy, + KmsKeyId: props.kmsKey ? props.kmsKey?.keyArn : undefined, }, }); diff --git a/packages/aws-cdk-lib/aws-logs/test/log-retention.test.ts b/packages/aws-cdk-lib/aws-logs/test/log-retention.test.ts index cb26deba0c4d2..396d0be994113 100644 --- a/packages/aws-cdk-lib/aws-logs/test/log-retention.test.ts +++ b/packages/aws-cdk-lib/aws-logs/test/log-retention.test.ts @@ -4,6 +4,7 @@ import * as iam from '../../aws-iam'; import * as cdk from '../../core'; import * as cxapi from '../../cx-api'; import { LogRetention, RetentionDays } from '../lib'; +import {Key} from "../../aws-kms"; /* eslint-disable quote-props */ @@ -550,4 +551,17 @@ describe('log retention', () => { Timeout: 900, }); }); + + test('with KmsKeyId specified', () => { + const stack = new cdk.Stack(); + new LogRetention(stack, 'MyLambda', { + logGroupName: 'group', + retention: RetentionDays.INFINITE, + kmsKey: new Key(stack, 'MyKey') + }); + + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { + KmsKeyId: { 'Fn::GetAtt': [Match.stringLikeRegexp('MyKey'), 'Arn'] }, + }); + }); }); diff --git a/yarn.lock b/yarn.lock index 6cc7ad5fddeb6..145ea6bd7d707 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,7 +17,7 @@ "@actions/github@^5.1.1": version "5.1.1" - resolved "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz#40b9b9e1323a5efcf4ff7dadd33d8ea51651bbcb" + resolved "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz" integrity sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g== dependencies: "@actions/http-client" "^2.0.1"