cdk/lib/image-copier-lambda.ts (104 lines of code) (raw):
import type { GuStackProps } from "@guardian/cdk/lib/constructs/core";
import { GuStack } from "@guardian/cdk/lib/constructs/core";
import type { App } from "aws-cdk-lib";
import { CfnParameter, Duration, Fn } from "aws-cdk-lib";
import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
import { Code, Function, Runtime } from "aws-cdk-lib/aws-lambda";
import { SnsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
import { Bucket } from "aws-cdk-lib/aws-s3";
import { Topic } from "aws-cdk-lib/aws-sns";
export interface ImageCopierLambdaProps extends GuStackProps {
version: string;
}
export class ImageCopierLambda extends GuStack {
constructor(scope: App, id: string, props: ImageCopierLambdaProps) {
super(scope, id, props);
const functionCodeBucket = Bucket.fromBucketName(this, "function-code-bucket", "deploy-tools-dist");
const kmsKeyArnParam = new CfnParameter(this, "KmsKeyArn", {
description: "Override the default KMS key if required",
type: "String",
default: "",
});
const kmsKeyArn = Fn.importValue("amigo-imagecopier-key");
const housekeepingTopicParam = new CfnParameter(this, "AmigoHousekeepingTopicArn", {
description: "The housekeeping SNS topic to subscribe to",
type: "String",
});
const copierTopicParam = new CfnParameter(this, "AmigoTopicArn", {
description: "The SNS topic to subscribe to",
type: "String",
});
const loggingPolicy = new PolicyStatement({
effect: Effect.ALLOW,
actions: ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
resources: ["arn:aws:logs:*:*:*"],
});
const copierLambda = new Function(this, "ImageCopierLambda", {
description: "Lambda for copying and encrypting AMIgo baked AMIs",
runtime: Runtime.JAVA_21,
memorySize: 512,
handler: "com.gu.imageCopier.LambdaEntrypoint::run",
timeout: Duration.seconds(30),
environment: {
ACCOUNT_ID: this.account,
KMS_KEY_ARN: kmsKeyArn,
ENCRYPTED_TAG_VALUE: "true",
},
code: Code.fromBucket(functionCodeBucket, `${this.stack}/${this.stage}/imagecopier/image-copier-${props.version}.zip`),
initialPolicy: [
loggingPolicy,
new PolicyStatement({
effect: Effect.ALLOW,
actions: ["ec2:CopyImage", "ec2:CreateTags"],
resources: ["*"],
}),
new PolicyStatement({
effect: Effect.ALLOW,
actions: ["kms:Encrypt", "kms:Decrypt", "kms:CreateGrant", "kms:GenerateDataKey*", "kms:DescribeKey"],
resources: [Fn.importValue("amigo-imagecopier-key")],
}),
],
});
this.overrideLogicalId(copierLambda, {
logicalId: "ImageCopierLambda",
reason: "To gain confidence during the migration to CDK",
});
const copierTopic = Topic.fromTopicArn(
this,
`ImageCopierLambda-SnsExistingIncomingEventsTopic`,
copierTopicParam.valueAsString
);
copierLambda.addEventSource(new SnsEventSource(copierTopic));
const housekeepingLambda = new Function(this, "HousekeepingLambda", {
description: "Lambda for housekeeping AMIgo baked AMIs in other accounts",
runtime: Runtime.JAVA_11,
memorySize: 512,
handler: "com.gu.imageCopier.LambdaEntrypoint::housekeeping",
timeout: Duration.seconds(30),
environment: {
ACCOUNT_ID: this.account,
KMS_KEY_ARN: kmsKeyArn,
ENCRYPTED_TAG_VALUE: "true",
},
code: Code.fromBucket(functionCodeBucket, `${this.stack}/${this.stage}/imagecopier/image-copier-${props.version}.zip`),
initialPolicy: [
loggingPolicy,
new PolicyStatement({
effect: Effect.ALLOW,
actions: ["ec2:DescribeImages", "ec2:DeregisterImage", "ec2:DeleteSnapshot"],
resources: ["*"],
}),
],
});
this.overrideLogicalId(housekeepingLambda, {
logicalId: "HousekeepingLambda",
reason: "To gain confidence during the migration to CDK",
});
const housekeepingTopic = Topic.fromTopicArn(
this,
`HousekeepingLambda-SnsExistingIncomingEventsTopic`,
housekeepingTopicParam.valueAsString
);
housekeepingLambda.addEventSource(new SnsEventSource(housekeepingTopic));
}
}