@guardian/cdk 49.4.1 → 49.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -101,30 +101,30 @@ const newCdkProject = async (props) => {
101
101
  });
102
102
  const commands = (0, utils_1.getCommands)(config.packageManager, config.cdkDir);
103
103
  if (config.init) {
104
- core_1.CliUx.ux.action.start(chalk_1.default.yellow("Installing dependencies. This may take a while..."));
104
+ core_1.ux.action.start(chalk_1.default.yellow("Installing dependencies. This may take a while..."));
105
105
  await commands.installDependencies();
106
- core_1.CliUx.ux.action.stop();
106
+ core_1.ux.action.stop();
107
107
  }
108
108
  // Run `eslint --fix` on the generated files instead of trying to generate code that completely satisfies the linter
109
109
  await (0, exec_1.execute)("./node_modules/.bin/eslint", ["lib/** bin/**", "--ext .ts", "--no-error-on-unmatched-pattern", "--fix"], {
110
110
  cwd: config.cdkDir,
111
111
  });
112
- core_1.CliUx.ux.action.start(chalk_1.default.yellow("Running lint check..."));
112
+ core_1.ux.action.start(chalk_1.default.yellow("Running lint check..."));
113
113
  await commands.lint();
114
- core_1.CliUx.ux.action.stop();
115
- core_1.CliUx.ux.action.start(chalk_1.default.yellow("Running tests..."));
114
+ core_1.ux.action.stop();
115
+ core_1.ux.action.start(chalk_1.default.yellow("Running tests..."));
116
116
  await commands.test();
117
- core_1.CliUx.ux.action.stop();
118
- core_1.CliUx.ux.action.start(chalk_1.default.yellow("Running initial synthesis..."));
117
+ core_1.ux.action.stop();
118
+ core_1.ux.action.start(chalk_1.default.yellow("Running initial synthesis..."));
119
119
  await commands.synth();
120
- core_1.CliUx.ux.action.stop();
120
+ core_1.ux.action.stop();
121
121
  console.log(chalk_1.default.green("Success! Here's a summary of the created files:"));
122
122
  const tree = await (0, exec_1.execute)("tree", ["-I 'node_modules|cdk.out'"], {
123
123
  cwd: config.cdkDir,
124
124
  });
125
125
  console.log(tree);
126
126
  const docsUrl = "https://github.com/guardian/cdk/tree/main/docs";
127
- core_1.CliUx.ux.url(chalk_1.default.green(`Please see the docs (${docsUrl}) for next steps.`), docsUrl);
127
+ core_1.ux.url(chalk_1.default.green(`Please see the docs (${docsUrl}) for next steps.`), docsUrl);
128
128
  return Promise.resolve(0);
129
129
  };
130
130
  exports.newCdkProject = newCdkProject;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/bin/commands/new-project/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"fs\";\nimport { basename, dirname, join } from \"path\";\nimport { CliUx } from \"@oclif/core\";\nimport chalk from \"chalk\";\nimport kebabCase from \"lodash.kebabcase\";\nimport type { CliCommandResponse } from \"../../../types/cli\";\nimport { execute } from \"../../../utils/exec\";\nimport { gitRootOrCwd } from \"../../../utils/git\";\nimport { constructApp } from \"./utils/app\";\nimport { Imports } from \"./utils/imports\";\nimport { buildDirectory } from \"./utils/init\";\nimport { constructTest } from \"./utils/snapshot\";\nimport { constructStack } from \"./utils/stack\";\nimport type { Name } from \"./utils/utils\";\nimport { getCommands, pascalCase } from \"./utils/utils\";\n\nexport type PackageManager = \"npm\" | \"yarn\";\n\ninterface NewProjectProps {\n init: boolean;\n app: string;\n stack: string;\n stages: string[];\n yamlTemplateLocation?: string;\n packageManager: PackageManager;\n}\n\ninterface NewProjectConfig extends Omit<NewProjectProps, \"stack\" | \"app\"> {\n cdkDir: string;\n appPath: string;\n appName: Name;\n stackPath: string;\n stackName: Name;\n testPath: string;\n}\n\nconst checkPathExists = (path: string): void => {\n if (!existsSync(path)) {\n throw new Error(`File not found - ${path}`);\n }\n};\n\nconst checkPathDoesNotExist = (path: string): void => {\n if (existsSync(path)) {\n throw new Error(`There is already a file at - ${path}`);\n }\n};\n\nfunction validateConfig(config: NewProjectConfig): void {\n if (!config.init) {\n checkPathExists(config.cdkDir);\n }\n checkPathDoesNotExist(config.appPath); // TODO: Update the app file if it already exists\n checkPathDoesNotExist(config.stackPath);\n\n if (config.yamlTemplateLocation) {\n checkPathExists(config.yamlTemplateLocation);\n }\n}\n\nfunction getConfig(props: NewProjectProps): NewProjectConfig {\n const { init, app, stack, stages, yamlTemplateLocation, packageManager } = props;\n\n const rootDir = gitRootOrCwd();\n const cdkDir = join(rootDir, \"/cdk\");\n\n const appName = pascalCase(app);\n const kebabAppName = kebabCase(appName);\n const stackName = pascalCase(stack);\n const kebabStackName = kebabCase(stackName);\n\n const config: NewProjectConfig = {\n init,\n yamlTemplateLocation,\n stages,\n cdkDir,\n appName: {\n kebab: kebabAppName,\n pascal: appName,\n },\n appPath: `${cdkDir}/bin/${kebabAppName}.ts`,\n stackName: {\n kebab: kebabStackName,\n pascal: stackName,\n },\n stackPath: `${cdkDir}/lib/${kebabAppName}.ts`,\n testPath: `${cdkDir}/lib/${kebabAppName}.test.ts`,\n packageManager,\n };\n\n validateConfig(config);\n\n return config;\n}\n\nexport const newCdkProject = async (props: NewProjectProps): CliCommandResponse => {\n console.log(\"Starting CDK generator\");\n\n const config = getConfig(props);\n\n if (config.init) {\n buildDirectory({ outputDir: config.cdkDir });\n }\n\n console.log(`New app ${config.appName.pascal} will be written to ${config.appPath}`);\n console.log(`New stack ${config.stackName.pascal} will be written to ${config.stackPath}`);\n\n // bin directory\n await constructApp({\n appName: config.appName,\n outputFile: \"cdk.ts\",\n outputDir: dirname(config.appPath),\n stack: config.stackName,\n imports: Imports.newAppImports(config.appName),\n stages: config.stages,\n });\n\n // lib directory\n await constructStack({\n imports: Imports.newStackImports(),\n appName: config.appName,\n outputFile: basename(config.stackPath),\n outputDir: dirname(config.stackPath),\n yamlTemplateLocation: config.yamlTemplateLocation,\n });\n\n // lib directory\n await constructTest({\n imports: Imports.newTestImports(config.appName),\n stackName: config.stackName,\n appName: config.appName,\n outputFile: basename(config.testPath),\n outputDir: dirname(config.stackPath),\n });\n\n const commands = getCommands(config.packageManager, config.cdkDir);\n\n if (config.init) {\n CliUx.ux.action.start(chalk.yellow(\"Installing dependencies. This may take a while...\"));\n await commands.installDependencies();\n CliUx.ux.action.stop();\n }\n\n // Run `eslint --fix` on the generated files instead of trying to generate code that completely satisfies the linter\n await execute(\n \"./node_modules/.bin/eslint\",\n [\"lib/** bin/**\", \"--ext .ts\", \"--no-error-on-unmatched-pattern\", \"--fix\"],\n {\n cwd: config.cdkDir,\n }\n );\n\n CliUx.ux.action.start(chalk.yellow(\"Running lint check...\"));\n await commands.lint();\n CliUx.ux.action.stop();\n\n CliUx.ux.action.start(chalk.yellow(\"Running tests...\"));\n await commands.test();\n CliUx.ux.action.stop();\n\n CliUx.ux.action.start(chalk.yellow(\"Running initial synthesis...\"));\n await commands.synth();\n CliUx.ux.action.stop();\n\n console.log(chalk.green(\"Success! Here's a summary of the created files:\"));\n const tree = await execute(\"tree\", [\"-I 'node_modules|cdk.out'\"], {\n cwd: config.cdkDir,\n });\n console.log(tree);\n\n const docsUrl = \"https://github.com/guardian/cdk/tree/main/docs\";\n CliUx.ux.url(chalk.green(`Please see the docs (${docsUrl}) for next steps.`), docsUrl);\n\n return Promise.resolve(0);\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/bin/commands/new-project/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"fs\";\nimport { basename, dirname, join } from \"path\";\nimport { ux } from \"@oclif/core\";\nimport chalk from \"chalk\";\nimport kebabCase from \"lodash.kebabcase\";\nimport type { CliCommandResponse } from \"../../../types/cli\";\nimport { execute } from \"../../../utils/exec\";\nimport { gitRootOrCwd } from \"../../../utils/git\";\nimport { constructApp } from \"./utils/app\";\nimport { Imports } from \"./utils/imports\";\nimport { buildDirectory } from \"./utils/init\";\nimport { constructTest } from \"./utils/snapshot\";\nimport { constructStack } from \"./utils/stack\";\nimport type { Name } from \"./utils/utils\";\nimport { getCommands, pascalCase } from \"./utils/utils\";\n\nexport type PackageManager = \"npm\" | \"yarn\";\n\ninterface NewProjectProps {\n init: boolean;\n app: string;\n stack: string;\n stages: string[];\n yamlTemplateLocation?: string;\n packageManager: PackageManager;\n}\n\ninterface NewProjectConfig extends Omit<NewProjectProps, \"stack\" | \"app\"> {\n cdkDir: string;\n appPath: string;\n appName: Name;\n stackPath: string;\n stackName: Name;\n testPath: string;\n}\n\nconst checkPathExists = (path: string): void => {\n if (!existsSync(path)) {\n throw new Error(`File not found - ${path}`);\n }\n};\n\nconst checkPathDoesNotExist = (path: string): void => {\n if (existsSync(path)) {\n throw new Error(`There is already a file at - ${path}`);\n }\n};\n\nfunction validateConfig(config: NewProjectConfig): void {\n if (!config.init) {\n checkPathExists(config.cdkDir);\n }\n checkPathDoesNotExist(config.appPath); // TODO: Update the app file if it already exists\n checkPathDoesNotExist(config.stackPath);\n\n if (config.yamlTemplateLocation) {\n checkPathExists(config.yamlTemplateLocation);\n }\n}\n\nfunction getConfig(props: NewProjectProps): NewProjectConfig {\n const { init, app, stack, stages, yamlTemplateLocation, packageManager } = props;\n\n const rootDir = gitRootOrCwd();\n const cdkDir = join(rootDir, \"/cdk\");\n\n const appName = pascalCase(app);\n const kebabAppName = kebabCase(appName);\n const stackName = pascalCase(stack);\n const kebabStackName = kebabCase(stackName);\n\n const config: NewProjectConfig = {\n init,\n yamlTemplateLocation,\n stages,\n cdkDir,\n appName: {\n kebab: kebabAppName,\n pascal: appName,\n },\n appPath: `${cdkDir}/bin/${kebabAppName}.ts`,\n stackName: {\n kebab: kebabStackName,\n pascal: stackName,\n },\n stackPath: `${cdkDir}/lib/${kebabAppName}.ts`,\n testPath: `${cdkDir}/lib/${kebabAppName}.test.ts`,\n packageManager,\n };\n\n validateConfig(config);\n\n return config;\n}\n\nexport const newCdkProject = async (props: NewProjectProps): CliCommandResponse => {\n console.log(\"Starting CDK generator\");\n\n const config = getConfig(props);\n\n if (config.init) {\n buildDirectory({ outputDir: config.cdkDir });\n }\n\n console.log(`New app ${config.appName.pascal} will be written to ${config.appPath}`);\n console.log(`New stack ${config.stackName.pascal} will be written to ${config.stackPath}`);\n\n // bin directory\n await constructApp({\n appName: config.appName,\n outputFile: \"cdk.ts\",\n outputDir: dirname(config.appPath),\n stack: config.stackName,\n imports: Imports.newAppImports(config.appName),\n stages: config.stages,\n });\n\n // lib directory\n await constructStack({\n imports: Imports.newStackImports(),\n appName: config.appName,\n outputFile: basename(config.stackPath),\n outputDir: dirname(config.stackPath),\n yamlTemplateLocation: config.yamlTemplateLocation,\n });\n\n // lib directory\n await constructTest({\n imports: Imports.newTestImports(config.appName),\n stackName: config.stackName,\n appName: config.appName,\n outputFile: basename(config.testPath),\n outputDir: dirname(config.stackPath),\n });\n\n const commands = getCommands(config.packageManager, config.cdkDir);\n\n if (config.init) {\n ux.action.start(chalk.yellow(\"Installing dependencies. This may take a while...\"));\n await commands.installDependencies();\n ux.action.stop();\n }\n\n // Run `eslint --fix` on the generated files instead of trying to generate code that completely satisfies the linter\n await execute(\n \"./node_modules/.bin/eslint\",\n [\"lib/** bin/**\", \"--ext .ts\", \"--no-error-on-unmatched-pattern\", \"--fix\"],\n {\n cwd: config.cdkDir,\n }\n );\n\n ux.action.start(chalk.yellow(\"Running lint check...\"));\n await commands.lint();\n ux.action.stop();\n\n ux.action.start(chalk.yellow(\"Running tests...\"));\n await commands.test();\n ux.action.stop();\n\n ux.action.start(chalk.yellow(\"Running initial synthesis...\"));\n await commands.synth();\n ux.action.stop();\n\n console.log(chalk.green(\"Success! Here's a summary of the created files:\"));\n const tree = await execute(\"tree\", [\"-I 'node_modules|cdk.out'\"], {\n cwd: config.cdkDir,\n });\n console.log(tree);\n\n const docsUrl = \"https://github.com/guardian/cdk/tree/main/docs\";\n ux.url(chalk.green(`Please see the docs (${docsUrl}) for next steps.`), docsUrl);\n\n return Promise.resolve(0);\n};\n"]}
