diff --git a/cdk/lib/__snapshots__/index.test.ts.snap b/cdk/lib/__snapshots__/index.test.ts.snap index 8a37b210e..92892c691 100644 --- a/cdk/lib/__snapshots__/index.test.ts.snap +++ b/cdk/lib/__snapshots__/index.test.ts.snap @@ -108,6 +108,10 @@ exports[`The typerighter stack matches the snapshot 1`] = ` "Description": "A list of private subnets", "Type": "AWS::SSM::Parameter::Value>", }, + "SsmParameterValueTESTtyperightertyperighterlivecontentlambdafirehoseARNC96584B6F00A464EAD1953AFF4B05118Parameter": { + "Default": "/TEST/typerighter/typerighter-live-content-lambda/firehose-ARN", + "Type": "AWS::SSM::Parameter::Value", + }, "VpcId": { "Default": "/account/vpc/primary/id", "Description": "Virtual Private Cloud to run EC2 instances within. Should NOT be the account default VPC.", @@ -1722,6 +1726,19 @@ exports[`The typerighter stack matches the snapshot 1`] = ` }, "Type": "AWS::Lambda::Function", }, + "TyperighterLiveContentLambdaKinesisEventSourcetyperighterContentApiFirehose12B21953B7975807": { + "Properties": { + "BatchSize": 100, + "EventSourceArn": { + "Ref": "SsmParameterValueTESTtyperightertyperighterlivecontentlambdafirehoseARNC96584B6F00A464EAD1953AFF4B05118Parameter", + }, + "FunctionName": { + "Ref": "TyperighterLiveContentLambdaF35D688E", + }, + "StartingPosition": "LATEST", + }, + "Type": "AWS::Lambda::EventSourceMapping", + }, "TyperighterLiveContentLambdaServiceRole47E0FE94": { "Properties": { "AssumeRolePolicyDocument": { @@ -1749,6 +1766,18 @@ exports[`The typerighter stack matches the snapshot 1`] = ` ], ], }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/AWSLambdaKinesisExecutionRole", + ], + ], + }, ], "Tags": [ { @@ -1863,6 +1892,29 @@ exports[`The typerighter stack matches the snapshot 1`] = ` ], }, }, + { + "Action": [ + "kinesis:DescribeStreamSummary", + "kinesis:GetRecords", + "kinesis:GetShardIterator", + "kinesis:ListShards", + "kinesis:SubscribeToShard", + "kinesis:DescribeStream", + "kinesis:ListStreams", + "kinesis:DescribeStreamConsumer", + ], + "Effect": "Allow", + "Resource": { + "Ref": "SsmParameterValueTESTtyperightertyperighterlivecontentlambdafirehoseARNC96584B6F00A464EAD1953AFF4B05118Parameter", + }, + }, + { + "Action": "kinesis:DescribeStream", + "Effect": "Allow", + "Resource": { + "Ref": "SsmParameterValueTESTtyperightertyperighterlivecontentlambdafirehoseARNC96584B6F00A464EAD1953AFF4B05118Parameter", + }, + }, ], "Version": "2012-10-17", }, diff --git a/cdk/lib/index.ts b/cdk/lib/index.ts index e0e65a2e7..7f276072b 100644 --- a/cdk/lib/index.ts +++ b/cdk/lib/index.ts @@ -4,7 +4,6 @@ import { Duration, RemovalPolicy, SecretValue, - Tags, } from "aws-cdk-lib"; import { Certificate } from "aws-cdk-lib/aws-certificatemanager"; import type { GuStackProps } from "@guardian/cdk/lib/constructs/core/stack"; @@ -38,7 +37,10 @@ import { TreatMissingData, } from "aws-cdk-lib/aws-cloudwatch"; import { GuDatabaseInstance } from "@guardian/cdk/lib/constructs/rds"; -import { Architecture, Runtime } from "aws-cdk-lib/aws-lambda"; +import { ManagedPolicy } from "aws-cdk-lib/aws-iam"; +import { Stream } from "aws-cdk-lib/aws-kinesis"; +import { Architecture, Runtime, StartingPosition } from "aws-cdk-lib/aws-lambda"; +import { KinesisEventSource } from "aws-cdk-lib/aws-lambda-event-sources"; import { Credentials, DatabaseInstanceEngine, @@ -49,6 +51,7 @@ import { import { GuArnParameter, GuParameter } from "@guardian/cdk/lib/constructs/core"; import { AccessScope } from "@guardian/cdk/lib/constants/access"; import { Secret } from "aws-cdk-lib/aws-secretsmanager"; +import { StringParameter } from 'aws-cdk-lib/aws-ssm'; export interface TyperighterStackProps extends GuStackProps { domainSuffix: string; @@ -339,12 +342,26 @@ EOF devXBackups: { enabled: true } }); - new GuLambdaFunction(this, 'TyperighterLiveContentLambda', { + const liveContentLambda = new GuLambdaFunction(this, 'TyperighterLiveContentLambda', { app: 'typerighter-live-content-lambda', fileName: 'typerighter-live-content-lambda.zip', handler: 'index.main', runtime: Runtime.NODEJS_20_X, - architecture: Architecture.ARM_64, + architecture: Architecture.ARM_64 }); + + liveContentLambda.role?.addManagedPolicy( + ManagedPolicy.fromAwsManagedPolicyName("AWSLambdaKinesisExecutionRole") + ); + + const streamARN = StringParameter.valueForStringParameter(this, + `/${this.stage}/typerighter/typerighter-live-content-lambda/firehose-ARN` + ); + + const stream = Stream.fromStreamArn(this, 'ContentApiFirehose', streamARN); + + liveContentLambda.addEventSource(new KinesisEventSource(stream, { + startingPosition: StartingPosition.LATEST, + })); } }