postgres/cdk/lib/giant.ts (97 lines of code) (raw):

import type { GuStackProps } from '@guardian/cdk/lib/constructs/core'; import { GuStack, } from '@guardian/cdk/lib/constructs/core'; import { GuVpc, SubnetType } from '@guardian/cdk/lib/constructs/ec2/vpc'; import type { App } from 'aws-cdk-lib'; import { CfnOutput, Duration, SecretValue, Tags } from 'aws-cdk-lib'; import { InstanceClass, InstanceSize, InstanceType, Port, SecurityGroup, } from 'aws-cdk-lib/aws-ec2'; import { Credentials, DatabaseInstance, DatabaseInstanceEngine, PostgresEngineVersion, StorageType, } from 'aws-cdk-lib/aws-rds'; export class Giant extends GuStack { constructor(scope: App, id: string, props: GuStackProps) { super(scope, id, props); const vpc = GuVpc.fromIdParameter( this, 'GiantVPC', ); const dbStorage = 20; const DATABASE_MASTER_USER = 'giant_master'; const DATABASE_PORT = 5432; const databaseSecurityGroup = new SecurityGroup( this, 'DatabaseSecurityGroup', { vpc: vpc, }, ); const database = new DatabaseInstance(this, 'Database', { vpc: vpc, vpcSubnets: { subnets: GuVpc.subnetsFromParameter(this, { type: SubnetType.PRIVATE, }), }, engine: DatabaseInstanceEngine.postgres({ version: PostgresEngineVersion.VER_15 }), allowMajorVersionUpgrade: true, allocatedStorage: dbStorage, maxAllocatedStorage: dbStorage + 20, autoMinorVersionUpgrade: true, instanceType: InstanceType.of( InstanceClass.T4G, this.stage === 'PROD' ? InstanceSize.MICRO : InstanceSize.MICRO, ), instanceIdentifier: `giant-db-${this.stage}`, databaseName: 'giant', deletionProtection: true, deleteAutomatedBackups: false, cloudwatchLogsExports: ['postgresql'], iamAuthentication: true, multiAz: false, publiclyAccessible: false, storageEncrypted: true, storageType: StorageType.GP3, monitoringInterval: Duration.minutes(1), port: DATABASE_PORT, securityGroups: [databaseSecurityGroup], credentials: Credentials.fromGeneratedSecret(DATABASE_MASTER_USER, { secretName: `${props.stack}-postgres-${props.stage}`, }), }); // Enable nightly backups (via https://github.com/guardian/aws-backup) Tags.of(database).add("devx-backup-enabled", "true"); const dbAccessSecurityGroup = new SecurityGroup(this, 'db-access', { vpc: vpc, allowAllOutbound: false, }); dbAccessSecurityGroup.addEgressRule( databaseSecurityGroup, Port.tcp(DATABASE_PORT), 'Allow DB access', ); databaseSecurityGroup.addIngressRule( dbAccessSecurityGroup, Port.tcp(DATABASE_PORT), ); new CfnOutput(this, 'DbAccessSecurityGroup', { exportName: `${props.stack}-postgres-${props.stage}-DbAccessSecurityGroup`, value: dbAccessSecurityGroup.securityGroupId, }); new CfnOutput(this, 'PostgresDbSecretArn', { exportName: `${props.stack}-postgres-${props.stage}-PostgresDbSecretArn`, value: database.secret?.secretArn ?? '', }); } }