cdk/lib/dynamic-fronts.ts (82 lines of code) (raw):
import { GuParameter, type GuStack } from '@guardian/cdk/lib/constructs/core';
import { GuLambdaFunction } from '@guardian/cdk/lib/constructs/lambda';
import {
AccountPrincipal,
Effect,
ManagedPolicy,
PolicyDocument,
PolicyStatement,
Role,
ServicePrincipal,
} from 'aws-cdk-lib/aws-iam';
import { Runtime } from 'aws-cdk-lib/aws-lambda';
import type { IBucket } from 'aws-cdk-lib/aws-s3';
import { CfnOutput } from 'aws-cdk-lib/core';
import { Construct } from 'constructs';
interface DynamicFrontsProps {
destBucket: IBucket;
}
export class DynamicFronts extends Construct {
constructor(scope: GuStack, name: string, props: DynamicFrontsProps) {
super(scope, name);
const base_path = 'dynamic/curation';
const lambdaRole = new Role(this, 'FetcherRole', {
//The role name needs to be short for cross-cloud federation or you
//get an incomprehensible error!
roleName: `dynamic-fronts-fetcher-${scope.stage}`,
assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
managedPolicies: [
ManagedPolicy.fromAwsManagedPolicyName(
'service-role/AWSLambdaBasicExecutionRole',
),
],
inlinePolicies: {
S3Put: new PolicyDocument({
statements: [
new PolicyStatement({
effect: Effect.ALLOW,
actions: ['s3:PutObject', 's3:GetObject'],
resources: [`${props.destBucket.bucketArn}/${base_path}/*`],
}),
],
}),
},
});
const fetcher = new GuLambdaFunction(scope, 'DynamicFrontsFetcher', {
fileName: 'dynamic-fronts-fetcher.zip',
handler: 'main.handler',
functionName: `dynamic-fetcher-${scope.stage}`,
runtime: Runtime.NODEJS_20_X,
app: 'dynamic-fronts-fetcher',
memorySize: 256,
environment: {
BUCKET_NAME: props.destBucket.bucketName,
BASE_PATH: base_path,
},
role: lambdaRole,
});
const dataTechAcctParam = new GuParameter(scope, 'DynamicFrontsSrcAcct', {
fromSSM: true,
default: `/INFRA/recipes-backend/dynamic-fronts-fetcher/data-tech-account-id`,
type: 'String',
});
const xar = new Role(this, 'XAR', {
inlinePolicies: {
invokeFetcher: new PolicyDocument({
statements: [
new PolicyStatement({
effect: Effect.ALLOW,
resources: [fetcher.functionArn],
actions: ['lambda:InvokeFunction'],
}),
],
}),
},
assumedBy: new AccountPrincipal(dataTechAcctParam.valueAsString),
});
new CfnOutput(this, 'XARNameOutput', {
description:
'Cross-account role for Airflow to trigger the dynamic fronts fetcher',
value: xar.roleArn,
key: 'DynamicFrontsFetcherXAR',
});
}
}