Managing multiple AWS Accounts and Environments with CDK.
Markus Loupeen
Posted on February 26, 2023
This is just a small post that will be followed up later with pipeline examples.
We do not want our CDK applications to know much about how and where they are deployed, instead it is all defined in a small private npm package that contains all account information.
Here is how we have it, so we can import it in multiple projects and pipelines.
import { Annotations, Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';
export const DeploymentRegion = {
EU_NORTH_1: 'eu-north-1',
EU_CENTRAL_1: 'eu-central-1',
};
export const ApplicationStack = {
DEV: 'dev',
TEST: 'test',
QA: 'qa',
PRODUCTION: 'production',
};
type ApplicationStackType = (typeof ApplicationStack)[keyof typeof ApplicationStack];
type DeploymentRegionType = (typeof DeploymentRegion)[keyof typeof DeploymentRegion];
export class AwsAccount {
private static accounts: AwsAccount[] = [];
// -- Applications --
// - Production -
static readonly APP1_PRODUCTION = new AwsAccount('APP1_Production', '100000000001', ApplicationStack.PRODUCTION, [DeploymentRegion.EU_NORTH_1, DeploymentRegion.EU_CENTRAL_1], true);
// - QA -
static readonly APP1_QA = new AwsAccount('APP1_QA', '100000000002', ApplicationStack.QA, [DeploymentRegion.EU_NORTH_1, DeploymentRegion.EU_CENTRAL_1], true,);
// - Test -
static readonly APP1_TEST = new AwsAccount('APP1_Test', '100000000003', ApplicationStack.TEST);
// - Dev -
static readonly APP1_DEV = new AwsAccount('APP1_Dev', '100000000004', ApplicationStack.TEST);
static readonly APP2_DEV = new AwsAccount('APP2_Dev', '200000000001', ApplicationStack.TEST);
// -- Aws Core --
static readonly AUDIT = new AwsAccount('Audit', '900000000010', ApplicationStack.PRODUCTION);
static readonly LOG_ARCHIVE = new AwsAccount('Log archive', '900000000011', ApplicationStack.PRODUCTION);
// -- Infrastructure --
static readonly OPS = new AwsAccount('OPS', '000000000001', ApplicationStack.PRODUCTION);
private constructor(
public readonly name: string,
public readonly accountId: string,
public readonly stack: ApplicationStackType,
public readonly deploymentRegions: DeploymentRegionType[] = [DeploymentRegion.EU_NORTH_1],
public readonly approveBeforeDeploy: boolean = false,
) {
AwsAccount.accounts.push(this);
}
static fromScope(scope?: Construct): AwsAccount | undefined {
if (!scope) {
return undefined;
}
const accountNumber = Stack.of(scope).account;
const account = this.accounts.find((acc) => acc.accountId === accountNumber);
if (account) return account;
Annotations.of(scope).addError(`Couldn't find account [${account}] in AwsAccount array!`);
return undefined;
}
}
In next post I will show you how we utilize this in pipelines to make life esier.
💖 💪 🙅 🚩
Markus Loupeen
Posted on February 26, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.