@@ -14,6 +14,7 @@ interface NamedSsmParameterPaths {
14
14
  PrimaryVpcPrivateSubnets: SsmParameterPath;
15
15
  PrimaryVpcPublicSubnets: SsmParameterPath;
16
16
  FastlyCustomerId: SsmParameterPath;
17
+ DevxGlobalDistBucket: SsmParameterPath;
17
18
  }
18
19
  export declare const VPC_SSM_PARAMETER_PREFIX = "/account/vpc";
19
20
  export declare const NAMED_SSM_PARAMETER_PATHS: NamedSsmParameterPaths;
@@ -1 +1 @@
1
- {"version":3,"file":"ssm-parameter-paths.d.ts","sourceRoot":"","sources":["../../src/constants/ssm-parameter-paths.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,sBAAsB;IAC9B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,EAAE,gBAAgB,CAAC;IACpC,kBAAkB,EAAE,gBAAgB,CAAC;IACrC,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,wBAAwB,EAAE,gBAAgB,CAAC;IAC3C,uBAAuB,EAAE,gBAAgB,CAAC;IAC1C,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AAEvD,eAAO,MAAM,yBAAyB,EAAE,sBA0CvC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,EAE/B,CAAC"}
1
+ {"version":3,"file":"ssm-parameter-paths.d.ts","sourceRoot":"","sources":["../../src/constants/ssm-parameter-paths.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,sBAAsB;IAC9B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,EAAE,gBAAgB,CAAC;IACpC,kBAAkB,EAAE,gBAAgB,CAAC;IACrC,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,wBAAwB,EAAE,gBAAgB,CAAC;IAC3C,uBAAuB,EAAE,gBAAgB,CAAC;IAC1C,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,oBAAoB,EAAE,gBAAgB,CAAC;CACxC;AAED,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AAEvD,eAAO,MAAM,yBAAyB,EAAE,sBA8CvC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,EAE/B,CAAC"}
@@ -38,6 +38,10 @@ exports.NAMED_SSM_PARAMETER_PATHS = {
38
38
  path: `${exports.VPC_SSM_PARAMETER_PREFIX}/primary/subnets/public`,
39
39
  description: "A comma-separated list of public subnets",
40
40
  },
41
+ DevxGlobalDistBucket: {
42
+ path: "/organisation/services/artifact.bucket",
43
+ description: "SSM parameter containing the S3 bucket name holding organisation-level DevX artifacts",
44
+ },
41
45
  FastlyCustomerId: {
42
46
  path: "/account/external/fastly/customer.id",
43
47
  description: "SSM parameter containing the Fastly Customer ID. Can be obtained from https://manage.fastly.com/account/company by an admin",
@@ -1 +1 @@
1
- {"version":3,"file":"ssm-parameter-paths.js","sourceRoot":"","sources":["../../src/constants/ssm-parameter-paths.ts"],"names":[],"mappings":";;;AAsBa,QAAA,wBAAwB,GAAG,cAAc,CAAC;AAE1C,QAAA,yBAAyB,GAA2B;IAC/D,WAAW,EAAE;QACX,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,+DAA+D;QAC5E,QAAQ,EAAE,IAAI;KACf;IACD,iBAAiB,EAAE;QACjB,IAAI,EAAE,uCAAuC;QAC7C,WAAW,EAAE,mEAAmE;KACjF;IACD,kBAAkB,EAAE;QAClB,IAAI,EAAE,mCAAmC;QACzC,WAAW,EAAE,4EAA4E;QACzF,aAAa,EAAE,2BAA2B;KAC3C;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,qCAAqC;KACnD;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,qFAAqF;QAClG,aAAa,EAAE,yBAAyB;KACzC;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,GAAG,gCAAwB,aAAa;QAC9C,WAAW,EAAE,2FAA2F;KACzG;IACD,wBAAwB,EAAE;QACxB,IAAI,EAAE,GAAG,gCAAwB,0BAA0B;QAC3D,WAAW,EAAE,2CAA2C;KACzD;IACD,uBAAuB,EAAE;QACvB,IAAI,EAAE,GAAG,gCAAwB,yBAAyB;QAC1D,WAAW,EAAE,0CAA0C;KACxD;IACD,gBAAgB,EAAE;QAChB,IAAI,EAAE,sCAAsC;QAC5C,WAAW,EACT,6HAA6H;QAC/H,QAAQ,EAAE,IAAI;KACf;CACF,CAAC;AAEW,QAAA,uBAAuB,GAAuB,MAAM,CAAC,MAAM,CACtE,iCAAyB,CACJ,CAAC","sourcesContent":["export interface SsmParameterPath {\n path: string;\n description: string;\n optional?: boolean;\n\n // Recommended naming convention for target resource, such as an S3 bucket.\n // $account is substituted as the account name.\n namingPattern?: string;\n}\n\ninterface NamedSsmParameterPaths {\n Anghammarad: SsmParameterPath;\n LoggingStreamName: SsmParameterPath;\n DistributionBucket: SsmParameterPath;\n AccessLoggingBucket: SsmParameterPath;\n ConfigurationBucket: SsmParameterPath;\n PrimaryVpcId: SsmParameterPath;\n PrimaryVpcPrivateSubnets: SsmParameterPath;\n PrimaryVpcPublicSubnets: SsmParameterPath;\n FastlyCustomerId: SsmParameterPath;\n}\n\nexport const VPC_SSM_PARAMETER_PREFIX = \"/account/vpc\";\n\nexport const NAMED_SSM_PARAMETER_PATHS: NamedSsmParameterPaths = {\n Anghammarad: {\n path: \"/account/services/anghammarad.topic.arn\",\n description: \"SSM parameter containing the ARN of the Anghammarad SNS topic\",\n optional: true,\n },\n LoggingStreamName: {\n path: \"/account/services/logging.stream.name\",\n description: \"SSM parameter containing the Name (not ARN) on the kinesis stream\",\n },\n DistributionBucket: {\n path: \"/account/services/artifact.bucket\",\n description: \"SSM parameter containing the S3 bucket name holding distribution artifacts\",\n namingPattern: \"com-gu-$account-artifacts\",\n },\n AccessLoggingBucket: {\n path: \"/account/services/access-logging/bucket\",\n description: \"S3 bucket to store your access logs\",\n },\n ConfigurationBucket: {\n path: \"/account/services/private.config.bucket\",\n description: \"SSM parameter containing the S3 bucket name holding the app's private configuration\",\n namingPattern: \"com-gu-$account-configs\",\n },\n PrimaryVpcId: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/id`,\n description: \"Virtual Private Cloud to run EC2 instances within. Should NOT be the account default VPC.\",\n },\n PrimaryVpcPrivateSubnets: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/subnets/private`,\n description: \"A comma-separated list of private subnets\",\n },\n PrimaryVpcPublicSubnets: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/subnets/public`,\n description: \"A comma-separated list of public subnets\",\n },\n FastlyCustomerId: {\n path: \"/account/external/fastly/customer.id\",\n description:\n \"SSM parameter containing the Fastly Customer ID. Can be obtained from https://manage.fastly.com/account/company by an admin\",\n optional: true,\n },\n};\n\nexport const ALL_SSM_PARAMETER_PATHS: SsmParameterPath[] = Object.values(\n NAMED_SSM_PARAMETER_PATHS\n) as SsmParameterPath[];\n"]}
1
+ {"version":3,"file":"ssm-parameter-paths.js","sourceRoot":"","sources":["../../src/constants/ssm-parameter-paths.ts"],"names":[],"mappings":";;;AAuBa,QAAA,wBAAwB,GAAG,cAAc,CAAC;AAE1C,QAAA,yBAAyB,GAA2B;IAC/D,WAAW,EAAE;QACX,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,+DAA+D;QAC5E,QAAQ,EAAE,IAAI;KACf;IACD,iBAAiB,EAAE;QACjB,IAAI,EAAE,uCAAuC;QAC7C,WAAW,EAAE,mEAAmE;KACjF;IACD,kBAAkB,EAAE;QAClB,IAAI,EAAE,mCAAmC;QACzC,WAAW,EAAE,4EAA4E;QACzF,aAAa,EAAE,2BAA2B;KAC3C;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,qCAAqC;KACnD;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,yCAAyC;QAC/C,WAAW,EAAE,qFAAqF;QAClG,aAAa,EAAE,yBAAyB;KACzC;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,GAAG,gCAAwB,aAAa;QAC9C,WAAW,EAAE,2FAA2F;KACzG;IACD,wBAAwB,EAAE;QACxB,IAAI,EAAE,GAAG,gCAAwB,0BAA0B;QAC3D,WAAW,EAAE,2CAA2C;KACzD;IACD,uBAAuB,EAAE;QACvB,IAAI,EAAE,GAAG,gCAAwB,yBAAyB;QAC1D,WAAW,EAAE,0CAA0C;KACxD;IACD,oBAAoB,EAAE;QACpB,IAAI,EAAE,wCAAwC;QAC9C,WAAW,EAAE,uFAAuF;KACrG;IACD,gBAAgB,EAAE;QAChB,IAAI,EAAE,sCAAsC;QAC5C,WAAW,EACT,6HAA6H;QAC/H,QAAQ,EAAE,IAAI;KACf;CACF,CAAC;AAEW,QAAA,uBAAuB,GAAuB,MAAM,CAAC,MAAM,CACtE,iCAAyB,CACJ,CAAC","sourcesContent":["export interface SsmParameterPath {\n path: string;\n description: string;\n optional?: boolean;\n\n // Recommended naming convention for target resource, such as an S3 bucket.\n // $account is substituted as the account name.\n namingPattern?: string;\n}\n\ninterface NamedSsmParameterPaths {\n Anghammarad: SsmParameterPath;\n LoggingStreamName: SsmParameterPath;\n DistributionBucket: SsmParameterPath;\n AccessLoggingBucket: SsmParameterPath;\n ConfigurationBucket: SsmParameterPath;\n PrimaryVpcId: SsmParameterPath;\n PrimaryVpcPrivateSubnets: SsmParameterPath;\n PrimaryVpcPublicSubnets: SsmParameterPath;\n FastlyCustomerId: SsmParameterPath;\n DevxGlobalDistBucket: SsmParameterPath;\n}\n\nexport const VPC_SSM_PARAMETER_PREFIX = \"/account/vpc\";\n\nexport const NAMED_SSM_PARAMETER_PATHS: NamedSsmParameterPaths = {\n Anghammarad: {\n path: \"/account/services/anghammarad.topic.arn\",\n description: \"SSM parameter containing the ARN of the Anghammarad SNS topic\",\n optional: true,\n },\n LoggingStreamName: {\n path: \"/account/services/logging.stream.name\",\n description: \"SSM parameter containing the Name (not ARN) on the kinesis stream\",\n },\n DistributionBucket: {\n path: \"/account/services/artifact.bucket\",\n description: \"SSM parameter containing the S3 bucket name holding distribution artifacts\",\n namingPattern: \"com-gu-$account-artifacts\",\n },\n AccessLoggingBucket: {\n path: \"/account/services/access-logging/bucket\",\n description: \"S3 bucket to store your access logs\",\n },\n ConfigurationBucket: {\n path: \"/account/services/private.config.bucket\",\n description: \"SSM parameter containing the S3 bucket name holding the app's private configuration\",\n namingPattern: \"com-gu-$account-configs\",\n },\n PrimaryVpcId: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/id`,\n description: \"Virtual Private Cloud to run EC2 instances within. Should NOT be the account default VPC.\",\n },\n PrimaryVpcPrivateSubnets: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/subnets/private`,\n description: \"A comma-separated list of private subnets\",\n },\n PrimaryVpcPublicSubnets: {\n path: `${VPC_SSM_PARAMETER_PREFIX}/primary/subnets/public`,\n description: \"A comma-separated list of public subnets\",\n },\n DevxGlobalDistBucket: {\n path: \"/organisation/services/artifact.bucket\",\n description: \"SSM parameter containing the S3 bucket name holding organisation-level DevX artifacts\",\n },\n FastlyCustomerId: {\n path: \"/account/external/fastly/customer.id\",\n description:\n \"SSM parameter containing the Fastly Customer ID. Can be obtained from https://manage.fastly.com/account/company by an admin\",\n optional: true,\n },\n};\n\nexport const ALL_SSM_PARAMETER_PATHS: SsmParameterPath[] = Object.values(\n NAMED_SSM_PARAMETER_PATHS\n) as SsmParameterPath[];\n"]}
@@ -3,6 +3,7 @@ import type { AlarmProps } from "aws-cdk-lib/aws-cloudwatch";
3
3
  import type { AppIdentity, GuStack } from "../core";
4
4
  export interface GuAlarmProps extends AlarmProps, AppIdentity {
5
5
  snsTopicName: string;
6
+ okAction?: boolean;
6
7
  }
7
8
  export interface Http5xxAlarmProps extends Omit<GuAlarmProps, "snsTopicName" | "evaluationPeriods" | "metric" | "period" | "threshold" | "treatMissingData" | "app"> {
8
9
  tolerated5xxPercentage: number;
@@ -1 +1 @@
1
- {"version":3,"file":"alarm.d.ts","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/alarm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAI7D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEpD,MAAM,WAAW,YAAa,SAAQ,UAAU,EAAE,WAAW;IAC3D,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBACf,SAAQ,IAAI,CACV,YAAY,EACZ,cAAc,GAAG,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,kBAAkB,GAAG,KAAK,CACtG;IACD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wCAAwC,CAAC,EAAE,MAAM,CAAC;CACnD;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,OAAQ,SAAQ,KAAK;gBACpB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;CAU5D"}
1
+ {"version":3,"file":"alarm.d.ts","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/alarm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAI7D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEpD,MAAM,WAAW,YAAa,SAAQ,UAAU,EAAE,WAAW;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBACf,SAAQ,IAAI,CACV,YAAY,EACZ,cAAc,GAAG,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,kBAAkB,GAAG,KAAK,CACtG;IACD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wCAAwC,CAAC,EAAE,MAAM,CAAC;CACnD;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,OAAQ,SAAQ,KAAK;gBACpB,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;CAa5D"}
@@ -23,11 +23,14 @@ const aws_sns_1 = require("aws-cdk-lib/aws-sns");
23
23
  class GuAlarm extends aws_cloudwatch_1.Alarm {
24
24
  constructor(scope, id, props) {
25
25
  const { region, account } = scope;
26
- const { snsTopicName, actionsEnabled = true } = props;
26
+ const { snsTopicName, actionsEnabled = true, okAction } = props;
27
27
  super(scope, id, { ...props, actionsEnabled });
28
28
  const topicArn = `arn:aws:sns:${region}:${account}:${snsTopicName}`;
29
29
  const snsTopic = aws_sns_1.Topic.fromTopicArn(scope, `SnsTopicFor${id}`, topicArn);
30
30
  this.addAlarmAction(new aws_cloudwatch_actions_1.SnsAction(snsTopic));
31
+ if (okAction) {
32
+ this.addOkAction(new aws_cloudwatch_actions_1.SnsAction(snsTopic));
33
+ }
31
34
  }
32
35
  }
33
36
  exports.GuAlarm = GuAlarm;
@@ -1 +1 @@
1
- {"version":3,"file":"alarm.js","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/alarm.ts"],"names":[],"mappings":";;;AAAA,+DAAmD;AAEnD,+EAA+D;AAC/D,iDAA4C;AAiB5C;;;;;;;;;;;;;;;GAeG;AACH,MAAa,OAAQ,SAAQ,sBAAK;IAChC,YAAY,KAAc,EAAE,EAAU,EAAE,KAAmB;QACzD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QAClC,MAAM,EAAE,YAAY,EAAE,cAAc,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QAEtD,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QAE/C,MAAM,QAAQ,GAAW,eAAe,MAAM,IAAI,OAAO,IAAI,YAAY,EAAE,CAAC;QAC5E,MAAM,QAAQ,GAAW,eAAK,CAAC,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;QACjF,IAAI,CAAC,cAAc,CAAC,IAAI,kCAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/C,CAAC;CACF;AAXD,0BAWC","sourcesContent":["import { Alarm } from \"aws-cdk-lib/aws-cloudwatch\";\nimport type { AlarmProps } from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport type { ITopic } from \"aws-cdk-lib/aws-sns\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport interface GuAlarmProps extends AlarmProps, AppIdentity {\n snsTopicName: string;\n}\n\nexport interface Http5xxAlarmProps\n extends Omit<\n GuAlarmProps,\n \"snsTopicName\" | \"evaluationPeriods\" | \"metric\" | \"period\" | \"threshold\" | \"treatMissingData\" | \"app\"\n > {\n tolerated5xxPercentage: number;\n numberOfMinutesAboveThresholdBeforeAlarm?: number;\n}\n\n/**\n * Creates a CloudWatch alarm which sends notifications to the specified SNS topic.\n *\n * Alarm actions are enabled by default.\n *\n * To enable the alarm only in PROD, use the value of `Stage`:\n * ```typescript\n * new GuAlarm(stack, \"alarm\", {\n * // other required props\n * actionsEnabled: this.stage === \"PROD\",\n * });\n * ```\n *\n * This library provides an implementation of some commonly used alarms, which require less boilerplate than this construct,\n * for example the [[`GuAlb5xxPercentageAlarm`]]. Prefer using these more specific implementations where possible.\n */\nexport class GuAlarm extends Alarm {\n constructor(scope: GuStack, id: string, props: GuAlarmProps) {\n const { region, account } = scope;\n const { snsTopicName, actionsEnabled = true } = props;\n\n super(scope, id, { ...props, actionsEnabled });\n\n const topicArn: string = `arn:aws:sns:${region}:${account}:${snsTopicName}`;\n const snsTopic: ITopic = Topic.fromTopicArn(scope, `SnsTopicFor${id}`, topicArn);\n this.addAlarmAction(new SnsAction(snsTopic));\n }\n}\n"]}
1
+ {"version":3,"file":"alarm.js","sourceRoot":"","sources":["../../../src/constructs/cloudwatch/alarm.ts"],"names":[],"mappings":";;;AAAA,+DAAmD;AAEnD,+EAA+D;AAC/D,iDAA4C;AAkB5C;;;;;;;;;;;;;;;GAeG;AACH,MAAa,OAAQ,SAAQ,sBAAK;IAChC,YAAY,KAAc,EAAE,EAAU,EAAE,KAAmB;QACzD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QAClC,MAAM,EAAE,YAAY,EAAE,cAAc,GAAG,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;QAEhE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QAE/C,MAAM,QAAQ,GAAW,eAAe,MAAM,IAAI,OAAO,IAAI,YAAY,EAAE,CAAC;QAC5E,MAAM,QAAQ,GAAW,eAAK,CAAC,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;QACjF,IAAI,CAAC,cAAc,CAAC,IAAI,kCAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC7C,IAAI,QAAQ,EAAE;YACZ,IAAI,CAAC,WAAW,CAAC,IAAI,kCAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;SAC3C;IACH,CAAC;CACF;AAdD,0BAcC","sourcesContent":["import { Alarm } from \"aws-cdk-lib/aws-cloudwatch\";\nimport type { AlarmProps } from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport type { ITopic } from \"aws-cdk-lib/aws-sns\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport interface GuAlarmProps extends AlarmProps, AppIdentity {\n snsTopicName: string;\n okAction?: boolean;\n}\n\nexport interface Http5xxAlarmProps\n extends Omit<\n GuAlarmProps,\n \"snsTopicName\" | \"evaluationPeriods\" | \"metric\" | \"period\" | \"threshold\" | \"treatMissingData\" | \"app\"\n > {\n tolerated5xxPercentage: number;\n numberOfMinutesAboveThresholdBeforeAlarm?: number;\n}\n\n/**\n * Creates a CloudWatch alarm which sends notifications to the specified SNS topic.\n *\n * Alarm actions are enabled by default.\n *\n * To enable the alarm only in PROD, use the value of `Stage`:\n * ```typescript\n * new GuAlarm(stack, \"alarm\", {\n * // other required props\n * actionsEnabled: this.stage === \"PROD\",\n * });\n * ```\n *\n * This library provides an implementation of some commonly used alarms, which require less boilerplate than this construct,\n * for example the [[`GuAlb5xxPercentageAlarm`]]. Prefer using these more specific implementations where possible.\n */\nexport class GuAlarm extends Alarm {\n constructor(scope: GuStack, id: string, props: GuAlarmProps) {\n const { region, account } = scope;\n const { snsTopicName, actionsEnabled = true, okAction } = props;\n\n super(scope, id, { ...props, actionsEnabled });\n\n const topicArn: string = `arn:aws:sns:${region}:${account}:${snsTopicName}`;\n const snsTopic: ITopic = Topic.fromTopicArn(scope, `SnsTopicFor${id}`, topicArn);\n this.addAlarmAction(new SnsAction(snsTopic));\n if (okAction) {\n this.addOkAction(new SnsAction(snsTopic));\n }\n }\n}\n"]}
@@ -13,7 +13,19 @@ import { AppAccess } from "../../types";
13
13
  import type { GuAsgCapacity, GuDomainName } from "../../types";
14
14
  import type { AmigoProps } from "../../types/amigo";
15
15
  export interface AccessLoggingProps {
16
+ /**
17
+ * Enable (load balancer) access logs.
18
+ *
19
+ * Note, you will need to specify a region in your stack declaration to use
20
+ * this.
21
+ * See`https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-elasticloadbalancingv2.ApplicationLoadBalancer.html#logwbraccesswbrlogsbucket-prefix`
22
+ */
16
23
  enabled: boolean;
24
+ /**
25
+ * S3 prefix for the logs.
26
+ *
27
+ * @defaultValue no prefix
28
+ */
17
29
  prefix?: string;
18
30
  }
19
31
  /**
@@ -29,279 +41,136 @@ export interface AccessLoggingProps {
29
41
  * to Kinesis will be configured automatically via the [[`GuEc2App`]] pattern.
30
42
  */
31
43
  export interface ApplicationLoggingProps {
44
+ /**
45
+ * Enables forwarding of application logs to the Guardian ELK stack.
46
+ *
47
+ * Note, to work, you will need to also do the following non-CDK things:
48
+ *
49
+ * 1. Include the `cdk-base` Amigo role in your AMI.
50
+ * 2. Log to `journald`. We recommend doing this by logging to `stdout` and
51
+ * using `systemd` to start your app
52
+ * 3. Confirm that your [[`systemdUnitName`]] is configured properly.
53
+ *
54
+ * Unless you have explicitly opted-out, appropriate IAM permissions for
55
+ * logging to Kinesis will be configured automatically via the [[`GuEc2App`]]
56
+ * pattern.
57
+ *
58
+ * @see https://github.com/guardian/amigo/tree/main/roles/cdk-base
59
+ */
32
60
  enabled: boolean;
33
61
  /**
34
- * Defaults to app name. That is, if your app runs as `<app>.service`
35
- * (e.g. `janus.service`), this will 'just work'.
62
+ * This needs to match the name of your SystemD unit.
63
+ *
64
+ * If your systemd unit is not `<app>.service` set this value.
36
65
  *
37
- * If it runs with a non-standard name, you will need to override the default
38
- * behavour. I.e. if your app is running as `some-different-name.service`, then
39
- * this prop should be set to `some-different-name`.
66
+ * @defaultValue `<app>.service`
40
67
  */
41
68
  systemdUnitName?: string;
42
69
  }
70
+ /**
71
+ * @privateRemarks we should rename this to AlarmsProps.
72
+ */
43
73
  export interface Alarms {
74
+ /**
75
+ * Name of the target (SNS Topic) for alarm notifications.
76
+ */
44
77
  snsTopicName: string;
78
+ /**
79
+ * Enable the 5xx alarm with settings.
80
+ */
45
81
  http5xxAlarm: false | Http5xxAlarmProps;
82
+ /**
83
+ * Enable the unhealthy instances alarm.
84
+ */
46
85
  unhealthyInstancesAlarm: boolean;
86
+ /**
87
+ * Internal flag - users of this library should ignore this setting.
88
+ */
47
89
  noMonitoring?: false;
48
90
  }
49
- /**
50
- * Configuration options for the [[`GuEc2App`]] pattern.
51
- *
52
- * To grant EC2 instances additional IAM permissions, use the `roleConfiguration` prop. For example,
53
- * to allow your app to write to DynamoDB:
54
- *
55
- * ```typescript
56
- * // other props
57
- * roleConfiguration: {
58
- * additionalPolicies: [new GuDynamoDBWritePolicy(stack, "DynamoTable", { tableName: "my-dynamo-table" })],
59
- * }
60
- * ```
61
- *
62
- * To create alarms (recommended), use:
63
- * ```typescript
64
- * // other props
65
- * monitoringConfiguration: {
66
- * snsTopicName: "alerts-topic-for-my-team",
67
- * http5xxAlarm: {
68
- * tolerated5xxPercentage: 1,
69
- * },
70
- * unhealthyInstancesAlarm: true,
71
- * }
72
- * ```
73
- *
74
- * To opt out of creating alarms, use:
75
- *```typescript
76
- * // other props
77
- * monitoringConfiguration: { noMonitoring: true }
78
- * ```
79
- *
80
- * To automatically ship application logs from `stdout` to ELK, use:
81
- *
82
- * ```typescript
83
- * {
84
- * // other props
85
- * applicationLogging: { enabled: true }
86
- * }
87
- * ```
88
- *
89
- * For more details on the requirements for application log shipping, see [[`ApplicationLoggingProps`]].
90
- *
91
- * To enable access logging for your load balancer, you can specify the prefix to write the logs to.
92
- * The S3 bucket used to hold these access logs must be specified in SSM at `/account/services/access-logging/bucket`
93
- * You must specify a region in your stack declaration if you are to use this prop, as specified here:
94
- * https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-elasticloadbalancingv2.ApplicationLoadBalancer.html#logwbraccesswbrlogsbucket-prefix
95
- * For example:
96
- * ```typescript
97
- * {
98
- * // other props
99
- * accessLogging: {
100
- * enabled: true,
101
- * prefix: "my-application-logs"
102
- * }
103
- * }
104
- *
105
- * If you would like to enable access logging at the root of the S3 bucket (ie without a prefix), you can omit the prefix
106
- * For example:
107
- * ```typescript
108
- * {
109
- * // other props
110
- * accessLogging: {
111
- * enabled: true,
112
- * }
113
- * }
114
- * ```
115
- */
116
91
  export interface GuEc2AppProps extends AppIdentity {
92
+ /**
93
+ * User data for the autoscaling group.
94
+ */
117
95
  userData: GuUserDataProps | string;
96
+ /**
97
+ * Network access restrictions for your load balancer.
98
+ *
99
+ * Note, this merely provides defence in depth; you should, for example, limit
100
+ * access to the VPN and then treat that as sufficient. Instead, use Google
101
+ * Auth for human access, or a suitable machine auth mechanism.
102
+ */
118
103
  access: AppAccess;
104
+ /**
105
+ * The port your application runs on.
106
+ */
119
107
  applicationPort: number;
108
+ /**
109
+ * Configure IAM roles for autoscaling group EC2 instances.
110
+ */
120
111
  roleConfiguration?: GuInstanceRoleProps;
112
+ /**
113
+ * Enable and configure alarms.
114
+ */
121
115
  monitoringConfiguration: Alarms | NoMonitoring;
116
+ /**
117
+ * EC2 instance type. Note, ensure your code is built for the same
118
+ * architecture family (arm64 - 'Graviton' instances - or x64).
119
+ */
122
120
  instanceType: InstanceType;
121
+ /**
122
+ * Enable and configures application logs.
123
+ */
123
124
  applicationLogging?: ApplicationLoggingProps;
125
+ /**
126
+ * Enable and configures access logs.
127
+ */
124
128
  accessLogging?: AccessLoggingProps;
129
+ /**
130
+ * Add block devices (additional storage).
131
+ */
125
132
  blockDevices?: BlockDevice[];
133
+ /**
134
+ * Autoscaling group min and max sizes.
135
+ */
126
136
  scaling: GuAsgCapacity;
137
+ /**
138
+ * Specify certificate for the load balancer.
139
+ */
127
140
  certificateProps?: GuDomainName;
141
+ /**
142
+ * Disable imdsv2. Most of the time you should not set this.
143
+ *
144
+ * @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html
145
+ */
128
146
  withoutImdsv2?: boolean;
147
+ /**
148
+ * Configure Amigo image recipe.
149
+ */
129
150
  imageRecipe?: string | AmigoProps;
151
+ /**
152
+ * Specify the VPC to use.
153
+ *
154
+ * @see https://github.com/guardian/aws-account-setup
155
+ */
130
156
  vpc?: IVpc;
157
+ /**
158
+ * Specify private subnets if using a non-default VPC or (generally
159
+ * discouraged) to limit to a subset of the available subnets.
160
+ */
131
161
  privateSubnets?: ISubnet[];
162
+ /**
163
+ * Specify private subnets if using a non-default VPC or (generally
164
+ * discouraged) to limit to a subset of the available subnets.
165
+ */
132
166
  publicSubnets?: ISubnet[];
133
167
  }
134
168
  /**
135
- * Pattern which creates the resources needed to run an application on EC2 instances.
136
- * For convenience, you may wish to use [[`GuPlayApp`]] or [[`GuNodeApp`]], which extend this class.
137
- *
138
- * This pattern will grant your EC2 instances a number of commonly needed IAM permissions. For more information on
139
- * this, see [[`GuInstanceRole`]]. To add additional permissions to your EC2 instances, see [[`GuEc2AppProps`]].
140
- *
141
- * This pattern will automatically create security groups/rules which allow for:
142
- * 1. Incoming traffic over HTTPS (from the whole internet or from the specified CIDR ranges, depending on the
143
- * [[`AppAccess`]] specified).
144
- * 2. Communication between the load balancer and the EC2 instances over HTTP, via the specified application port.
145
- * 3. Outbound traffic from your EC2 instances over HTTPS (to enable communication with third-party APIs).
146
- *
147
- * Example usage for a public facing app (open to the internet):
148
- * ```typescript
149
- * new GuEc2App(stack, {
150
- * applicationPort: 1234,
151
- * app: "app-name",
152
- * access: { scope: AccessScope.PUBLIC },
153
- * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),
154
- * certificateProps:{
155
- * domainName: "domain-name-for-your-application.example",
156
- * },
157
- * monitoringConfiguration: {
158
- * snsTopicName: "alerts-topic-for-my-team",
159
- * http5xxAlarm: {
160
- * tolerated5xxPercentage: 1,
161
- * },
162
- * unhealthyInstancesAlarm: true,
163
- * },
164
- * userData: {
165
- * distributable: {
166
- * fileName: "app-name.deb",
167
- * executionStatement: `dpkg -i /app-name/app-name.deb`,
168
- * }
169
- * },
170
- * });
171
- * ```
172
- *
173
- * Example usage for an app which is restricted to specific CIDR ranges:
174
- * ```typescript
175
- * new GuEc2App(stack, {
176
- * applicationPort: 1234,
177
- * app: "app-name",
178
- * access: {
179
- * scope: AccessScope.RESTRICTED,
180
- * cidrRanges: [Peer.ipv4("192.168.1.1/32"), Peer.ipv4("8.8.8.8/32")],
181
- * },
182
- * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),
183
- * certificateProps:{
184
- * domainName: "domain-name-for-your-application.example",
185
- * },
186
- * monitoringConfiguration: {
187
- * snsTopicName: "alerts-topic-for-my-team",
188
- * http5xxAlarm: {
189
- * tolerated5xxPercentage: 1,
190
- * },
191
- * unhealthyInstancesAlarm: true,
192
- * }
193
- * userData: {
194
- * distributable: {
195
- * fileName: "app-name.deb",
196
- * executionStatement: `dpkg -i /app-name/app-name.deb`,
197
- * }
198
- * },
199
- * });
200
- * ```
201
- *
202
- * ### Varying values by stage
203
- *
204
- * There are times when you want a resource's configuration to be stage aware,
205
- * for example the number of instances in an ASG.
206
- *
207
- * To do this, we can use a simple ternary:
208
- * ```typescript
209
- * new GuEc2App(this, {
210
- * // other required properties
211
- * scaling: this.stage === "PROD" ? { minimumInstances: 6 } : { minimumInstances: 1 }
212
- * });
213
- * ```
214
- *
215
- * If multiple properties need to be stage aware, consider encoding this into the `props` of the calling class:
216
- *
217
- * ```typescript
218
- * export interface MyAppProps extends GuStackProps {
219
- * domainName: string;
220
- * scaling: GuAsgCapacity;
221
- * monitoringConfiguration: Alarms | NoMonitoring;
222
- * }
223
- *
224
- * export class MyApp extends GuStack {
225
- * private static app = "cdk-playground";
226
- *
227
- * constructor(scope: App, id: string, props: MyAppProps) {
228
- * const { stage, domainName, scaling, monitoringConfiguration } = props;
229
- *
230
- * super(scope, id, props);
231
- *
232
- * new GuPlayApp(this, {
233
- * app: "my-app",
234
- * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MICRO),
235
- * access: { scope: AccessScope.PUBLIC },
236
- * userData: {
237
- * distributable: {
238
- * fileName: `my-app.deb`,
239
- * executionStatement: `dpkg -i /my-app/my-app.deb`,
240
- * },
241
- * },
242
- * certificateProps: {
243
- * domainName,
244
- * },
245
- * monitoringConfiguration,
246
- * scaling,
247
- * });
248
- * }
249
- * }
250
- *
251
- * new MyApp(app, "MyApp-CODE", {
252
- * stage: "CODE",
253
- * domainName: "my-app.code.dev-gutools.co.uk",
254
- * scaling: { minimumInstances: 1 },
255
- * monitoringConfiguration: { noMonitoring: true },
256
- * });
257
- *
258
- * new MyApp(app, "MyApp-PROD", {
259
- * stage: "PROD",
260
- * domainName: "my-app.prod.gutools.co.uk",
261
- * scaling: { minimumInstances: 6 },
262
- * monitoringConfiguration: {
263
- * // config to enable alarms in PROD
264
- * },
265
- * });
266
- * ```
267
- *
268
- * If you _must_ support a non-standard VPC setup, it's possible to override the VPC and subnet selection into which
269
- * instances will be started. You need to set the three props below in order for this to work:
270
- * vpc: this must be an IVpc instance indicating the VPC to deploy into (usually obtained from `Vpc.fromVpcAttributes`)
271
- * privateSubnets: a list of ISubnet indicating the subnets for the autoscaling group to deploy instances into (usually
272
- * obtained from `GuVpc.subnets`)
273
- * publicSubnets: a list of ISubnet indicating the subnets for the loadbalancer to use, if the loadbalancer
274
- * is intended for public access (usually obtained from `GuVpc.subnets`)
275
- * On the other hand, if the access is private, then an "internal" loadbalancer is used in the `privateSubnets` list.
276
- * Please note that no checking is applied to the subnet lists to ensure that they correspond to the vpc given; as
277
- * an advanced feature it is assumed that the caller ensures this. If the subnets are mismatched then the resulting
278
- * Cloudformation will fail to deploy.
279
- *
280
- * ### Customising the infrastructure generated by this pattern
281
- *
282
- * Although we allow users to customise many aspects of their infrastructure via [[`GuEc2AppProps`]], it's possible
283
- * that there are less common use-cases which are currently unsupported via the API. In these circumstances escape
284
- * hatches can be used to override specific resources in the stack.
285
- *
286
- * In order to do this:
169
+ * Pattern which creates the resources needed to run an application on EC2
170
+ * behind a load balancer. For convenience, you may wish to use [[`GuPlayApp`]]
171
+ * or [[`GuNodeApp`]], which extend this class.
287
172
  *
288
- * 1. Create desired resource using Guardian or AWS constructs, for example:
289
- * ```typescript
290
- * const sg = new GuSecurityGroup(
291
- * // custom parameters
292
- * );
293
- * ```
294
- * 2. Access the CloudFormation version of the resource that you wish to customise, for example:
295
- * ```typescript
296
- * const pattern = new GuEc2App(
297
- * // all parameters
298
- * )
299
- * const cfnLb = pattern.loadBalancer.node.defaultChild as CfnLoadBalancer;
300
- * ```
301
- * 3. Replace the resource generated by the pattern with your bespoke resource, for example:
302
- * ```typescript
303
- * cfnLb.securityGroups = [sg.securityGroupId];
304
- * ```
173
+ * See props for further details.
305
174
  */
306
175
  export declare class GuEc2App extends Construct {
307
176
  readonly vpc: IVpc;
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/patterns/ec2-app/base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/patterns/ec2-app/base.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAS,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAI9E,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAc,MAAM,8BAA8B,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEnF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAmD,MAAM,uBAAuB,CAAC;AAErG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EACxB,0BAA0B,EAC3B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;;;;;;;;OAeG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,YAAY,EAAE,KAAK,GAAG,iBAAiB,CAAC;IACxC;;OAEG;IACH,uBAAuB,EAAE,OAAO,CAAC;IACjC;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD;;OAEG;IACH,QAAQ,EAAE,eAAe,GAAG,MAAM,CAAC;IACnC;;;;;;OAMG;IACH,MAAM,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,iBAAiB,CAAC,EAAE,mBAAmB,CAAC;IACxC;;OAEG;IACH,uBAAuB,EAAE,MAAM,GAAG,YAAY,CAAC;IAC/C;;;OAGG;IACH,YAAY,EAAE,YAAY,CAAC;IAC3B;;OAEG;IACH,kBAAkB,CAAC,EAAE,uBAAuB,CAAC;IAC7C;;OAEG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC;;OAEG;IACH,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B;;OAEG;IACH,OAAO,EAAE,aAAa,CAAC;IACvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,YAAY,CAAC;IAChC;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAClC;;;;OAIG;IACH,GAAG,CAAC,EAAE,IAAI,CAAC;IACX;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;IAE3B;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC;CAC3B;AAUD;;;;;;GAMG;AACH,qBAAa,QAAS,SAAQ,SAAS;IASrC,SAAgB,GAAG,EAAE,IAAI,CAAC;IAC1B,SAAgB,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5C,SAAgB,YAAY,EAAE,yBAAyB,CAAC;IACxD,SAAgB,gBAAgB,EAAE,kBAAkB,CAAC;IACrD,SAAgB,QAAQ,EAAE,0BAA0B,CAAC;IACrD,SAAgB,WAAW,EAAE,wBAAwB,CAAC;gBAE1C,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa;CAyKjD"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GuEc2App = void 0;
4
+ /* eslint "@guardian/tsdoc-required/tsdoc-required": 2 -- to begin rolling this out for public APIs. */
4
5
  const aws_cdk_lib_1 = require("aws-cdk-lib");
5
6
  const aws_autoscaling_1 = require("aws-cdk-lib/aws-autoscaling");
6
7
  const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
@@ -24,176 +25,11 @@ function restrictedCidrRanges(ranges) {
24
25
  }));
25
26
  }
26
27
  /**
27
- * Pattern which creates the resources needed to run an application on EC2 instances.
28
- * For convenience, you may wish to use [[`GuPlayApp`]] or [[`GuNodeApp`]], which extend this class.
28
+ * Pattern which creates the resources needed to run an application on EC2
29
+ * behind a load balancer. For convenience, you may wish to use [[`GuPlayApp`]]
30
+ * or [[`GuNodeApp`]], which extend this class.
29
31
  *
30
- * This pattern will grant your EC2 instances a number of commonly needed IAM permissions. For more information on
31
- * this, see [[`GuInstanceRole`]]. To add additional permissions to your EC2 instances, see [[`GuEc2AppProps`]].
32
- *
33
- * This pattern will automatically create security groups/rules which allow for:
34
- * 1. Incoming traffic over HTTPS (from the whole internet or from the specified CIDR ranges, depending on the
35
- * [[`AppAccess`]] specified).
36
- * 2. Communication between the load balancer and the EC2 instances over HTTP, via the specified application port.
37
- * 3. Outbound traffic from your EC2 instances over HTTPS (to enable communication with third-party APIs).
38
- *
39
- * Example usage for a public facing app (open to the internet):
40
- * ```typescript
41
- * new GuEc2App(stack, {
42
- * applicationPort: 1234,
43
- * app: "app-name",
44
- * access: { scope: AccessScope.PUBLIC },
45
- * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),
46
- * certificateProps:{
47
- * domainName: "domain-name-for-your-application.example",
48
- * },
49
- * monitoringConfiguration: {
50
- * snsTopicName: "alerts-topic-for-my-team",
51
- * http5xxAlarm: {
52
- * tolerated5xxPercentage: 1,
53
- * },
54
- * unhealthyInstancesAlarm: true,
55
- * },
56
- * userData: {
57
- * distributable: {
58
- * fileName: "app-name.deb",
59
- * executionStatement: `dpkg -i /app-name/app-name.deb`,
60
- * }
61
- * },
62
- * });
63
- * ```
64
- *
65
- * Example usage for an app which is restricted to specific CIDR ranges:
66
- * ```typescript
67
- * new GuEc2App(stack, {
68
- * applicationPort: 1234,
69
- * app: "app-name",
70
- * access: {
71
- * scope: AccessScope.RESTRICTED,
72
- * cidrRanges: [Peer.ipv4("192.168.1.1/32"), Peer.ipv4("8.8.8.8/32")],
73
- * },
74
- * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),
75
- * certificateProps:{
76
- * domainName: "domain-name-for-your-application.example",
77
- * },
78
- * monitoringConfiguration: {
79
- * snsTopicName: "alerts-topic-for-my-team",
80
- * http5xxAlarm: {
81
- * tolerated5xxPercentage: 1,
82
- * },
83
- * unhealthyInstancesAlarm: true,
84
- * }
85
- * userData: {
86
- * distributable: {
87
- * fileName: "app-name.deb",
88
- * executionStatement: `dpkg -i /app-name/app-name.deb`,
89
- * }
90
- * },
91
- * });
92
- * ```
93
- *
94
- * ### Varying values by stage
95
- *
96
- * There are times when you want a resource's configuration to be stage aware,
97
- * for example the number of instances in an ASG.
98
- *
99
- * To do this, we can use a simple ternary:
100
- * ```typescript
101
- * new GuEc2App(this, {
102
- * // other required properties
103
- * scaling: this.stage === "PROD" ? { minimumInstances: 6 } : { minimumInstances: 1 }
104
- * });
105
- * ```
106
- *
107
- * If multiple properties need to be stage aware, consider encoding this into the `props` of the calling class:
108
- *
109
- * ```typescript
110
- * export interface MyAppProps extends GuStackProps {
111
- * domainName: string;
112
- * scaling: GuAsgCapacity;
113
- * monitoringConfiguration: Alarms | NoMonitoring;
114
- * }
115
- *
116
- * export class MyApp extends GuStack {
117
- * private static app = "cdk-playground";
118
- *
119
- * constructor(scope: App, id: string, props: MyAppProps) {
120
- * const { stage, domainName, scaling, monitoringConfiguration } = props;
121
- *
122
- * super(scope, id, props);
123
- *
124
- * new GuPlayApp(this, {
125
- * app: "my-app",
126
- * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MICRO),
127
- * access: { scope: AccessScope.PUBLIC },
128
- * userData: {
129
- * distributable: {
130
- * fileName: `my-app.deb`,
131
- * executionStatement: `dpkg -i /my-app/my-app.deb`,
132
- * },
133
- * },
134
- * certificateProps: {
135
- * domainName,
136
- * },
137
- * monitoringConfiguration,
138
- * scaling,
139
- * });
140
- * }
141
- * }
142
- *
143
- * new MyApp(app, "MyApp-CODE", {
144
- * stage: "CODE",
145
- * domainName: "my-app.code.dev-gutools.co.uk",
146
- * scaling: { minimumInstances: 1 },
147
- * monitoringConfiguration: { noMonitoring: true },
148
- * });
149
- *
150
- * new MyApp(app, "MyApp-PROD", {
151
- * stage: "PROD",
152
- * domainName: "my-app.prod.gutools.co.uk",
153
- * scaling: { minimumInstances: 6 },
154
- * monitoringConfiguration: {
155
- * // config to enable alarms in PROD
156
- * },
157
- * });
158
- * ```
159
- *
160
- * If you _must_ support a non-standard VPC setup, it's possible to override the VPC and subnet selection into which
161
- * instances will be started. You need to set the three props below in order for this to work:
162
- * vpc: this must be an IVpc instance indicating the VPC to deploy into (usually obtained from `Vpc.fromVpcAttributes`)
163
- * privateSubnets: a list of ISubnet indicating the subnets for the autoscaling group to deploy instances into (usually
164
- * obtained from `GuVpc.subnets`)
165
- * publicSubnets: a list of ISubnet indicating the subnets for the loadbalancer to use, if the loadbalancer
166
- * is intended for public access (usually obtained from `GuVpc.subnets`)
167
- * On the other hand, if the access is private, then an "internal" loadbalancer is used in the `privateSubnets` list.
168
- * Please note that no checking is applied to the subnet lists to ensure that they correspond to the vpc given; as
169
- * an advanced feature it is assumed that the caller ensures this. If the subnets are mismatched then the resulting
170
- * Cloudformation will fail to deploy.
171
- *
172
- * ### Customising the infrastructure generated by this pattern
173
- *
174
- * Although we allow users to customise many aspects of their infrastructure via [[`GuEc2AppProps`]], it's possible
175
- * that there are less common use-cases which are currently unsupported via the API. In these circumstances escape
176
- * hatches can be used to override specific resources in the stack.
177
- *
178
- * In order to do this:
179
- *
180
- * 1. Create desired resource using Guardian or AWS constructs, for example:
181
- * ```typescript
182
- * const sg = new GuSecurityGroup(
183
- * // custom parameters
184
- * );
185
- * ```
186
- * 2. Access the CloudFormation version of the resource that you wish to customise, for example:
187
- * ```typescript
188
- * const pattern = new GuEc2App(
189
- * // all parameters
190
- * )
191
- * const cfnLb = pattern.loadBalancer.node.defaultChild as CfnLoadBalancer;
192
- * ```
193
- * 3. Replace the resource generated by the pattern with your bespoke resource, for example:
194
- * ```typescript
195
- * cfnLb.securityGroups = [sg.securityGroupId];
196
- * ```
32
+ * See props for further details.
197
33
  */
198
34
  class GuEc2App extends constructs_1.Construct {
199
35
  constructor(scope, props) {
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/patterns/ec2-app/base.ts"],"names":[],"mappings":";;;AAAA,6CAA6C;AAE7C,iEAA0D;AAE1D,iDAA2C;AAC3C,uFAA6E;AAC7E,+CAA4C;AAC5C,2CAAuC;AACvC,+CAAuF;AACvF,8CAAqD;AAErD,8DAA8E;AAE9E,4DAAiG;AAEjG,gDAAqG;AACrG,8CAA0E;AAE1E,8CAAgF;AAChF,kEAIwC;AACxC,uCAAwC;AA+HxC,SAAS,oBAAoB,CAAC,MAAe;IAC3C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5B,KAAK;QACL,IAAI,EAAE,cAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QACnB,WAAW,EAAE,iCAAiC,KAAK,CAAC,QAAQ,EAAE;KAC/D,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2KG;AACH,MAAa,QAAS,SAAQ,sBAAS;IAgBrC,YAAY,KAAc,EAAE,KAAoB;QAC9C,MAAM,EACJ,MAAM,EACN,aAAa,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAClC,GAAG;QACH,6FAA6F;QAC7F,kBAAkB,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EACvC,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,EACvB,iBAAiB,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,EAAE,EACzE,OAAO,EAAE,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,CAAC,EAAE,EACtE,QAAQ,EACR,aAAa,EACb,WAAW,EACX,GAAG,GAAG,WAAK,CAAC,eAAe,CAAC,KAAK,EAAE,kBAAW,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,EAC1E,cAAc,GAAG,WAAK,CAAC,oBAAoB,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAU,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,EACrF,aAAa,GAAG,WAAK,CAAC,oBAAoB,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAU,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GACpF,GAAG,KAAK,CAAC;QAEV,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,oCAAoC;QAEvD,sEAAsE;QACtE,iDAAiD;QACjD,IAAI,kBAAkB,CAAC,OAAO,IAAI,iBAAiB,CAAC,kBAAkB,EAAE;YACtE,MAAM,IAAI,KAAK,CACb,6GAA6G;gBAC3G,kGAAkG,CACrG,CAAC;SACH;QAED,iBAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAE3B,MAAM,WAAW,GACf,OAAO,gBAAgB,KAAK,WAAW;YACrC,CAAC,CAAC,IAAI,mBAAa,CAAC,KAAK,EAAE;gBACvB,GAAG;gBACH,UAAU,EAAE,gBAAgB,CAAC,UAAU;gBACvC,YAAY,EAAE,gBAAgB,CAAC,YAAY;aAC5C,CAAC;YACJ,CAAC,CAAC,SAAS,CAAC;QAEhB,MAAM,wBAAwB,GAC5B,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,aAAa;YACpD,CAAC,CAAC,CAAC,IAAI,8BAAwB,CAAC,KAAK,EAAE,8BAA8B,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;YAC/F,CAAC,CAAC,EAAE,CAAC;QAET,MAAM,uBAAuB,GAAwB;YACnD,kBAAkB,EAAE,iBAAiB,CAAC,kBAAkB;YACxD,kBAAkB,EAAE,wBAAwB,CAAC,MAAM,CAAC,iBAAiB,CAAC,kBAAkB,IAAI,EAAE,CAAC;SAChG,CAAC;QAEF,MAAM,gBAAgB,GAAG,IAAI,gCAAkB,CAAC,KAAK,EAAE,kBAAkB,EAAE;YACzE,GAAG;YACH,GAAG;YACH,YAAY;YACZ,gBAAgB;YAChB,gBAAgB;YAChB,aAAa;YACb,IAAI,EAAE,IAAI,oBAAc,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,uBAAuB,EAAE,CAAC;YACpE,WAAW,EAAE,6BAAW,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,sBAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,QAAQ,EAAE,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,wBAAU,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;YACxG,UAAU,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE;YACvC,GAAG,CAAC,YAAY,IAAI,EAAE,YAAY,EAAE,CAAC;YACrC,WAAW;SACZ,CAAC,CAAC;QAEH,4EAA4E;QAC5E,qCAAqC;QACrC,kBAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAC3B,wBAAY,CAAC,uBAAuB,EACpC,mCAA4B,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,aAAa,CAC9D,CAAC;QAEF,IAAI,kBAAkB,CAAC,OAAO,EAAE;YAC9B,oEAAoE;YACpE,qCAAqC;YACrC,kBAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAC3B,wBAAY,CAAC,YAAY,EACzB,kBAAkB,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,eAAe,UAAU,CAAC,CAAC,CAAC,GAAG,GAAG,UAAU,CACxG,CAAC;SACH;QAED,MAAM,YAAY,GAAG,IAAI,yCAAyB,CAAC,KAAK,EAAE,cAAc,EAAE;YACxE,GAAG;YACH,GAAG;YACH,sJAAsJ;YACtJ,cAAc,EAAE,MAAM,CAAC,KAAK,KAAK,uBAAW,CAAC,QAAQ;YACrD,UAAU,EAAE;gBACV,OAAO,EAAE,MAAM,CAAC,KAAK,KAAK,uBAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa;aAChF;SACF,CAAC,CAAC;QAEH,IAAI,aAAa,CAAC,OAAO,EAAE;YACzB,MAAM,mBAAmB,GAAG,IAAI,wBAAiB,CAAC,KAAK,EAAE,qBAAqB,EAAE;gBAC9E,WAAW,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,WAAW;gBACtE,OAAO,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,IAAI;gBAC3D,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YAEH,YAAY,CAAC,aAAa,CACxB,eAAM,CAAC,cAAc,CACnB,KAAK,EACL,kBAAW,CAAC,UAAU,CAAC,KAAK,EAAE,qBAAqB,CAAC,EACpD,mBAAmB,CAAC,aAAa,CAClC,EACD,aAAa,CAAC,MAAM,CACrB,CAAC;SACH;QAED,MAAM,WAAW,GAAG,IAAI,wCAAwB,CAAC,KAAK,EAAE,aAAa,EAAE;YACrE,GAAG;YACH,GAAG;YACH,QAAQ,EAAE,gDAAmB,CAAC,IAAI;YAClC,OAAO,EAAE,CAAC,gBAAgB,CAAC;YAC3B,IAAI,EAAE,eAAe;SACtB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAI,0CAA0B,CAAC,KAAK,EAAE,UAAU,EAAE;YACjE,GAAG;YACH,YAAY;YACZ,WAAW;YACX,WAAW;YACX,+FAA+F;YAC/F,IAAI,EAAE,MAAM,CAAC,KAAK,KAAK,uBAAW,CAAC,MAAM,IAAI,OAAO,WAAW,KAAK,WAAW;SAChF,CAAC,CAAC;QAEH,gGAAgG;QAChG,IAAI,MAAM,CAAC,KAAK,KAAK,uBAAW,CAAC,MAAM,EAAE;YACvC,YAAY,CAAC,gBAAgB,CAC3B,IAAI,qBAAe,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,KAAK,sBAAsB,EAAE;gBAChE,GAAG;gBACH,GAAG;gBACH,WAAW,EAAE,2CAA2C;gBACxD,gBAAgB,EAAE,KAAK;gBACvB,SAAS,EAAE,oBAAoB,CAAC,MAAM,CAAC,UAAU,CAAC;aACnD,CAAC,CACH,CAAC;SACH;QAED,IAAI,CAAC,uBAAuB,CAAC,YAAY,EAAE;YACzC,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,uBAAuB,EAAE,GAAG,uBAAuB,CAAC;YAExF,IAAI,YAAY,EAAE;gBAChB,IAAI,oCAAuB,CAAC,KAAK,EAAE;oBACjC,GAAG;oBACH,YAAY;oBACZ,YAAY;oBACZ,GAAG,YAAY;iBAChB,CAAC,CAAC;aACJ;YACD,IAAI,uBAAuB,EAAE;gBAC3B,IAAI,sCAAyB,CAAC,KAAK,EAAE;oBACnC,GAAG;oBACH,WAAW;oBACX,YAAY;iBACb,CAAC,CAAC;aACJ;SACF;QAED,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF;AAzLD,4BAyLC","sourcesContent":["import { Duration, Tags } from \"aws-cdk-lib\";\nimport type { BlockDevice } from \"aws-cdk-lib/aws-autoscaling\";\nimport { HealthCheck } from \"aws-cdk-lib/aws-autoscaling\";\nimport type { InstanceType, IPeer, ISubnet, IVpc } from \"aws-cdk-lib/aws-ec2\";\nimport { Port } from \"aws-cdk-lib/aws-ec2\";\nimport { ApplicationProtocol } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport { Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { Construct } from \"constructs\";\nimport { AccessScope, MetadataKeys, NAMED_SSM_PARAMETER_PATHS } from \"../../constants\";\nimport { GuCertificate } from \"../../constructs/acm\";\nimport type { GuUserDataProps } from \"../../constructs/autoscaling\";\nimport { GuAutoScalingGroup, GuUserData } from \"../../constructs/autoscaling\";\nimport type { Http5xxAlarmProps, NoMonitoring } from \"../../constructs/cloudwatch\";\nimport { GuAlb5xxPercentageAlarm, GuUnhealthyInstancesAlarm } from \"../../constructs/cloudwatch\";\nimport type { GuStack } from \"../../constructs/core\";\nimport { AppIdentity, GuLoggingStreamNameParameter, GuStringParameter } from \"../../constructs/core\";\nimport { GuSecurityGroup, GuVpc, SubnetType } from \"../../constructs/ec2\";\nimport type { GuInstanceRoleProps } from \"../../constructs/iam\";\nimport { GuGetPrivateConfigPolicy, GuInstanceRole } from \"../../constructs/iam\";\nimport {\n GuApplicationLoadBalancer,\n GuApplicationTargetGroup,\n GuHttpsApplicationListener,\n} from \"../../constructs/loadbalancing\";\nimport { AppAccess } from \"../../types\";\nimport type { GuAsgCapacity, GuDomainName } from \"../../types\";\nimport type { AmigoProps } from \"../../types/amigo\";\n\nexport interface AccessLoggingProps {\n enabled: boolean;\n prefix?: string;\n}\n\n/**\n * To ship your application logs to ELK automatically, you must:\n *\n * 1. Set the `enabled` flag to true\n * 2. Include the `cdk-base` Amigo role in your AMI\n * 3. Log to `journald`. We recommend doing this by logging to `stdout` and\n * using `systemd` to start your app\n * 4. Confirm that your [[`systemdUnitName`]] is configured properly.\n *\n * Unless you have explicitly opted-out, appropriate IAM permissions for logging\n * to Kinesis will be configured automatically via the [[`GuEc2App`]] pattern.\n */\nexport interface ApplicationLoggingProps {\n enabled: boolean;\n /**\n * Defaults to app name. That is, if your app runs as `<app>.service`\n * (e.g. `janus.service`), this will 'just work'.\n *\n * If it runs with a non-standard name, you will need to override the default\n * behavour. I.e. if your app is running as `some-different-name.service`, then\n * this prop should be set to `some-different-name`.\n */\n systemdUnitName?: string;\n}\n\nexport interface Alarms {\n snsTopicName: string;\n http5xxAlarm: false | Http5xxAlarmProps;\n unhealthyInstancesAlarm: boolean;\n noMonitoring?: false;\n}\n\n/**\n * Configuration options for the [[`GuEc2App`]] pattern.\n *\n * To grant EC2 instances additional IAM permissions, use the `roleConfiguration` prop. For example,\n * to allow your app to write to DynamoDB:\n *\n * ```typescript\n * // other props\n * roleConfiguration: {\n * additionalPolicies: [new GuDynamoDBWritePolicy(stack, \"DynamoTable\", { tableName: \"my-dynamo-table\" })],\n * }\n * ```\n *\n * To create alarms (recommended), use:\n * ```typescript\n * // other props\n * monitoringConfiguration: {\n * snsTopicName: \"alerts-topic-for-my-team\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * },\n * unhealthyInstancesAlarm: true,\n * }\n * ```\n *\n * To opt out of creating alarms, use:\n *```typescript\n * // other props\n * monitoringConfiguration: { noMonitoring: true }\n * ```\n *\n * To automatically ship application logs from `stdout` to ELK, use:\n *\n * ```typescript\n * {\n * // other props\n * applicationLogging: { enabled: true }\n * }\n * ```\n *\n * For more details on the requirements for application log shipping, see [[`ApplicationLoggingProps`]].\n *\n * To enable access logging for your load balancer, you can specify the prefix to write the logs to.\n * The S3 bucket used to hold these access logs must be specified in SSM at `/account/services/access-logging/bucket`\n * You must specify a region in your stack declaration if you are to use this prop, as specified here:\n * https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-elasticloadbalancingv2.ApplicationLoadBalancer.html#logwbraccesswbrlogsbucket-prefix\n * For example:\n * ```typescript\n * {\n * // other props\n * accessLogging: {\n * enabled: true,\n * prefix: \"my-application-logs\"\n * }\n * }\n *\n * If you would like to enable access logging at the root of the S3 bucket (ie without a prefix), you can omit the prefix\n * For example:\n * ```typescript\n * {\n * // other props\n * accessLogging: {\n * enabled: true,\n * }\n * }\n * ```\n */\nexport interface GuEc2AppProps extends AppIdentity {\n userData: GuUserDataProps | string;\n access: AppAccess;\n applicationPort: number;\n roleConfiguration?: GuInstanceRoleProps;\n monitoringConfiguration: Alarms | NoMonitoring;\n instanceType: InstanceType;\n applicationLogging?: ApplicationLoggingProps;\n accessLogging?: AccessLoggingProps;\n blockDevices?: BlockDevice[];\n scaling: GuAsgCapacity;\n certificateProps?: GuDomainName;\n withoutImdsv2?: boolean;\n imageRecipe?: string | AmigoProps;\n vpc?: IVpc;\n privateSubnets?: ISubnet[];\n publicSubnets?: ISubnet[];\n}\n\nfunction restrictedCidrRanges(ranges: IPeer[]) {\n return ranges.map((range) => ({\n range,\n port: Port.tcp(443),\n description: `Allow access on port 443 from ${range.uniqueId}`,\n }));\n}\n\n/**\n * Pattern which creates the resources needed to run an application on EC2 instances.\n * For convenience, you may wish to use [[`GuPlayApp`]] or [[`GuNodeApp`]], which extend this class.\n *\n * This pattern will grant your EC2 instances a number of commonly needed IAM permissions. For more information on\n * this, see [[`GuInstanceRole`]]. To add additional permissions to your EC2 instances, see [[`GuEc2AppProps`]].\n *\n * This pattern will automatically create security groups/rules which allow for:\n * 1. Incoming traffic over HTTPS (from the whole internet or from the specified CIDR ranges, depending on the\n * [[`AppAccess`]] specified).\n * 2. Communication between the load balancer and the EC2 instances over HTTP, via the specified application port.\n * 3. Outbound traffic from your EC2 instances over HTTPS (to enable communication with third-party APIs).\n *\n * Example usage for a public facing app (open to the internet):\n * ```typescript\n * new GuEc2App(stack, {\n * applicationPort: 1234,\n * app: \"app-name\",\n * access: { scope: AccessScope.PUBLIC },\n * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),\n * certificateProps:{\n * domainName: \"domain-name-for-your-application.example\",\n * },\n * monitoringConfiguration: {\n * snsTopicName: \"alerts-topic-for-my-team\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * },\n * unhealthyInstancesAlarm: true,\n * },\n * userData: {\n * distributable: {\n * fileName: \"app-name.deb\",\n * executionStatement: `dpkg -i /app-name/app-name.deb`,\n * }\n * },\n * });\n * ```\n *\n * Example usage for an app which is restricted to specific CIDR ranges:\n * ```typescript\n * new GuEc2App(stack, {\n * applicationPort: 1234,\n * app: \"app-name\",\n * access: {\n * scope: AccessScope.RESTRICTED,\n * cidrRanges: [Peer.ipv4(\"192.168.1.1/32\"), Peer.ipv4(\"8.8.8.8/32\")],\n * },\n * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),\n * certificateProps:{\n * domainName: \"domain-name-for-your-application.example\",\n * },\n * monitoringConfiguration: {\n * snsTopicName: \"alerts-topic-for-my-team\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * },\n * unhealthyInstancesAlarm: true,\n * }\n * userData: {\n * distributable: {\n * fileName: \"app-name.deb\",\n * executionStatement: `dpkg -i /app-name/app-name.deb`,\n * }\n * },\n * });\n * ```\n *\n * ### Varying values by stage\n *\n * There are times when you want a resource's configuration to be stage aware,\n * for example the number of instances in an ASG.\n *\n * To do this, we can use a simple ternary:\n * ```typescript\n * new GuEc2App(this, {\n * // other required properties\n * scaling: this.stage === \"PROD\" ? { minimumInstances: 6 } : { minimumInstances: 1 }\n * });\n * ```\n *\n * If multiple properties need to be stage aware, consider encoding this into the `props` of the calling class:\n *\n * ```typescript\n * export interface MyAppProps extends GuStackProps {\n * domainName: string;\n * scaling: GuAsgCapacity;\n * monitoringConfiguration: Alarms | NoMonitoring;\n * }\n *\n * export class MyApp extends GuStack {\n * private static app = \"cdk-playground\";\n *\n * constructor(scope: App, id: string, props: MyAppProps) {\n * const { stage, domainName, scaling, monitoringConfiguration } = props;\n *\n * super(scope, id, props);\n *\n * new GuPlayApp(this, {\n * app: \"my-app\",\n * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MICRO),\n * access: { scope: AccessScope.PUBLIC },\n * userData: {\n * distributable: {\n * fileName: `my-app.deb`,\n * executionStatement: `dpkg -i /my-app/my-app.deb`,\n * },\n * },\n * certificateProps: {\n * domainName,\n * },\n * monitoringConfiguration,\n * scaling,\n * });\n * }\n * }\n *\n * new MyApp(app, \"MyApp-CODE\", {\n * stage: \"CODE\",\n * domainName: \"my-app.code.dev-gutools.co.uk\",\n * scaling: { minimumInstances: 1 },\n * monitoringConfiguration: { noMonitoring: true },\n * });\n *\n * new MyApp(app, \"MyApp-PROD\", {\n * stage: \"PROD\",\n * domainName: \"my-app.prod.gutools.co.uk\",\n * scaling: { minimumInstances: 6 },\n * monitoringConfiguration: {\n * // config to enable alarms in PROD\n * },\n * });\n * ```\n *\n * If you _must_ support a non-standard VPC setup, it's possible to override the VPC and subnet selection into which\n * instances will be started. You need to set the three props below in order for this to work:\n * vpc: this must be an IVpc instance indicating the VPC to deploy into (usually obtained from `Vpc.fromVpcAttributes`)\n * privateSubnets: a list of ISubnet indicating the subnets for the autoscaling group to deploy instances into (usually\n * obtained from `GuVpc.subnets`)\n * publicSubnets: a list of ISubnet indicating the subnets for the loadbalancer to use, if the loadbalancer\n * is intended for public access (usually obtained from `GuVpc.subnets`)\n * On the other hand, if the access is private, then an \"internal\" loadbalancer is used in the `privateSubnets` list.\n * Please note that no checking is applied to the subnet lists to ensure that they correspond to the vpc given; as\n * an advanced feature it is assumed that the caller ensures this. If the subnets are mismatched then the resulting\n * Cloudformation will fail to deploy.\n *\n * ### Customising the infrastructure generated by this pattern\n *\n * Although we allow users to customise many aspects of their infrastructure via [[`GuEc2AppProps`]], it's possible\n * that there are less common use-cases which are currently unsupported via the API. In these circumstances escape\n * hatches can be used to override specific resources in the stack.\n *\n * In order to do this:\n *\n * 1. Create desired resource using Guardian or AWS constructs, for example:\n * ```typescript\n * const sg = new GuSecurityGroup(\n * // custom parameters\n * );\n * ```\n * 2. Access the CloudFormation version of the resource that you wish to customise, for example:\n * ```typescript\n * const pattern = new GuEc2App(\n * // all parameters\n * )\n * const cfnLb = pattern.loadBalancer.node.defaultChild as CfnLoadBalancer;\n * ```\n * 3. Replace the resource generated by the pattern with your bespoke resource, for example:\n * ```typescript\n * cfnLb.securityGroups = [sg.securityGroupId];\n * ```\n */\nexport class GuEc2App extends Construct {\n /*\n * These are public for now, as this allows users to\n * modify these constructs as desired to fit their\n * specific needs.\n * In the future, we might build functionality to better enable users\n * to access in-pattern constructs, but this would allow teams to be unblocked\n * in the short term.\n * */\n public readonly vpc: IVpc;\n public readonly certificate?: GuCertificate;\n public readonly loadBalancer: GuApplicationLoadBalancer;\n public readonly autoScalingGroup: GuAutoScalingGroup;\n public readonly listener: GuHttpsApplicationListener;\n public readonly targetGroup: GuApplicationTargetGroup;\n\n constructor(scope: GuStack, props: GuEc2AppProps) {\n const {\n access,\n accessLogging = { enabled: false },\n app,\n // We should update this default once a significant number of apps have migrated to devx-logs\n applicationLogging = { enabled: false },\n applicationPort,\n blockDevices,\n certificateProps,\n instanceType,\n monitoringConfiguration,\n roleConfiguration = { withoutLogShipping: false, additionalPolicies: [] },\n scaling: { minimumInstances, maximumInstances = minimumInstances * 2 },\n userData,\n withoutImdsv2,\n imageRecipe,\n vpc = GuVpc.fromIdParameter(scope, AppIdentity.suffixText({ app }, \"VPC\")),\n privateSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PRIVATE, app }),\n publicSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PUBLIC, app }),\n } = props;\n\n super(scope, app); // The assumption is `app` is unique\n\n // We should really prevent users from doing this via the type system,\n // but that requires a breaking change to the API\n if (applicationLogging.enabled && roleConfiguration.withoutLogShipping) {\n throw new Error(\n \"Application logging has been enabled (via the `applicationLogging` prop) but your `roleConfiguration` sets \" +\n \"`withoutLogShipping` to true. Please turn off application logging or remove `withoutLogShipping`\"\n );\n }\n\n AppAccess.validate(access);\n\n const certificate =\n typeof certificateProps !== \"undefined\"\n ? new GuCertificate(scope, {\n app,\n domainName: certificateProps.domainName,\n hostedZoneId: certificateProps.hostedZoneId,\n })\n : undefined;\n\n const maybePrivateConfigPolicy =\n typeof userData !== \"string\" && userData.configuration\n ? [new GuGetPrivateConfigPolicy(scope, \"GetPrivateConfigFromS3Policy\", userData.configuration)]\n : [];\n\n const mergedRoleConfiguration: GuInstanceRoleProps = {\n withoutLogShipping: roleConfiguration.withoutLogShipping,\n additionalPolicies: maybePrivateConfigPolicy.concat(roleConfiguration.additionalPolicies ?? []),\n };\n\n const autoScalingGroup = new GuAutoScalingGroup(scope, \"AutoScalingGroup\", {\n app,\n vpc,\n instanceType,\n minimumInstances,\n maximumInstances,\n withoutImdsv2,\n role: new GuInstanceRole(scope, { app, ...mergedRoleConfiguration }),\n healthCheck: HealthCheck.elb({ grace: Duration.minutes(2) }), // should this be defaulted at pattern or construct level?\n userData: typeof userData !== \"string\" ? new GuUserData(scope, { app, ...userData }).userData : userData,\n vpcSubnets: { subnets: privateSubnets },\n ...(blockDevices && { blockDevices }),\n imageRecipe,\n });\n\n // This allows automatic shipping of instance Cloud Init logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.LOG_KINESIS_STREAM_NAME,\n GuLoggingStreamNameParameter.getInstance(scope).valueAsString\n );\n\n if (applicationLogging.enabled) {\n // This allows automatic shipping of application logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.SYSTEMD_UNIT,\n applicationLogging.systemdUnitName ? `${applicationLogging.systemdUnitName}.service` : `${app}.service`\n );\n }\n\n const loadBalancer = new GuApplicationLoadBalancer(scope, \"LoadBalancer\", {\n app,\n vpc,\n // Setting internetFacing to true does not necessarily allow public access to the load balancer itself. That is handled by the listener's `open` prop.\n internetFacing: access.scope !== AccessScope.INTERNAL,\n vpcSubnets: {\n subnets: access.scope === AccessScope.INTERNAL ? privateSubnets : publicSubnets,\n },\n });\n\n if (accessLogging.enabled) {\n const accessLoggingBucket = new GuStringParameter(scope, \"AccessLoggingBucket\", {\n description: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.description,\n default: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.path,\n fromSSM: true,\n });\n\n loadBalancer.logAccessLogs(\n Bucket.fromBucketName(\n scope,\n AppIdentity.suffixText(props, \"AccessLoggingBucket\"),\n accessLoggingBucket.valueAsString\n ),\n accessLogging.prefix\n );\n }\n\n const targetGroup = new GuApplicationTargetGroup(scope, \"TargetGroup\", {\n app,\n vpc,\n protocol: ApplicationProtocol.HTTP,\n targets: [autoScalingGroup],\n port: applicationPort,\n });\n\n const listener = new GuHttpsApplicationListener(scope, \"Listener\", {\n app,\n loadBalancer,\n certificate,\n targetGroup,\n // When open=true, AWS will create a security group which allows all inbound traffic over HTTPS\n open: access.scope === AccessScope.PUBLIC && typeof certificate !== \"undefined\",\n });\n\n // Since AWS won't create a security group automatically when open=false, we need to add our own\n if (access.scope !== AccessScope.PUBLIC) {\n loadBalancer.addSecurityGroup(\n new GuSecurityGroup(scope, `${access.scope}IngressSecurityGroup`, {\n app,\n vpc,\n description: \"Allow restricted ingress from CIDR ranges\",\n allowAllOutbound: false,\n ingresses: restrictedCidrRanges(access.cidrRanges),\n })\n );\n }\n\n if (!monitoringConfiguration.noMonitoring) {\n const { http5xxAlarm, snsTopicName, unhealthyInstancesAlarm } = monitoringConfiguration;\n\n if (http5xxAlarm) {\n new GuAlb5xxPercentageAlarm(scope, {\n app,\n loadBalancer,\n snsTopicName,\n ...http5xxAlarm,\n });\n }\n if (unhealthyInstancesAlarm) {\n new GuUnhealthyInstancesAlarm(scope, {\n app,\n targetGroup,\n snsTopicName,\n });\n }\n }\n\n this.vpc = vpc;\n this.certificate = certificate;\n this.loadBalancer = loadBalancer;\n this.autoScalingGroup = autoScalingGroup;\n this.listener = listener;\n this.targetGroup = targetGroup;\n }\n}\n"]}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/patterns/ec2-app/base.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint \"@guardian/tsdoc-required/tsdoc-required\": 2 -- to begin rolling this out for public APIs. */\nimport { Duration, Tags } from \"aws-cdk-lib\";\nimport type { BlockDevice } from \"aws-cdk-lib/aws-autoscaling\";\nimport { HealthCheck } from \"aws-cdk-lib/aws-autoscaling\";\nimport type { InstanceType, IPeer, ISubnet, IVpc } from \"aws-cdk-lib/aws-ec2\";\nimport { Port } from \"aws-cdk-lib/aws-ec2\";\nimport { ApplicationProtocol } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport { Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { Construct } from \"constructs\";\nimport { AccessScope, MetadataKeys, NAMED_SSM_PARAMETER_PATHS } from \"../../constants\";\nimport { GuCertificate } from \"../../constructs/acm\";\nimport type { GuUserDataProps } from \"../../constructs/autoscaling\";\nimport { GuAutoScalingGroup, GuUserData } from \"../../constructs/autoscaling\";\nimport type { Http5xxAlarmProps, NoMonitoring } from \"../../constructs/cloudwatch\";\nimport { GuAlb5xxPercentageAlarm, GuUnhealthyInstancesAlarm } from \"../../constructs/cloudwatch\";\nimport type { GuStack } from \"../../constructs/core\";\nimport { AppIdentity, GuLoggingStreamNameParameter, GuStringParameter } from \"../../constructs/core\";\nimport { GuSecurityGroup, GuVpc, SubnetType } from \"../../constructs/ec2\";\nimport type { GuInstanceRoleProps } from \"../../constructs/iam\";\nimport { GuGetPrivateConfigPolicy, GuInstanceRole } from \"../../constructs/iam\";\nimport {\n GuApplicationLoadBalancer,\n GuApplicationTargetGroup,\n GuHttpsApplicationListener,\n} from \"../../constructs/loadbalancing\";\nimport { AppAccess } from \"../../types\";\nimport type { GuAsgCapacity, GuDomainName } from \"../../types\";\nimport type { AmigoProps } from \"../../types/amigo\";\n\nexport interface AccessLoggingProps {\n /**\n * Enable (load balancer) access logs.\n *\n * Note, you will need to specify a region in your stack declaration to use\n * this.\n * See`https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-elasticloadbalancingv2.ApplicationLoadBalancer.html#logwbraccesswbrlogsbucket-prefix`\n */\n enabled: boolean;\n /**\n * S3 prefix for the logs.\n *\n * @defaultValue no prefix\n */\n prefix?: string;\n}\n\n/**\n * To ship your application logs to ELK automatically, you must:\n *\n * 1. Set the `enabled` flag to true\n * 2. Include the `cdk-base` Amigo role in your AMI\n * 3. Log to `journald`. We recommend doing this by logging to `stdout` and\n * using `systemd` to start your app\n * 4. Confirm that your [[`systemdUnitName`]] is configured properly.\n *\n * Unless you have explicitly opted-out, appropriate IAM permissions for logging\n * to Kinesis will be configured automatically via the [[`GuEc2App`]] pattern.\n */\nexport interface ApplicationLoggingProps {\n /**\n * Enables forwarding of application logs to the Guardian ELK stack.\n *\n * Note, to work, you will need to also do the following non-CDK things:\n *\n * 1. Include the `cdk-base` Amigo role in your AMI.\n * 2. Log to `journald`. We recommend doing this by logging to `stdout` and\n * using `systemd` to start your app\n * 3. Confirm that your [[`systemdUnitName`]] is configured properly.\n *\n * Unless you have explicitly opted-out, appropriate IAM permissions for\n * logging to Kinesis will be configured automatically via the [[`GuEc2App`]]\n * pattern.\n *\n * @see https://github.com/guardian/amigo/tree/main/roles/cdk-base\n */\n enabled: boolean;\n /**\n * This needs to match the name of your SystemD unit.\n *\n * If your systemd unit is not `<app>.service` set this value.\n *\n * @defaultValue `<app>.service`\n */\n systemdUnitName?: string;\n}\n\n/**\n * @privateRemarks we should rename this to AlarmsProps.\n */\nexport interface Alarms {\n /**\n * Name of the target (SNS Topic) for alarm notifications.\n */\n snsTopicName: string;\n /**\n * Enable the 5xx alarm with settings.\n */\n http5xxAlarm: false | Http5xxAlarmProps;\n /**\n * Enable the unhealthy instances alarm.\n */\n unhealthyInstancesAlarm: boolean;\n /**\n * Internal flag - users of this library should ignore this setting.\n */\n noMonitoring?: false;\n}\n\nexport interface GuEc2AppProps extends AppIdentity {\n /**\n * User data for the autoscaling group.\n */\n userData: GuUserDataProps | string;\n /**\n * Network access restrictions for your load balancer.\n *\n * Note, this merely provides defence in depth; you should, for example, limit\n * access to the VPN and then treat that as sufficient. Instead, use Google\n * Auth for human access, or a suitable machine auth mechanism.\n */\n access: AppAccess;\n /**\n * The port your application runs on.\n */\n applicationPort: number;\n /**\n * Configure IAM roles for autoscaling group EC2 instances.\n */\n roleConfiguration?: GuInstanceRoleProps;\n /**\n * Enable and configure alarms.\n */\n monitoringConfiguration: Alarms | NoMonitoring;\n /**\n * EC2 instance type. Note, ensure your code is built for the same\n * architecture family (arm64 - 'Graviton' instances - or x64).\n */\n instanceType: InstanceType;\n /**\n * Enable and configures application logs.\n */\n applicationLogging?: ApplicationLoggingProps;\n /**\n * Enable and configures access logs.\n */\n accessLogging?: AccessLoggingProps;\n /**\n * Add block devices (additional storage).\n */\n blockDevices?: BlockDevice[];\n /**\n * Autoscaling group min and max sizes.\n */\n scaling: GuAsgCapacity;\n /**\n * Specify certificate for the load balancer.\n */\n certificateProps?: GuDomainName;\n /**\n * Disable imdsv2. Most of the time you should not set this.\n *\n * @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html\n */\n withoutImdsv2?: boolean;\n /**\n * Configure Amigo image recipe.\n */\n imageRecipe?: string | AmigoProps;\n /**\n * Specify the VPC to use.\n *\n * @see https://github.com/guardian/aws-account-setup\n */\n vpc?: IVpc;\n /**\n * Specify private subnets if using a non-default VPC or (generally\n * discouraged) to limit to a subset of the available subnets.\n */\n privateSubnets?: ISubnet[];\n\n /**\n * Specify private subnets if using a non-default VPC or (generally\n * discouraged) to limit to a subset of the available subnets.\n */\n publicSubnets?: ISubnet[];\n}\n\nfunction restrictedCidrRanges(ranges: IPeer[]) {\n return ranges.map((range) => ({\n range,\n port: Port.tcp(443),\n description: `Allow access on port 443 from ${range.uniqueId}`,\n }));\n}\n\n/**\n * Pattern which creates the resources needed to run an application on EC2\n * behind a load balancer. For convenience, you may wish to use [[`GuPlayApp`]]\n * or [[`GuNodeApp`]], which extend this class.\n *\n * See props for further details.\n */\nexport class GuEc2App extends Construct {\n /*\n * These are public for now, as this allows users to\n * modify these constructs as desired to fit their\n * specific needs.\n * In the future, we might build functionality to better enable users\n * to access in-pattern constructs, but this would allow teams to be unblocked\n * in the short term.\n * */\n public readonly vpc: IVpc;\n public readonly certificate?: GuCertificate;\n public readonly loadBalancer: GuApplicationLoadBalancer;\n public readonly autoScalingGroup: GuAutoScalingGroup;\n public readonly listener: GuHttpsApplicationListener;\n public readonly targetGroup: GuApplicationTargetGroup;\n\n constructor(scope: GuStack, props: GuEc2AppProps) {\n const {\n access,\n accessLogging = { enabled: false },\n app,\n // We should update this default once a significant number of apps have migrated to devx-logs\n applicationLogging = { enabled: false },\n applicationPort,\n blockDevices,\n certificateProps,\n instanceType,\n monitoringConfiguration,\n roleConfiguration = { withoutLogShipping: false, additionalPolicies: [] },\n scaling: { minimumInstances, maximumInstances = minimumInstances * 2 },\n userData,\n withoutImdsv2,\n imageRecipe,\n vpc = GuVpc.fromIdParameter(scope, AppIdentity.suffixText({ app }, \"VPC\")),\n privateSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PRIVATE, app }),\n publicSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PUBLIC, app }),\n } = props;\n\n super(scope, app); // The assumption is `app` is unique\n\n // We should really prevent users from doing this via the type system,\n // but that requires a breaking change to the API\n if (applicationLogging.enabled && roleConfiguration.withoutLogShipping) {\n throw new Error(\n \"Application logging has been enabled (via the `applicationLogging` prop) but your `roleConfiguration` sets \" +\n \"`withoutLogShipping` to true. Please turn off application logging or remove `withoutLogShipping`\"\n );\n }\n\n AppAccess.validate(access);\n\n const certificate =\n typeof certificateProps !== \"undefined\"\n ? new GuCertificate(scope, {\n app,\n domainName: certificateProps.domainName,\n hostedZoneId: certificateProps.hostedZoneId,\n })\n : undefined;\n\n const maybePrivateConfigPolicy =\n typeof userData !== \"string\" && userData.configuration\n ? [new GuGetPrivateConfigPolicy(scope, \"GetPrivateConfigFromS3Policy\", userData.configuration)]\n : [];\n\n const mergedRoleConfiguration: GuInstanceRoleProps = {\n withoutLogShipping: roleConfiguration.withoutLogShipping,\n additionalPolicies: maybePrivateConfigPolicy.concat(roleConfiguration.additionalPolicies ?? []),\n };\n\n const autoScalingGroup = new GuAutoScalingGroup(scope, \"AutoScalingGroup\", {\n app,\n vpc,\n instanceType,\n minimumInstances,\n maximumInstances,\n withoutImdsv2,\n role: new GuInstanceRole(scope, { app, ...mergedRoleConfiguration }),\n healthCheck: HealthCheck.elb({ grace: Duration.minutes(2) }), // should this be defaulted at pattern or construct level?\n userData: typeof userData !== \"string\" ? new GuUserData(scope, { app, ...userData }).userData : userData,\n vpcSubnets: { subnets: privateSubnets },\n ...(blockDevices && { blockDevices }),\n imageRecipe,\n });\n\n // This allows automatic shipping of instance Cloud Init logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.LOG_KINESIS_STREAM_NAME,\n GuLoggingStreamNameParameter.getInstance(scope).valueAsString\n );\n\n if (applicationLogging.enabled) {\n // This allows automatic shipping of application logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.SYSTEMD_UNIT,\n applicationLogging.systemdUnitName ? `${applicationLogging.systemdUnitName}.service` : `${app}.service`\n );\n }\n\n const loadBalancer = new GuApplicationLoadBalancer(scope, \"LoadBalancer\", {\n app,\n vpc,\n // Setting internetFacing to true does not necessarily allow public access to the load balancer itself. That is handled by the listener's `open` prop.\n internetFacing: access.scope !== AccessScope.INTERNAL,\n vpcSubnets: {\n subnets: access.scope === AccessScope.INTERNAL ? privateSubnets : publicSubnets,\n },\n });\n\n if (accessLogging.enabled) {\n const accessLoggingBucket = new GuStringParameter(scope, \"AccessLoggingBucket\", {\n description: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.description,\n default: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.path,\n fromSSM: true,\n });\n\n loadBalancer.logAccessLogs(\n Bucket.fromBucketName(\n scope,\n AppIdentity.suffixText(props, \"AccessLoggingBucket\"),\n accessLoggingBucket.valueAsString\n ),\n accessLogging.prefix\n );\n }\n\n const targetGroup = new GuApplicationTargetGroup(scope, \"TargetGroup\", {\n app,\n vpc,\n protocol: ApplicationProtocol.HTTP,\n targets: [autoScalingGroup],\n port: applicationPort,\n });\n\n const listener = new GuHttpsApplicationListener(scope, \"Listener\", {\n app,\n loadBalancer,\n certificate,\n targetGroup,\n // When open=true, AWS will create a security group which allows all inbound traffic over HTTPS\n open: access.scope === AccessScope.PUBLIC && typeof certificate !== \"undefined\",\n });\n\n // Since AWS won't create a security group automatically when open=false, we need to add our own\n if (access.scope !== AccessScope.PUBLIC) {\n loadBalancer.addSecurityGroup(\n new GuSecurityGroup(scope, `${access.scope}IngressSecurityGroup`, {\n app,\n vpc,\n description: \"Allow restricted ingress from CIDR ranges\",\n allowAllOutbound: false,\n ingresses: restrictedCidrRanges(access.cidrRanges),\n })\n );\n }\n\n if (!monitoringConfiguration.noMonitoring) {\n const { http5xxAlarm, snsTopicName, unhealthyInstancesAlarm } = monitoringConfiguration;\n\n if (http5xxAlarm) {\n new GuAlb5xxPercentageAlarm(scope, {\n app,\n loadBalancer,\n snsTopicName,\n ...http5xxAlarm,\n });\n }\n if (unhealthyInstancesAlarm) {\n new GuUnhealthyInstancesAlarm(scope, {\n app,\n targetGroup,\n snsTopicName,\n });\n }\n }\n\n this.vpc = vpc;\n this.certificate = certificate;\n this.loadBalancer = loadBalancer;\n this.autoScalingGroup = autoScalingGroup;\n this.listener = listener;\n this.targetGroup = targetGroup;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@guardian/cdk",
3
3
  "description": "Generic Guardian flavoured AWS CDK components",
4
- "version": "49.4.1",
4
+ "version": "49.6.0",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "files": [
@@ -28,18 +28,19 @@
28
28
  "cli:dev": "ts-node src/bin/index.ts"
29
29
  },
30
30
  "devDependencies": {
31
- "@guardian/eslint-config-typescript": "4.0.0",
31
+ "@guardian/eslint-config-typescript": "5.0.0",
32
+ "@guardian/eslint-plugin-tsdoc-required": "^0.1.3",
32
33
  "@types/git-url-parse": "^9.0.1",
33
- "@types/jest": "^29.4.0",
34
+ "@types/jest": "^29.5.0",
34
35
  "@types/js-yaml": "^4.0.5",
35
36
  "@types/lodash.camelcase": "^4.3.7",
36
37
  "@types/lodash.kebabcase": "^4.1.7",
37
38
  "@types/lodash.upperfirst": "^4.3.7",
38
- "@types/node": "18.14.6",
39
+ "@types/node": "18.15.5",
39
40
  "@types/yargs": "^17.0.19",
40
41
  "aws-cdk": "2.68.0",
41
42
  "cz-conventional-changelog": "^3.3.0",
42
- "eslint": "^8.35.0",
43
+ "eslint": "^8.36.0",
43
44
  "eslint-plugin-custom-rules": "file:tools/eslint",
44
45
  "gh-pages": "^5.0.0",
45
46
  "jest": "^29.5.0",
@@ -48,15 +49,15 @@
48
49
  "serve": "^14.2.0",
49
50
  "ts-jest": "^29.0.5",
50
51
  "ts-node": "^10.9.1",
51
- "typedoc": "^0.23.26",
52
+ "typedoc": "^0.23.28",
52
53
  "typescript": "~4.9.5"
53
54
  },
54
55
  "dependencies": {
55
- "@oclif/core": "1.24.2",
56
+ "@oclif/core": "2.7.1",
56
57
  "aws-cdk-lib": "2.68.0",
57
- "aws-sdk": "^2.1326.0",
58
+ "aws-sdk": "^2.1339.0",
58
59
  "chalk": "^4.1.2",
59
- "codemaker": "^1.77.0",
60
+ "codemaker": "^1.78.1",
60
61
  "constructs": "10.1.273",
61
62
  "git-url-parse": "^13.1.0",
62
63
  "js-yaml": "^4.1.0",