@digitraffic/common 2022.11.1-1 → 2022.11.10-1

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.
Files changed (41) hide show
  1. package/dist/aws/infra/canaries/canary.js +1 -1
  2. package/dist/aws/infra/canaries/database-checker.d.ts +22 -8
  3. package/dist/aws/infra/canaries/database-checker.js +36 -27
  4. package/dist/aws/infra/canaries/database-checker.js.map +1 -1
  5. package/dist/aws/infra/canaries/url-checker.js +1 -1
  6. package/dist/aws/infra/import-util.d.ts +21 -0
  7. package/dist/aws/infra/import-util.js +53 -0
  8. package/dist/aws/infra/import-util.js.map +1 -0
  9. package/dist/aws/infra/stack/rest_apis.d.ts +1 -1
  10. package/dist/aws/infra/stack/rest_apis.js +2 -2
  11. package/dist/aws/infra/stack/rest_apis.js.map +1 -1
  12. package/dist/aws/infra/stacks/db-dns-stack.d.ts +11 -0
  13. package/dist/aws/infra/stacks/db-dns-stack.js +63 -0
  14. package/dist/aws/infra/stacks/db-dns-stack.js.map +1 -0
  15. package/dist/aws/infra/stacks/db-proxy-stack.d.ts +19 -0
  16. package/dist/aws/infra/stacks/db-proxy-stack.js +74 -0
  17. package/dist/aws/infra/stacks/db-proxy-stack.js.map +1 -0
  18. package/dist/aws/infra/stacks/db-stack.d.ts +31 -0
  19. package/dist/aws/infra/stacks/db-stack.js +91 -0
  20. package/dist/aws/infra/stacks/db-stack.js.map +1 -0
  21. package/dist/aws/infra/stacks/intra-stack-configuration.d.ts +5 -0
  22. package/dist/aws/infra/stacks/intra-stack-configuration.js +3 -0
  23. package/dist/aws/infra/stacks/intra-stack-configuration.js.map +1 -0
  24. package/dist/aws/infra/stacks/network-stack.d.ts +12 -0
  25. package/dist/aws/infra/stacks/network-stack.js +36 -0
  26. package/dist/aws/infra/stacks/network-stack.js.map +1 -0
  27. package/dist/aws/infra/usage-plans.d.ts +3 -2
  28. package/dist/aws/infra/usage-plans.js +5 -4
  29. package/dist/aws/infra/usage-plans.js.map +1 -1
  30. package/package.json +3 -3
  31. package/src/aws/infra/canaries/canary.ts +1 -1
  32. package/src/aws/infra/canaries/database-checker.ts +42 -36
  33. package/src/aws/infra/canaries/url-checker.ts +1 -1
  34. package/src/aws/infra/import-util.ts +57 -0
  35. package/src/aws/infra/stack/rest_apis.ts +2 -2
  36. package/src/aws/infra/stacks/db-dns-stack.ts +88 -0
  37. package/src/aws/infra/stacks/db-proxy-stack.ts +129 -0
  38. package/src/aws/infra/stacks/db-stack.ts +165 -0
  39. package/src/aws/infra/stacks/intra-stack-configuration.ts +6 -0
  40. package/src/aws/infra/stacks/network-stack.ts +46 -0
  41. package/src/aws/infra/usage-plans.ts +15 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-stack.js","sourceRoot":"","sources":["../../../../src/aws/infra/stacks/db-stack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Environment } from "aws-cdk-lib";
