@infoxchange/make-it-so 2.13.0-internal-testing-randomise-subnet.2 → 2.13.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.
- package/README.md +32 -8
- package/dist/cdk-constructs/IxDnsRecord.d.ts +4 -1
- package/dist/cdk-constructs/IxDnsRecord.d.ts.map +1 -1
- package/dist/cdk-constructs/IxDnsRecord.js +19 -2
- package/dist/cdk-constructs/IxSESIdentity.d.ts +12 -0
- package/dist/cdk-constructs/IxSESIdentity.d.ts.map +1 -0
- package/dist/cdk-constructs/IxSESIdentity.js +45 -0
- package/dist/cdk-constructs/IxVpcDetails.d.ts.map +1 -1
- package/dist/cdk-constructs/IxVpcDetails.js +1 -12
- package/dist/cdk-constructs/SiteOidcAuth/index.js +1 -1
- package/dist/cdk-constructs/index.d.ts +1 -0
- package/dist/cdk-constructs/index.d.ts.map +1 -1
- package/dist/cdk-constructs/index.js +1 -0
- package/dist/lib/utils/objects.d.ts +1 -1
- package/dist/lib/utils/objects.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cdk-constructs/IxDnsRecord.ts +28 -4
- package/src/cdk-constructs/IxSESIdentity.ts +70 -0
- package/src/cdk-constructs/IxVpcDetails.ts +1 -12
- package/src/cdk-constructs/SiteOidcAuth/index.ts +1 -1
- package/src/cdk-constructs/index.ts +1 -0
- package/src/lib/utils/objects.ts +5 -1
package/README.md
CHANGED
|
@@ -250,14 +250,38 @@ new IxDnsRecord(scope, "IxDnsRecord", {
|
|
|
250
250
|
|
|
251
251
|
#### Options:
|
|
252
252
|
|
|
253
|
-
| Prop | Type
|
|
254
|
-
| ------------ |
|
|
255
|
-
| type | "A" \| "CNAME" \| "NS" \| "SOA" \| "ALIAS" | DNS record type |
|
|
256
|
-
| name | string
|
|
257
|
-
| value | string
|
|
258
|
-
| ttl | number
|
|
259
|
-
| hostedZoneId | string
|
|
260
|
-
| aliasZoneId | string
|
|
253
|
+
| Prop | Type | Description |
|
|
254
|
+
| ------------ | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
255
|
+
| type | "A" \| "CNAME" \| "NS" \| "SOA" \| "ALIAS" \| "TXT" \| "MX" | DNS record type |
|
|
256
|
+
| name | string | DNS record FQDN |
|
|
257
|
+
| value | string | DNS record value |
|
|
258
|
+
| ttl | number | (optional) TTL value for DNS record |
|
|
259
|
+
| hostedZoneId | string | (optional) The ID of the Route53 HostedZone belonging to the dns-hosting account in which to create the DNS record. If not given the correct HostedZone will be inferred from the domain in the "value" prop. |
|
|
260
|
+
| aliasZoneId | string | (only needed if type = "Alias") the Route53 HostedZone that the target of the alias record lives in. Generally this will be the well known ID of a HostedZone for a AWS service itself that is managed by AWS, not an end-user. |
|
|
261
|
+
| priority | number | (only needed if type = "MX") The priority level of the MX record. |
|
|
262
|
+
|
|
263
|
+
</details>
|
|
264
|
+
|
|
265
|
+
<details>
|
|
266
|
+
<summary><strong>IxSESIdentity</strong> - Creates an SES domain identity for a domain managed by IX.</summary>
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import { IxSESIdentity } from "@infoxchange/make-it-so/cdk-constructs";
|
|
270
|
+
|
|
271
|
+
new IxSESIdentity(scope, "IxSESIdentity", {
|
|
272
|
+
// Email identity domain will be: example.dev.ixapps.org
|
|
273
|
+
// Custom mail from domain will be: info.example.dev.ixapps.org
|
|
274
|
+
domain: "example.dev.ixapps.org",
|
|
275
|
+
mailFromSubdomain: "info", // optional, "mail" will be used otherwise
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### Options:
|
|
280
|
+
|
|
281
|
+
| Prop | Type | Description |
|
|
282
|
+
| ----------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
283
|
+
| domain | string | The domain of the identity. An email address can also be provided in which case the domain will be extracted from the email. |
|
|
284
|
+
| mailFromSubdomain | string | (optional) by default the custom mail from domain will be `mail.${domain}`. This lets you change that. It should be given as just the subdomain part, not the fully qualified domain. |
|
|
261
285
|
|
|
262
286
|
</details>
|
|
263
287
|
|
|
@@ -7,10 +7,13 @@ type Props = {
|
|
|
7
7
|
ttl?: number;
|
|
8
8
|
hostedZoneId?: string;
|
|
9
9
|
} & ({
|
|
10
|
-
type: "A" | "CNAME" | "NS" | "SOA";
|
|
10
|
+
type: "A" | "CNAME" | "NS" | "SOA" | "TXT";
|
|
11
11
|
} | {
|
|
12
12
|
type: "ALIAS";
|
|
13
13
|
aliasZoneId: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: "MX";
|
|
16
|
+
priority: number;
|
|
14
17
|
});
|
|
15
18
|
export declare class IxDnsRecord extends Construct {
|
|
16
19
|
constructor(scope: ConstructScope, id: ConstructId, props: Props);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IxDnsRecord.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/IxDnsRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKvC,KAAK,cAAc,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,KAAK,WAAW,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,CACA;IACE,IAAI,EAAE,GAAG,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"IxDnsRecord.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/IxDnsRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKvC,KAAK,cAAc,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,KAAK,WAAW,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,CACA;IACE,IAAI,EAAE,GAAG,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC;CAC5C,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,GACD;IACE,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB,CACJ,CAAC;AAEF,qBAAa,WAAY,SAAQ,SAAS;gBAC5B,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;IAKhE,OAAO,CAAC,eAAe;CA6CxB"}
|
|
@@ -9,14 +9,31 @@ export class IxDnsRecord extends Construct {
|
|
|
9
9
|
}
|
|
10
10
|
createDnsRecord(scope, id, constructProps) {
|
|
11
11
|
const dnsRecordUpdaterLambdaArn = StringParameter.valueForStringParameter(scope, "/shared-services/route53/lambdaArn");
|
|
12
|
-
const
|
|
12
|
+
const keysMap = {
|
|
13
13
|
name: "RecordFQDN",
|
|
14
14
|
value: "RecordValue",
|
|
15
15
|
ttl: "RecordTTL",
|
|
16
16
|
hostedZoneId: "HostedZoneId",
|
|
17
17
|
type: "RecordType",
|
|
18
18
|
aliasZoneId: "AliasZoneId",
|
|
19
|
-
}
|
|
19
|
+
};
|
|
20
|
+
let lambdaProps;
|
|
21
|
+
if (constructProps.type === "TXT") {
|
|
22
|
+
lambdaProps = remapKeys({
|
|
23
|
+
...constructProps,
|
|
24
|
+
value: `"${constructProps.value}"`,
|
|
25
|
+
}, keysMap);
|
|
26
|
+
}
|
|
27
|
+
else if (constructProps.type === "MX") {
|
|
28
|
+
const { priority, ...rest } = constructProps;
|
|
29
|
+
lambdaProps = remapKeys({
|
|
30
|
+
...rest,
|
|
31
|
+
value: `${priority} ${rest.value}`,
|
|
32
|
+
}, keysMap);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
lambdaProps = remapKeys(constructProps, keysMap);
|
|
36
|
+
}
|
|
20
37
|
new CustomResource(scope, id + "-CertificateCustomResource", {
|
|
21
38
|
resourceType: "Custom::DNSRecordUpdaterLambda",
|
|
22
39
|
serviceToken: dnsRecordUpdaterLambdaArn,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Construct } from "constructs";
|
|
2
|
+
type ConstructScope = ConstructorParameters<typeof Construct>[0];
|
|
3
|
+
type ConstructId = ConstructorParameters<typeof Construct>[1];
|
|
4
|
+
type Props = {
|
|
5
|
+
domain: string;
|
|
6
|
+
mailFromSubdomain?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare class IxSESIdentity extends Construct {
|
|
9
|
+
constructor(scope: ConstructScope, id: ConstructId, props: Props);
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=IxSESIdentity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IxSESIdentity.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/IxSESIdentity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKvC,KAAK,cAAc,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,KAAK,WAAW,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;CAuDjE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Construct } from "constructs";
|
|
2
|
+
import { IxDnsRecord } from "./IxDnsRecord.js";
|
|
3
|
+
import * as ses from "aws-cdk-lib/aws-ses";
|
|
4
|
+
import * as cdk from "aws-cdk-lib";
|
|
5
|
+
export class IxSESIdentity extends Construct {
|
|
6
|
+
constructor(scope, id, props) {
|
|
7
|
+
const domain = props.domain.includes("@")
|
|
8
|
+
? props.domain.split("@")[1]
|
|
9
|
+
: props.domain;
|
|
10
|
+
const mailFromDomain = `${props.mailFromSubdomain ?? "mail"}.${domain}`;
|
|
11
|
+
super(scope, id);
|
|
12
|
+
const identity = new ses.EmailIdentity(scope, `${id}EmailIdentity`, {
|
|
13
|
+
identity: ses.Identity.domain(domain),
|
|
14
|
+
mailFromDomain,
|
|
15
|
+
});
|
|
16
|
+
// Based on https://github.com/aws/aws-cdk/blob/e2ef65a26c833ecb4a29c22e070c3c5f01c31995/packages/aws-cdk-lib/aws-ses/lib/email-identity.ts#L247
|
|
17
|
+
for (const i of [1, 2, 3]) {
|
|
18
|
+
new IxDnsRecord(scope, `${id}DkimDnsToken${i}`, {
|
|
19
|
+
type: "CNAME",
|
|
20
|
+
name: identity[`dkimDnsTokenName${i}`],
|
|
21
|
+
value: identity[`dkimDnsTokenValue${i}`],
|
|
22
|
+
ttl: 1800,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
// Based on
|
|
26
|
+
// https://github.com/aws/aws-cdk/blob/e2ef65a26c833ecb4a29c22e070c3c5f01c31995/packages/aws-cdk-lib/aws-ses/lib/email-identity.ts#L512
|
|
27
|
+
new IxDnsRecord(scope, `${id}MailFromMxRecord`, {
|
|
28
|
+
type: "MX",
|
|
29
|
+
name: mailFromDomain,
|
|
30
|
+
value: `feedback-smtp.${cdk.Stack.of(scope).region}.amazonses.com`,
|
|
31
|
+
priority: 10,
|
|
32
|
+
});
|
|
33
|
+
new IxDnsRecord(scope, `${id}MailFromTxtRecord`, {
|
|
34
|
+
type: "TXT",
|
|
35
|
+
name: mailFromDomain,
|
|
36
|
+
value: "v=spf1 include:amazonses.com ~all",
|
|
37
|
+
});
|
|
38
|
+
// Set up DMARC record
|
|
39
|
+
new IxDnsRecord(scope, `${id}DMARC`, {
|
|
40
|
+
type: "TXT",
|
|
41
|
+
name: `_dmarc.${domain}`,
|
|
42
|
+
value: "v=DMARC1; p=none;",
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IxVpcDetails.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/IxVpcDetails.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAO,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAGhD,KAAK,cAAc,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,KAAK,WAAW,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D,qBAAa,YAAa,SAAQ,SAAS;IAClC,GAAG,EAAE,IAAI,CAAC;gBAEL,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,WAAW;IAKlD,OAAO,CAAC,MAAM;IAad,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"IxVpcDetails.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/IxVpcDetails.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAO,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAGhD,KAAK,cAAc,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,KAAK,WAAW,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D,qBAAa,YAAa,SAAQ,SAAS;IAClC,GAAG,EAAE,IAAI,CAAC;gBAEL,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,WAAW;IAKlD,OAAO,CAAC,MAAM;IAad,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC;CAQ7D"}
|
|
@@ -21,17 +21,6 @@ export class IxVpcDetails extends Construct {
|
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
static getVpcSubnetIds(scope) {
|
|
24
|
-
|
|
25
|
-
let suffix = "";
|
|
26
|
-
if (workloadGroup === "ds") {
|
|
27
|
-
const possibleSuffixes = ["", "-2"];
|
|
28
|
-
// Randomly select a suffix to spread workload's IP usage across both sets of subnets. Use the app name as a seed
|
|
29
|
-
// to ensure consistent selection on redeploys.
|
|
30
|
-
const hash = appName
|
|
31
|
-
.split("")
|
|
32
|
-
.reduce((acc, char) => acc + char.charCodeAt(0), 0);
|
|
33
|
-
suffix = possibleSuffixes[hash % possibleSuffixes.length];
|
|
34
|
-
}
|
|
35
|
-
return [1, 2, 3].map((subnetNum) => StringParameter.valueForStringParameter(scope, `/vpc/subnet/private-${workloadGroup}${suffix}/${subnetNum}/id`));
|
|
24
|
+
return [1, 2, 3].map((subnetNum) => StringParameter.valueForStringParameter(scope, `/vpc/subnet/private-${ixDeployConfig.workloadGroup}/${subnetNum}/id`));
|
|
36
25
|
}
|
|
37
26
|
}
|
|
@@ -165,7 +165,7 @@ export class SiteOidcAuth extends Construct {
|
|
|
165
165
|
origin: new CloudFrontOrigins.HttpOrigin(CDK.Fn.parseDomainName(authRouteFunctionUrl.url)),
|
|
166
166
|
allowedMethods: CloudFront.AllowedMethods.ALLOW_ALL,
|
|
167
167
|
cachePolicy: new CloudFront.CachePolicy(scope, `${this.id}AllowAllCookiesPolicy`, {
|
|
168
|
-
cachePolicyName: `${
|
|
168
|
+
cachePolicyName: `${this.id}-AllowAllCookiesPolicy`,
|
|
169
169
|
comment: "Cache policy that forwards all cookies",
|
|
170
170
|
defaultTtl: CDK.Duration.seconds(1),
|
|
171
171
|
minTtl: CDK.Duration.seconds(1),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare function remapKeys<SourceObject extends object, MapObject extends Record<keyof SourceObject, string>>(object: SourceObject, keyMap: Readonly<MapObject>): {
|
|
2
|
-
[k in keyof SourceObject]:
|
|
2
|
+
[k in keyof SourceObject as k extends keyof MapObject ? MapObject[k] : k]: SourceObject[k];
|
|
3
3
|
};
|
|
4
4
|
//# sourceMappingURL=objects.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objects.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/objects.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CACvB,YAAY,SAAS,MAAM,EAC3B,SAAS,SAAS,MAAM,CAAC,MAAM,YAAY,EAAE,MAAM,CAAC,EAEpD,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,GAC1B;
|
|
1
|
+
{"version":3,"file":"objects.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/objects.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CACvB,YAAY,SAAS,MAAM,EAC3B,SAAS,SAAS,MAAM,CAAC,MAAM,YAAY,EAAE,MAAM,CAAC,EAEpD,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,GAC1B;KACA,CAAC,IAAI,MAAM,YAAY,IAAI,CAAC,SAAS,MAAM,SAAS,GACjD,SAAS,CAAC,CAAC,CAAC,GACZ,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;CACxB,CAQA"}
|
package/package.json
CHANGED
|
@@ -13,12 +13,16 @@ type Props = {
|
|
|
13
13
|
hostedZoneId?: string;
|
|
14
14
|
} & (
|
|
15
15
|
| {
|
|
16
|
-
type: "A" | "CNAME" | "NS" | "SOA";
|
|
16
|
+
type: "A" | "CNAME" | "NS" | "SOA" | "TXT";
|
|
17
17
|
}
|
|
18
18
|
| {
|
|
19
19
|
type: "ALIAS";
|
|
20
20
|
aliasZoneId: string;
|
|
21
21
|
}
|
|
22
|
+
| {
|
|
23
|
+
type: "MX";
|
|
24
|
+
priority: number;
|
|
25
|
+
}
|
|
22
26
|
);
|
|
23
27
|
|
|
24
28
|
export class IxDnsRecord extends Construct {
|
|
@@ -36,15 +40,35 @@ export class IxDnsRecord extends Construct {
|
|
|
36
40
|
scope,
|
|
37
41
|
"/shared-services/route53/lambdaArn",
|
|
38
42
|
);
|
|
39
|
-
|
|
40
|
-
const lambdaProps = remapKeys(constructProps, {
|
|
43
|
+
const keysMap = {
|
|
41
44
|
name: "RecordFQDN",
|
|
42
45
|
value: "RecordValue",
|
|
43
46
|
ttl: "RecordTTL",
|
|
44
47
|
hostedZoneId: "HostedZoneId",
|
|
45
48
|
type: "RecordType",
|
|
46
49
|
aliasZoneId: "AliasZoneId",
|
|
47
|
-
}
|
|
50
|
+
};
|
|
51
|
+
let lambdaProps;
|
|
52
|
+
if (constructProps.type === "TXT") {
|
|
53
|
+
lambdaProps = remapKeys(
|
|
54
|
+
{
|
|
55
|
+
...constructProps,
|
|
56
|
+
value: `"${constructProps.value}"`,
|
|
57
|
+
},
|
|
58
|
+
keysMap,
|
|
59
|
+
);
|
|
60
|
+
} else if (constructProps.type === "MX") {
|
|
61
|
+
const { priority, ...rest } = constructProps;
|
|
62
|
+
lambdaProps = remapKeys(
|
|
63
|
+
{
|
|
64
|
+
...rest,
|
|
65
|
+
value: `${priority} ${rest.value}`,
|
|
66
|
+
},
|
|
67
|
+
keysMap,
|
|
68
|
+
);
|
|
69
|
+
} else {
|
|
70
|
+
lambdaProps = remapKeys(constructProps, keysMap);
|
|
71
|
+
}
|
|
48
72
|
|
|
49
73
|
new CustomResource(scope, id + "-CertificateCustomResource", {
|
|
50
74
|
resourceType: "Custom::DNSRecordUpdaterLambda",
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Construct } from "constructs";
|
|
2
|
+
import { IxDnsRecord } from "./IxDnsRecord.js";
|
|
3
|
+
import * as ses from "aws-cdk-lib/aws-ses";
|
|
4
|
+
import * as cdk from "aws-cdk-lib";
|
|
5
|
+
|
|
6
|
+
type ConstructScope = ConstructorParameters<typeof Construct>[0];
|
|
7
|
+
type ConstructId = ConstructorParameters<typeof Construct>[1];
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
domain: string;
|
|
11
|
+
mailFromSubdomain?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export class IxSESIdentity extends Construct {
|
|
15
|
+
constructor(scope: ConstructScope, id: ConstructId, props: Props) {
|
|
16
|
+
const domain = props.domain.includes("@")
|
|
17
|
+
? props.domain.split("@")[1]
|
|
18
|
+
: props.domain;
|
|
19
|
+
const mailFromDomain = `${props.mailFromSubdomain ?? "mail"}.${domain}`;
|
|
20
|
+
|
|
21
|
+
super(scope, id);
|
|
22
|
+
|
|
23
|
+
const identity = new ses.EmailIdentity(scope, `${id}EmailIdentity`, {
|
|
24
|
+
identity: ses.Identity.domain(domain),
|
|
25
|
+
mailFromDomain,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Based on https://github.com/aws/aws-cdk/blob/e2ef65a26c833ecb4a29c22e070c3c5f01c31995/packages/aws-cdk-lib/aws-ses/lib/email-identity.ts#L247
|
|
29
|
+
for (const i of [1, 2, 3]) {
|
|
30
|
+
new IxDnsRecord(scope, `${id}DkimDnsToken${i}`, {
|
|
31
|
+
type: "CNAME",
|
|
32
|
+
name: identity[
|
|
33
|
+
`dkimDnsTokenName${i}` as
|
|
34
|
+
| "dkimDnsTokenName1"
|
|
35
|
+
| "dkimDnsTokenName2"
|
|
36
|
+
| "dkimDnsTokenName3"
|
|
37
|
+
],
|
|
38
|
+
value:
|
|
39
|
+
identity[
|
|
40
|
+
`dkimDnsTokenValue${i}` as
|
|
41
|
+
| "dkimDnsTokenValue1"
|
|
42
|
+
| "dkimDnsTokenValue2"
|
|
43
|
+
| "dkimDnsTokenValue3"
|
|
44
|
+
],
|
|
45
|
+
ttl: 1800,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Based on
|
|
50
|
+
// https://github.com/aws/aws-cdk/blob/e2ef65a26c833ecb4a29c22e070c3c5f01c31995/packages/aws-cdk-lib/aws-ses/lib/email-identity.ts#L512
|
|
51
|
+
new IxDnsRecord(scope, `${id}MailFromMxRecord`, {
|
|
52
|
+
type: "MX",
|
|
53
|
+
name: mailFromDomain,
|
|
54
|
+
value: `feedback-smtp.${cdk.Stack.of(scope).region}.amazonses.com`,
|
|
55
|
+
priority: 10,
|
|
56
|
+
});
|
|
57
|
+
new IxDnsRecord(scope, `${id}MailFromTxtRecord`, {
|
|
58
|
+
type: "TXT",
|
|
59
|
+
name: mailFromDomain,
|
|
60
|
+
value: "v=spf1 include:amazonses.com ~all",
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Set up DMARC record
|
|
64
|
+
new IxDnsRecord(scope, `${id}DMARC`, {
|
|
65
|
+
type: "TXT",
|
|
66
|
+
name: `_dmarc.${domain}`,
|
|
67
|
+
value: "v=DMARC1; p=none;",
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -28,21 +28,10 @@ export class IxVpcDetails extends Construct {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
static getVpcSubnetIds(scope: ConstructScope): Array<string> {
|
|
31
|
-
const { workloadGroup, appName } = ixDeployConfig;
|
|
32
|
-
let suffix = "";
|
|
33
|
-
if (workloadGroup === "ds") {
|
|
34
|
-
const possibleSuffixes = ["", "-2"];
|
|
35
|
-
// Randomly select a suffix to spread workload's IP usage across both sets of subnets. Use the app name as a seed
|
|
36
|
-
// to ensure consistent selection on redeploys.
|
|
37
|
-
const hash = appName
|
|
38
|
-
.split("")
|
|
39
|
-
.reduce((acc, char) => acc + char.charCodeAt(0), 0);
|
|
40
|
-
suffix = possibleSuffixes[hash % possibleSuffixes.length];
|
|
41
|
-
}
|
|
42
31
|
return [1, 2, 3].map((subnetNum) =>
|
|
43
32
|
StringParameter.valueForStringParameter(
|
|
44
33
|
scope,
|
|
45
|
-
`/vpc/subnet/private-${workloadGroup}
|
|
34
|
+
`/vpc/subnet/private-${ixDeployConfig.workloadGroup}/${subnetNum}/id`,
|
|
46
35
|
),
|
|
47
36
|
);
|
|
48
37
|
}
|
|
@@ -274,7 +274,7 @@ export class SiteOidcAuth extends Construct {
|
|
|
274
274
|
scope,
|
|
275
275
|
`${this.id}AllowAllCookiesPolicy`,
|
|
276
276
|
{
|
|
277
|
-
cachePolicyName: `${
|
|
277
|
+
cachePolicyName: `${this.id}-AllowAllCookiesPolicy`,
|
|
278
278
|
comment: "Cache policy that forwards all cookies",
|
|
279
279
|
defaultTtl: CDK.Duration.seconds(1),
|
|
280
280
|
minTtl: CDK.Duration.seconds(1),
|
package/src/lib/utils/objects.ts
CHANGED
|
@@ -4,7 +4,11 @@ export function remapKeys<
|
|
|
4
4
|
>(
|
|
5
5
|
object: SourceObject,
|
|
6
6
|
keyMap: Readonly<MapObject>,
|
|
7
|
-
): {
|
|
7
|
+
): {
|
|
8
|
+
[k in keyof SourceObject as k extends keyof MapObject
|
|
9
|
+
? MapObject[k]
|
|
10
|
+
: k]: SourceObject[k];
|
|
11
|
+
} {
|
|
8
12
|
return Object.fromEntries(
|
|
9
13
|
Object.entries(object).map(([key, value]) => {
|
|
10
14
|
// @ts-expect-error the typing for map() reduces keys to general string
|