cdk/lib/ticker-calculator.ts (86 lines of code) (raw):

import { GuScheduledLambda } from '@guardian/cdk'; import type { GuStackProps } from '@guardian/cdk/lib/constructs/core'; import { GuStack } from '@guardian/cdk/lib/constructs/core'; import type { GuScheduledLambdaProps } from '@guardian/cdk/lib/patterns/scheduled-lambda'; import type { App } from 'aws-cdk-lib'; import { Duration } from 'aws-cdk-lib'; import { RuleTargetInput, Schedule } from 'aws-cdk-lib/aws-events'; import { PolicyStatement, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; import { LoggingFormat, Runtime } from 'aws-cdk-lib/aws-lambda'; const AppName = 'ticker-calculator'; const TickerBucket = 'contributions-ticker'; export class TickerCalculator extends GuStack { constructor(scope: App, id: string, props: GuStackProps) { super(scope, id, props); const scheduleRules: GuScheduledLambdaProps['rules'] = [ { schedule: Schedule.rate(Duration.minutes(15)), description: 'US', input: RuleTargetInput.fromText('US'), }, { schedule: Schedule.rate(Duration.minutes(15)), description: 'AU', input: RuleTargetInput.fromText('AU'), }, { schedule: Schedule.rate(Duration.minutes(15)), description: 'global', input: RuleTargetInput.fromText('global'), }, ]; const role = new Role(this, 'query-lambda-role', { // Set the name of the role rather than using an autogenerated name. // This is because if the ARN is too long then it breaks the authentication request to GCP roleName: `${AppName}-${this.stage}`, assumedBy: new ServicePrincipal('lambda.amazonaws.com'), }); role.addToPolicy( // Logging permissions new PolicyStatement({ actions: [ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents', ], resources: ['*'], }), ); role.addToPolicy( // Permission to create the ticker output file in S3 new PolicyStatement({ actions: ['s3:*'], resources: [ `arn:aws:s3::*:${TickerBucket}/*`, `arn:aws:s3::*:${TickerBucket}`, ], }), ); role.addToPolicy( // Permission to read config from Parameter Store new PolicyStatement({ actions: ['ssm:GetParameter'], resources: [ `arn:aws:ssm:${this.region}:${this.account}:parameter/ticker-calculator/${this.stage}/gcp-wif-credentials-config`, `arn:aws:ssm:${this.region}:${this.account}:parameter/ticker-calculator/${this.stage}/ticker-config`, ], }), ); new GuScheduledLambda(this, 'TickerCalculator', { app: AppName, functionName: `${AppName}-${this.stage}`, runtime: Runtime.NODEJS_20_X, handler: 'lambda.handler', fileName: `${AppName}.zip`, rules: scheduleRules, role, environment: { Stage: this.stage, }, timeout: Duration.minutes(2), loggingFormat: LoggingFormat.TEXT, monitoringConfiguration: this.stage === 'PROD' ? { toleratedErrorPercentage: 0, snsTopicName: 'alarms-handler-topic-PROD', } : { noMonitoring: true }, }); } }