2
+ export interface InfraStackConfiguration {
3
+ readonly env: Environment;
4
+ readonly environmentName: string;
5
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=intra-stack-configuration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intra-stack-configuration.js","sourceRoot":"","sources":["../../../../src/aws/infra/stacks/intra-stack-configuration.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import { Stack } from "aws-cdk-lib";
2
+ import { Construct } from "constructs";
3
+ import { Vpc } from "aws-cdk-lib/aws-ec2";
4
+ import { InfraStackConfiguration } from "./intra-stack-configuration";
5
+ export interface NetworkConfiguration {
6
+ readonly vpcName: string;
7
+ readonly cidr: string;
8
+ }
9
+ export declare class NetworkStack extends Stack {
10
+ constructor(scope: Construct, id: string, isc: InfraStackConfiguration, configuration: NetworkConfiguration);
11
+ createVpc(configuration: NetworkConfiguration): Vpc;
12
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NetworkStack = void 0;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
6
+ class NetworkStack extends aws_cdk_lib_1.Stack {
7
+ constructor(scope, id, isc, configuration) {
8
+ super(scope, id, {
9
+ env: isc.env,
10
+ });
11
+ this.createVpc(configuration);
12
+ }
13
+ createVpc(configuration) {
14
+ return new aws_ec2_1.Vpc(this, "DigitrafficVPC", {
15
+ vpcName: configuration.vpcName,
16
+ availabilityZones: ["eu-west-1a", "eu-west-1b"],
17
+ enableDnsHostnames: true,
18
+ enableDnsSupport: true,
19
+ cidr: configuration.cidr,
20
+ subnetConfiguration: [
21
+ {
22
+ name: "public",
23
+ cidrMask: 24,
24
+ subnetType: aws_ec2_1.SubnetType.PUBLIC,
25
+ },
26
+ {
27
+ name: "private",
28
+ cidrMask: 24,
29
+ subnetType: aws_ec2_1.SubnetType.PRIVATE_WITH_NAT,
30
+ },
31
+ ],
32
+ });
33
+ }
34
+ }
35
+ exports.NetworkStack = NetworkStack;
36
+ //# sourceMappingURL=network-stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-stack.js","sourceRoot":"","sources":["../../../../src/aws/infra/stacks/network-stack.ts"],"names":[],"mappings":";;;AAAA,6CAAoC;AAEpC,iDAAsD;AAQtD,MAAa,YAAa,SAAQ,mBAAK;IACnC,YACI,KAAgB,EAChB,EAAU,EACV,GAA4B,EAC5B,aAAmC;QAEnC,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACb,GAAG,EAAE,GAAG,CAAC,GAAG;SACf,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IAClC,CAAC;IAED,SAAS,CAAC,aAAmC;QACzC,OAAO,IAAI,aAAG,CAAC,IAAI,EAAE,gBAAgB,EAAE;YACnC,OAAO,EAAE,aAAa,CAAC,OAAO;YAC9B,iBAAiB,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;YAC/C,kBAAkB,EAAE,IAAI;YACxB,gBAAgB,EAAE,IAAI;YACtB,IAAI,EAAE,aAAa,CAAC,IAAI;YACxB,mBAAmB,EAAE;gBACjB;oBACI,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,EAAE;oBACZ,UAAU,EAAE,oBAAU,CAAC,MAAM;iBAChC;gBACD;oBACI,IAAI,EAAE,SAAS;oBACf,QAAQ,EAAE,EAAE;oBACZ,UAAU,EAAE,oBAAU,CAAC,gBAAgB;iBAC1C;aACJ;SACJ,CAAC,CAAC;IACP,CAAC;CACJ;AAnCD,oCAmCC"}
@@ -1,4 +1,4 @@
1
- import { IApiKey, RestApi } from 'aws-cdk-lib/aws-apigateway';
1
+ import { IApiKey, RestApi } from "aws-cdk-lib/aws-apigateway";
2
2
  /**
3
3
  * Creates an usage plan for a REST API with a single API key
4
4
  * @param api The REST API
@@ -11,5 +11,6 @@ export declare function createUsagePlan(api: RestApi, apiKeyId: string, apiKeyNa
11
11
  * Creates a default usage plan for a REST API with a single API key
12
12
  * @param api The REST API
13
13
  * @param apiName Name of the api. Will generate key: apiName + ' API Key' and plan: apiName + ' API Usage Plan'
14
+ * @param value Optional value for the API key
14
15
  */
15
- export declare function createDefaultUsagePlan(api: RestApi, apiName: string): IApiKey;
16
+ export declare function createDefaultUsagePlan(api: RestApi, apiName: string, value?: string): IApiKey;
@@ -24,11 +24,12 @@ exports.createUsagePlan = createUsagePlan;
24
24
  * Creates a default usage plan for a REST API with a single API key
25
25
  * @param api The REST API
26
26
  * @param apiName Name of the api. Will generate key: apiName + ' API Key' and plan: apiName + ' API Usage Plan'
27
+ * @param value Optional value for the API key
27
28
  */
28
- function createDefaultUsagePlan(api, apiName) {
29
- const apiKeyName = apiName + ' API Key';
30
- const usagePlanName = apiName + ' API Usage Plan';
31
- const apiKey = api.addApiKey(apiKeyName, { apiKeyName: apiKeyName });
29
+ function createDefaultUsagePlan(api, apiName, value) {
30
+ const apiKeyName = apiName + " API Key";
31
+ const usagePlanName = apiName + " API Usage Plan";
32
+ const apiKey = api.addApiKey(apiKeyName, { apiKeyName: apiKeyName, value });
32
33
  const plan = api.addUsagePlan(usagePlanName, {
33
34
  name: usagePlanName,
34
35
  });
@@ -1 +1 @@
1
- {"version":3,"file":"usage-plans.js","sourceRoot":"","sources":["../../../src/aws/infra/usage-plans.ts"],"names":[],"mappings":";;;AAEA;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,GAAY,EAAE,QAAgB,EAAE,UAAkB;IAC9E,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,UAAU,EAAE;QACtC,IAAI,EAAE,UAAU;KACnB,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,CAAC;QACb,KAAK,EAAE,GAAG,CAAC,eAAe;KAC7B,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,MAAM,CAAC;AAClB,CAAC;AAXD,0CAWC;AAED;;;;GAIG;AACH,SAAgB,sBAAsB,CAAC,GAAY,EAAE,OAAe;IAChE,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;IACxC,MAAM,aAAa,GAAG,OAAO,GAAG,iBAAiB,CAAC;IAClD,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,aAAa,EAAE;QACzC,IAAI,EAAE,aAAa;KACtB,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,CAAC;QACb,KAAK,EAAE,GAAG,CAAC,eAAe;KAC7B,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,MAAM,CAAC;AAClB,CAAC;AAbD,wDAaC"}
1
+ {"version":3,"file":"usage-plans.js","sourceRoot":"","sources":["../../../src/aws/infra/usage-plans.ts"],"names":[],"mappings":";;;AAEA;;;;;;GAMG;AACH,SAAgB,eAAe,CAC3B,GAAY,EACZ,QAAgB,EAChB,UAAkB;IAElB,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,UAAU,EAAE;QACtC,IAAI,EAAE,UAAU;KACnB,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,CAAC;QACb,KAAK,EAAE,GAAG,CAAC,eAAe;KAC7B,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,MAAM,CAAC;AAClB,CAAC;AAfD,0CAeC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAClC,GAAY,EACZ,OAAe,EACf,KAAc;IAEd,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;IACxC,MAAM,aAAa,GAAG,OAAO,GAAG,iBAAiB,CAAC;IAClD,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,aAAa,EAAE;QACzC,IAAI,EAAE,aAAa;KACtB,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,CAAC;QACb,KAAK,EAAE,GAAG,CAAC,eAAe;KAC7B,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,MAAM,CAAC;AAClB,CAAC;AAjBD,wDAiBC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitraffic/common",
3
- "version": "2022.11.1-1",
3
+ "version": "2022.11.10-1",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,9 +26,9 @@
26
26
  "src/**/*.ts"
27
27
  ],
28
28
  "dependencies": {
29
- "@aws-cdk/aws-synthetics-alpha": "2.47.0-alpha.0",
29
+ "@aws-cdk/aws-synthetics-alpha": "2.50.0-alpha.0",
30
30
  "@types/geojson": "^7946.0.10",
31
- "aws-cdk-lib": "2.47.0",
31
+ "aws-cdk-lib": "2.50.0",
32
32
  "aws-sdk": "2.1241.0",
33
33
  "axios": "^0.21.1",
34
34
  "change-case": "4.1.2",
@@ -21,7 +21,7 @@ export class DigitrafficCanary extends Canary {
21
21
  environmentVariables: LambdaEnvironment
22
22
  ) {
23
23
  super(scope, canaryName, {
24
- runtime: Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_6,
24
+ runtime: Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_8,
25
25
  role,
26
26
  test: Test.custom({
27
27
  code: new AssetCode("dist", {
@@ -20,11 +20,7 @@ abstract class DatabaseCheck<T> {
20
20
  abstract check(value: T): void;
21
21
  }
22
22
 
23
- // For backwards compatibility disable following rule for BaseResponse.
24
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
25
- interface BaseResponse {}
26
-
27
- interface CountResponse extends BaseResponse {
23
+ interface CountResponse {
28
24
  count: number;
29
25
  }
30
26
 
@@ -40,8 +36,12 @@ class CountDatabaseCheck extends DatabaseCheck<CountResponse> {
40
36
  ) {
41
37
  super(name, sql);
42
38
 
39
+ if (!sql.toLowerCase().includes("select count(*)")) {
40
+ throw new Error("sql must contain select count(*)");
41
+ }
42
+
43
43
  if (minCount == null && maxCount == null) {
44
- throw new Error("no max or min given!");
44
+ throw new Error("no max or min given");
45
45
  }
46
46
 
47
47
  this.minCount = minCount;
@@ -49,30 +49,23 @@ class CountDatabaseCheck extends DatabaseCheck<CountResponse> {
49
49
  }
50
50
 
51
51
  check(value: CountResponse) {
52
- if (!value) {
53
- this.failed = true;
54
- throw new Error("no return value");
55
- } else {
56
- if ("count" in value) {
57
- if (this.minCount && value.count < this.minCount) {
58
- this.failed = true;
59
- throw new Error(
60
- `count was ${value.count}, minimum is ${this.minCount}`
61
- );
62
- }
63
- if (this.maxCount && value.count > this.maxCount) {
64
- this.failed = true;
65
- throw new Error(
66
- `count was ${value.count}, max is ${this.maxCount}`
67
- );
68
- }
69
- } else {
52
+ if ("count" in value) {
53
+ if (this.minCount && value.count < this.minCount) {
70
54
  this.failed = true;
71
-
72
- console.info("received " + JSON.stringify(value));
73
-
74
- throw new Error("no count available");
55
+ throw new Error(
56
+ `count was ${value.count}, minimum is ${this.minCount}`
57
+ );
58
+ }
59
+ if (this.maxCount && value.count > this.maxCount) {
60
+ this.failed = true;
61
+ throw new Error(
62
+ `count was ${value.count}, max is ${this.maxCount}`
63
+ );
75
64
  }
65
+ } else {
66
+ this.failed = true;
67
+
68
+ throw new Error("no count available");
76
69
  }
77
70
  }
78
71
  }
@@ -84,9 +77,13 @@ const stepConfig = {
84
77
  screenshotOnStepFailure: false,
85
78
  };
86
79
 
87
- export class DatabaseChecker {
80
+ /**
81
+ * Checker for sql that checks the count. Meaning that the
82
+ * sql must be structured as select(*) from table where something.
83
+ */
84
+ export class DatabaseCountChecker {
88
85
  credentialsFunction: () => Promise<void>;
89
- checks: DatabaseCheck<BaseResponse>[];
86
+ checks: DatabaseCheck<CountResponse>[];
90
87
 
91
88
  private constructor(credentialsFunction: () => Promise<void>) {
92
89
  this.credentialsFunction = credentialsFunction;
@@ -98,30 +95,39 @@ export class DatabaseChecker {
98
95
  }
99
96
 
100
97
  static createForProxy() {
101
- return new DatabaseChecker(() =>
98
+ return new DatabaseCountChecker(() =>
102
99
  new ProxyHolder(getEnvVariable("SECRET_ID")).setCredentials()
103
100
  );
104
101
  }
105
102
 
106
103
  static createForRds() {
107
- return new DatabaseChecker(() =>
104
+ return new DatabaseCountChecker(() =>
108
105
  new RdsHolder(getEnvVariable("SECRET_ID")).setCredentials()
109
106
  );
110
107
  }
111
108
 
112
- one(name: string, sql: string) {
109
+ /**
110
+ * Expect that the count is 1
111
+ */
112
+ expectOne(name: string, sql: string) {
113
113
  this.checks.push(new CountDatabaseCheck(name, sql, 1, 1));
114
114
 
115
115
  return this;
116
116
  }
117
117
 
118
- empty(name: string, sql: string) {
118
+ /**
119
+ * Expect that the count is 0
120
+ */
121
+ expectZero(name: string, sql: string) {
119
122
  this.checks.push(new CountDatabaseCheck(name, sql, null, 0));
120
123
 
121
124
  return this;
122
125
  }
123
126
 
124
- notEmpty(name: string, sql: string) {
127
+ /**
128
+ * Expect that the count is 1 or more
129
+ */
130
+ expectOneOrMore(name: string, sql: string) {
125
131
  this.checks.push(new CountDatabaseCheck(name, sql, 1, null));
126
132
 
127
133
  return this;
@@ -137,7 +143,7 @@ export class DatabaseChecker {
137
143
  for (const check of this.checks) {
138
144
  console.info("canary checking sql " + check.sql);
139
145
 
140
- const value = await db.oneOrNone(check.sql);
146
+ const value = await db.one<CountResponse>(check.sql);
141
147
  const checkFunction = () => {
142
148
  check.check(value);
143
149
  };
@@ -152,7 +152,7 @@ export class UrlChecker {
152
152
  requestOptions,
153
153
  validateStatusCodeAndContentType(
154
154
  403,
155
- mediaType || MediaType.APPLICATION_JSON
155
+ mediaType ?? MediaType.APPLICATION_JSON
156
156
  )
157
157
  );
158
158
  }
@@ -0,0 +1,57 @@
1
+ import { IVpc, Vpc } from "aws-cdk-lib/aws-ec2";
2
+ import { CfnOutput, Fn, Stack } from "aws-cdk-lib";
3
+ import { Construct } from "constructs";
4
+
5
+ export class OldStackImports {
6
+ public static AURORAINSTANCE_SG_IMPORT_NAME = "AuroraInstanceSG";
7
+ public static RDSPROXY_SG_IMPORT_NAME = "RDSProxySG";
8
+ }
9
+
10
+ /**
11
+ * Import VPC from other stack outputs
12
+ */
13
+ export function importVpc(scope: Construct, environmentName: string): IVpc {
14
+ const vpcId = importValue(environmentName, "VPCID");
15
+ const privateSubnetIds = [
16
+ importValue(environmentName, "digitrafficprivateASubnet"),
17
+ importValue(environmentName, "digitrafficprivateBSubnet"),
18
+ ];
19
+ const availabilityZones = ["euw1-az1", "euw1-az2"];
20
+
21
+ // VPC reference construction requires vpcId and availability zones
22
+ // private subnets are used in Lambda configuration
23
+ return Vpc.fromVpcAttributes(scope, "vpc", {
24
+ vpcId,
25
+ privateSubnetIds,
26
+ availabilityZones,
27
+ });
28
+ }
29
+
30
+ /**
31
+ * Import value from other stack output. Stack outputs are named with
32
+ * digitraffic-${environmentName}-${name} pattern and this function takes care of it
33
+ */
34
+ export function importValue(environmentName: string, name: string): string {
35
+ return Fn.importValue(outputName(environmentName, name));
36
+ }
37
+
38
+ /**
39
+ * Export value as stack output. Use same naming pattern as importValue.
40
+ */
41
+ export function exportValue(
42
+ stack: Stack,
43
+ environmentName: string,
44
+ name: string,
45
+ value: string
46
+ ) {
47
+ const exportName = outputName(environmentName, name);
48
+
49
+ new CfnOutput(stack, exportName, {
50
+ exportName,
51
+ value,
52
+ });
53
+ }
54
+
55
+ export function outputName(environmentName: string, name: string): string {
56
+ return `digitraffic-${environmentName}-${name}`;
57
+ }
@@ -78,8 +78,8 @@ export class DigitrafficRestApi extends RestApi {
78
78
  return newKeyId;
79
79
  }
80
80
 
81
- createUsagePlanV2(apiName: string): string {
82
- const newKeyId = createDefaultUsagePlan(this, apiName).keyId;
81
+ createUsagePlanV2(apiName: string, apiKey?: string): string {
82
+ const newKeyId = createDefaultUsagePlan(this, apiName, apiKey).keyId;
83
83
 
84
84
  this.apiKeyIds.push(newKeyId);
85
85
 
@@ -0,0 +1,88 @@
1
+ import { Duration, RemovalPolicy, Stack } from "aws-cdk-lib";
2
+ import { Construct } from "constructs";
3
+ import {
4
+ PrivateHostedZone,
5
+ RecordSet,
6
+ RecordTarget,
7
+ RecordType,
8
+ } from "aws-cdk-lib/aws-route53";
9
+ import { InfraStackConfiguration } from "./intra-stack-configuration";
10
+ import { importValue, importVpc } from "../import-util";
11
+ import { DbStack } from "./db-stack";
12
+ import { DbProxyStack } from "./db-proxy-stack";
13
+
14
+ const DEFAULT_RECORD_TTL = Duration.seconds(30);
15
+
16
+ /**
17
+ * Creates a dns local zone and creates records for cluster endpoints and proxy endpoints.
18
+ *
19
+ */
20
+ export class DbDnsStack extends Stack {
21
+ constructor(scope: Construct, id: string, isc: InfraStackConfiguration) {
22
+ super(scope, id, {
23
+ env: isc.env,
24
+ });
25
+
26
+ this.createDnsRecords(isc);
27
+ }
28
+
29
+ createDnsRecords(isc: InfraStackConfiguration) {
30
+ const vpc = importVpc(this, isc.environmentName);
31
+ const zone = new PrivateHostedZone(this, "DNSHostedZone", {
32
+ zoneName: isc.environmentName + ".local",
33
+ vpc,
34
+ });
35
+
36
+ zone.applyRemovalPolicy(RemovalPolicy.RETAIN);
37
+
38
+ const clusterReaderEndpoint = importValue(
39
+ isc.environmentName,
40
+ DbStack.CLUSTER_READ_ENDPOINT_EXPORT_NAME
41
+ );
42
+ const clusterWriterEndpoint = importValue(
43
+ isc.environmentName,
44
+ DbStack.CLUSTER_WRITE_ENDPOINT_EXPORT_NAME
45
+ );
46
+
47
+ const proxyReaderEndpoint = importValue(
48
+ isc.environmentName,
49
+ DbProxyStack.PROXY_READER_EXPORT_NAME
50
+ );
51
+ const proxyWriterEndpoint = importValue(
52
+ isc.environmentName,
53
+ DbProxyStack.PROXY_WRITER_EXPORT_NAME
54
+ );
55
+
56
+ new RecordSet(this, "ReaderRecord", {
57
+ recordType: RecordType.CNAME,
58
+ recordName: `db-ro.${isc.environmentName}.local`,
59
+ target: RecordTarget.fromValues(clusterReaderEndpoint),
60
+ ttl: DEFAULT_RECORD_TTL,
61
+ zone,
62
+ });
63
+
64
+ new RecordSet(this, "WriterRecord", {
65
+ recordType: RecordType.CNAME,
66
+ recordName: `db.${isc.environmentName}.local`,
67
+ target: RecordTarget.fromValues(clusterWriterEndpoint),
68
+ ttl: DEFAULT_RECORD_TTL,
69
+ zone,
70
+ });
71
+
72
+ new RecordSet(this, "ProxyReaderRecord", {
73
+ recordType: RecordType.CNAME,
74
+ recordName: `proxy-ro.${isc.environmentName}.local`,
75
+ target: RecordTarget.fromValues(proxyReaderEndpoint),
76
+ ttl: DEFAULT_RECORD_TTL,
77
+ zone,
78
+ });
79
+
80
+ new RecordSet(this, "ProxyWriterRecord", {
81
+ recordType: RecordType.CNAME,
82
+ recordName: `proxy.${isc.environmentName}.local`,
83
+ target: RecordTarget.fromValues(proxyWriterEndpoint),
84
+ ttl: DEFAULT_RECORD_TTL,
85
+ zone,
86
+ });
87
+ }
88
+ }
@@ -0,0 +1,129 @@
1
+ import { Duration, Stack } from "aws-cdk-lib";
2
+ import { Construct } from "constructs";
3
+ import {
4
+ CfnDBProxyEndpoint,
5
+ DatabaseCluster,
6
+ DatabaseClusterEngine,
7
+ DatabaseProxy,
8
+ ProxyTarget,
9
+ } from "aws-cdk-lib/aws-rds";
10
+ import { ISecret, Secret } from "aws-cdk-lib/aws-secretsmanager";
11
+ import { IVpc, SecurityGroup } from "aws-cdk-lib/aws-ec2";
12
+ import { InfraStackConfiguration } from "./intra-stack-configuration";
13
+ import { DbConfiguration, DbStack } from "./db-stack";
14
+ import { exportValue, importValue, importVpc } from "../import-util";
15
+
16
+ /**
17
+ * A stack that creates a Database proxy.
18
+ */
19
+ export class DbProxyStack extends Stack {
20
+ public static PROXY_READER_EXPORT_NAME = "db-reader-endpoint";
21
+ public static PROXY_WRITER_EXPORT_NAME = "db-writer-endpoint";
22
+
23
+ readonly isc: InfraStackConfiguration;
24
+
25
+ constructor(
26
+ scope: Construct,
27
+ id: string,
28
+ isc: InfraStackConfiguration,
29
+ configuration: DbConfiguration
30
+ ) {
31
+ super(scope, id, {
32
+ env: isc.env,
33
+ });
34
+
35
+ this.isc = isc;
36
+
37
+ const vpc = importVpc(this, isc.environmentName);
38
+ const secret = Secret.fromSecretAttributes(this, "proxy-secret", {
39
+ secretCompleteArn: configuration.secretArn,
40
+ });
41
+ const proxy = this.createProxy(vpc, secret, configuration);
42
+ const readerEndpoint = this.createProxyEndpoints(
43
+ vpc,
44
+ proxy,
45
+ configuration.securityGroupId
46
+ );
47
+ this.setOutputs(configuration, proxy, readerEndpoint);
48
+ }
49
+
50
+ createProxy(vpc: IVpc, secret: ISecret, configuration: DbConfiguration) {
51
+ const proxyId = `${this.isc.environmentName}-proxy`;
52
+ const securityGroup = SecurityGroup.fromSecurityGroupId(
53
+ this,
54
+ "securitygroup",
55
+ configuration.securityGroupId
56
+ );
57
+
58
+ const cluster = DatabaseCluster.fromDatabaseClusterAttributes(
59
+ this,
60
+ "db-cluster",
61
+ {
62
+ clusterIdentifier: importValue(
63
+ this.isc.environmentName,
64
+ DbStack.CLUSTER_IDENTIFIER_EXPORT_NAME
65
+ ),
66
+ engine: DatabaseClusterEngine.AURORA_POSTGRESQL,
67
+ port: DbStack.CLUSTER_PORT,
68
+ }
69
+ );
70
+
71
+ // CDK tries to allow connections between proxy and cluster
72
+ // this does not work on cluster references
73
+ cluster.connections.allowDefaultPortFrom = () => {
74
+ /* nothing */
75
+ };
76
+
77
+ return new DatabaseProxy(this, proxyId, {
78
+ dbProxyName: configuration.dbProxyName ?? "AuroraProxy",
79
+ securityGroups: [securityGroup],
80
+ proxyTarget: ProxyTarget.fromCluster(cluster),
81
+ idleClientTimeout: Duration.seconds(1800),
82
+ maxConnectionsPercent: 50,
83
+ maxIdleConnectionsPercent: 25,
84
+ borrowTimeout: Duration.seconds(120),
85
+ requireTLS: false,
86
+ secrets: [secret],
87
+ vpc: vpc,
88
+ });
89
+ }
90
+
91
+ createProxyEndpoints(
92
+ vpc: IVpc,
93
+ proxy: DatabaseProxy,
94
+ securityGroupId: string
95
+ ) {
96
+ return new CfnDBProxyEndpoint(this, "ReaderEndpoint", {
97
+ dbProxyEndpointName: "ReaderEndpoint",
98
+ dbProxyName: proxy.dbProxyName,
99
+ vpcSubnetIds: vpc.privateSubnets.map((sub) => sub.subnetId),
100
+ vpcSecurityGroupIds: [securityGroupId],
101
+ targetRole: "READ_ONLY",
102
+ });
103
+ }
104
+
105
+ setOutputs(
106
+ configuration: DbConfiguration,
107
+ proxy: DatabaseProxy,
108
+ proxyEndpoint: CfnDBProxyEndpoint
109
+ ) {
110
+ const readerEndpoint =
111
+ configuration.instances > 1
112
+ ? proxyEndpoint.attrEndpoint
113
+ : proxy.endpoint;
114
+
115
+ // if only one instance, then there is no reader-endpoint
116
+ exportValue(
117
+ this,
118
+ this.isc.environmentName,
119
+ DbProxyStack.PROXY_READER_EXPORT_NAME,
120
+ readerEndpoint
121
+ );
122
+ exportValue(
123
+ this,
124
+ this.isc.environmentName,
125
+ DbProxyStack.PROXY_WRITER_EXPORT_NAME,
126
+ proxy.endpoint
127
+ );
128
+ }
129
+ }