@trautonen/cdk-dns-validated-certificate 0.0.2 → 0.0.4

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/.gitattributes CHANGED
@@ -22,4 +22,5 @@
22
22
  /LICENSE linguist-generated
23
23
  /package-lock.json linguist-generated
24
24
  /package.json linguist-generated
25
+ /src/certificate-requestor-function.ts linguist-generated
25
26
  /tsconfig.dev.json linguist-generated
package/.jsii CHANGED
@@ -3515,7 +3515,7 @@
3515
3515
  },
3516
3516
  "locationInModule": {
3517
3517
  "filename": "src/dns-validated-certificate.ts",
3518
- "line": 181
3518
+ "line": 180
3519
3519
  },
3520
3520
  "parameters": [
3521
3521
  {
@@ -3554,7 +3554,7 @@
3554
3554
  "kind": "class",
3555
3555
  "locationInModule": {
3556
3556
  "filename": "src/dns-validated-certificate.ts",
3557
- "line": 152
3557
+ "line": 151
3558
3558
  },
3559
3559
  "methods": [
3560
3560
  {
@@ -3565,7 +3565,7 @@
3565
3565
  },
3566
3566
  "locationInModule": {
3567
3567
  "filename": "src/dns-validated-certificate.ts",
3568
- "line": 285
3568
+ "line": 282
3569
3569
  },
3570
3570
  "name": "applyRemovalPolicy",
3571
3571
  "overrides": "aws-cdk-lib.Resource",
@@ -3586,7 +3586,7 @@
3586
3586
  },
3587
3587
  "locationInModule": {
3588
3588
  "filename": "src/dns-validated-certificate.ts",
3589
- "line": 273
3589
+ "line": 270
3590
3590
  },
3591
3591
  "name": "metricDaysToExpiry",
3592
3592
  "overrides": "aws-cdk-lib.aws_certificatemanager.ICertificate",
@@ -3616,7 +3616,7 @@
3616
3616
  "immutable": true,
3617
3617
  "locationInModule": {
3618
3618
  "filename": "src/dns-validated-certificate.ts",
3619
- "line": 154
3619
+ "line": 153
3620
3620
  },
3621
3621
  "name": "certificateArn",
3622
3622
  "overrides": "aws-cdk-lib.aws_certificatemanager.ICertificate",
@@ -3632,7 +3632,7 @@
3632
3632
  "immutable": true,
3633
3633
  "locationInModule": {
3634
3634
  "filename": "src/dns-validated-certificate.ts",
3635
- "line": 157
3635
+ "line": 156
3636
3636
  },
3637
3637
  "name": "certificateRegion",
3638
3638
  "type": {
@@ -3647,7 +3647,7 @@
3647
3647
  "immutable": true,
3648
3648
  "locationInModule": {
3649
3649
  "filename": "src/dns-validated-certificate.ts",
3650
- "line": 166
3650
+ "line": 165
3651
3651
  },
3652
3652
  "name": "domainName",
3653
3653
  "type": {
@@ -3662,7 +3662,7 @@
3662
3662
  "immutable": true,
3663
3663
  "locationInModule": {
3664
3664
  "filename": "src/dns-validated-certificate.ts",
3665
- "line": 160
3665
+ "line": 159
3666
3666
  },
3667
3667
  "name": "hostedZoneId",
3668
3668
  "type": {
@@ -3677,7 +3677,7 @@
3677
3677
  "immutable": true,
3678
3678
  "locationInModule": {
3679
3679
  "filename": "src/dns-validated-certificate.ts",
3680
- "line": 163
3680
+ "line": 162
3681
3681
  },
3682
3682
  "name": "hostedZoneName",
3683
3683
  "type": {
@@ -3692,7 +3692,7 @@
3692
3692
  "immutable": true,
3693
3693
  "locationInModule": {
3694
3694
  "filename": "src/dns-validated-certificate.ts",
3695
- "line": 169
3695
+ "line": 168
3696
3696
  },
3697
3697
  "name": "tags",
3698
3698
  "overrides": "aws-cdk-lib.ITaggable",
@@ -3713,7 +3713,7 @@
3713
3713
  "kind": "interface",
3714
3714
  "locationInModule": {
3715
3715
  "filename": "src/dns-validated-certificate.ts",
3716
- "line": 13
3716
+ "line": 12
3717
3717
  },
3718
3718
  "name": "DnsValidatedCertificateProps",
3719
3719
  "properties": [
@@ -3727,7 +3727,7 @@
3727
3727
  "immutable": true,
3728
3728
  "locationInModule": {
3729
3729
  "filename": "src/dns-validated-certificate.ts",
3730
- "line": 19
3730
+ "line": 18
3731
3731
  },
3732
3732
  "name": "domainName",
3733
3733
  "type": {
@@ -3744,7 +3744,7 @@
3744
3744
  "immutable": true,
3745
3745
  "locationInModule": {
3746
3746
  "filename": "src/dns-validated-certificate.ts",
3747
- "line": 27
3747
+ "line": 26
3748
3748
  },
3749
3749
  "name": "hostedZone",
3750
3750
  "type": {
@@ -3762,7 +3762,7 @@
3762
3762
  "immutable": true,
3763
3763
  "locationInModule": {
3764
3764
  "filename": "src/dns-validated-certificate.ts",
3765
- "line": 37
3765
+ "line": 36
3766
3766
  },
3767
3767
  "name": "certificateRegion",
3768
3768
  "optional": true,
@@ -3781,7 +3781,7 @@
3781
3781
  "immutable": true,
3782
3782
  "locationInModule": {
3783
3783
  "filename": "src/dns-validated-certificate.ts",
3784
- "line": 81
3784
+ "line": 80
3785
3785
  },
3786
3786
  "name": "cleanupValidationRecords",
3787
3787
  "optional": true,
@@ -3800,7 +3800,7 @@
3800
3800
  "immutable": true,
3801
3801
  "locationInModule": {
3802
3802
  "filename": "src/dns-validated-certificate.ts",
3803
- "line": 48
3803
+ "line": 47
3804
3804
  },
3805
3805
  "name": "customResourceRole",
3806
3806
  "optional": true,
@@ -3819,7 +3819,7 @@
3819
3819
  "immutable": true,
3820
3820
  "locationInModule": {
3821
3821
  "filename": "src/dns-validated-certificate.ts",
3822
- "line": 106
3822
+ "line": 105
3823
3823
  },
3824
3824
  "name": "removalPolicy",
3825
3825
  "optional": true,
@@ -3839,7 +3839,7 @@
3839
3839
  "immutable": true,
3840
3840
  "locationInModule": {
3841
3841
  "filename": "src/dns-validated-certificate.ts",
3842
- "line": 93
3842
+ "line": 92
3843
3843
  },
3844
3844
  "name": "transparencyLoggingEnabled",
3845
3845
  "optional": true,
@@ -3858,7 +3858,7 @@
3858
3858
  "immutable": true,
3859
3859
  "locationInModule": {
3860
3860
  "filename": "src/dns-validated-certificate.ts",
3861
- "line": 69
3861
+ "line": 68
3862
3862
  },
3863
3863
  "name": "validationExternalId",
3864
3864
  "optional": true,
@@ -3877,7 +3877,7 @@
3877
3877
  "immutable": true,
3878
3878
  "locationInModule": {
3879
3879
  "filename": "src/dns-validated-certificate.ts",
3880
- "line": 60
3880
+ "line": 59
3881
3881
  },
3882
3882
  "name": "validationRole",
3883
3883
  "optional": true,
@@ -3889,6 +3889,6 @@
3889
3889
  "symbolId": "src/dns-validated-certificate:DnsValidatedCertificateProps"
3890
3890
  }
3891
3891
  },
3892
- "version": "0.0.2",
3893
- "fingerprint": "0YmErv+JlvcbPpHH8WXQhUgUxY+AN4irXPqxQZJ3tFI="
3892
+ "version": "0.0.4",
3893
+ "fingerprint": "9isTWJXuM6/JDWdtr/eWOBbNTViUHK0oLHtxzz9I3Y0="
3894
3894
  }
package/.prettierignore CHANGED
@@ -1 +1,2 @@
1
1
  # ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen".
2
+ src/certificate-requestor-function.ts
package/.projenrc.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { awscdk } from 'projen'
2
+ import { LambdaRuntime } from 'projen/lib/awscdk'
2
3
  import { NodePackageManager, NpmAccess, ProseWrap } from 'projen/lib/javascript'
3
4
 
4
5
  const awsSdkVersion = '^3.0.0'
@@ -20,6 +21,14 @@ const project = new awscdk.AwsCdkConstructLibrary({
20
21
  releaseToNpm: true,
21
22
  npmAccess: NpmAccess.PUBLIC,
22
23
 
24
+ lambdaOptions: {
25
+ runtime: LambdaRuntime.NODEJS_18_X,
26
+ bundlingOptions: {
27
+ externals: ['@aws-sdk/*'],
28
+ sourcemap: true,
29
+ },
30
+ },
31
+
23
32
  packageManager: NodePackageManager.NPM,
24
33
  prettier: true,
25
34
  prettierOptions: {
@@ -43,7 +52,7 @@ const project = new awscdk.AwsCdkConstructLibrary({
43
52
  })
44
53
 
45
54
  project.eslint?.addRules({
46
- 'import/no-extraneous-dependencies': ['error', { devDependencies: ['src/lambda/**/*.ts'] }],
55
+ 'import/no-extraneous-dependencies': ['error', { devDependencies: ['src/**/*.lambda.ts'] }],
47
56
  })
48
57
 
49
58
  project.synth()
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/certificate-requestor.lambda.ts
31
+ var certificate_requestor_lambda_exports = {};
32
+ __export(certificate_requestor_lambda_exports, {
33
+ handler: () => handler
34
+ });
35
+ module.exports = __toCommonJS(certificate_requestor_lambda_exports);
36
+ var crypto = __toESM(require("crypto"));
37
+ var import_client_acm = require("@aws-sdk/client-acm");
38
+ var import_client_route_53 = require("@aws-sdk/client-route-53");
39
+ var import_client_sts = require("@aws-sdk/client-sts");
40
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
41
+ var containsSame = (array1, array2) => {
42
+ if (array1.length !== array2.length)
43
+ return false;
44
+ return array1.every((v1) => array2.includes(v1));
45
+ };
46
+ var tryFor = async (maxSeconds, timeoutError, fn) => {
47
+ const startTime = Date.now();
48
+ for (let i = 0; true; i++) {
49
+ if (Date.now() > startTime + maxSeconds * 1e3) {
50
+ throw new Error(timeoutError);
51
+ }
52
+ const result = await fn();
53
+ if (result !== null) {
54
+ return result;
55
+ }
56
+ const base = Math.pow(2, i);
57
+ await sleep(Math.random() * base * 50 + base * 150);
58
+ }
59
+ };
60
+ var parseProperties = (properties) => {
61
+ return properties;
62
+ };
63
+ var parseDomainValidationRecords = (certificate) => {
64
+ const options = certificate.DomainValidationOptions ?? [];
65
+ console.log("options: ", options);
66
+ if (options.length > 0 && options.every((opt) => opt.ResourceRecord?.Name)) {
67
+ const uniqueRecords = [...new Map(options.map((opt) => [opt.ResourceRecord?.Name, opt.ResourceRecord])).values()];
68
+ return uniqueRecords.map((record) => {
69
+ return {
70
+ Name: record.Name,
71
+ Type: record.Type,
72
+ TTL: 30,
73
+ ResourceRecords: [
74
+ {
75
+ Value: record.Value
76
+ }
77
+ ]
78
+ };
79
+ });
80
+ }
81
+ return null;
82
+ };
83
+ var changeRecordSets = async (route53, action, records, hostedZoneId) => {
84
+ const changeRecordSetsInput = {
85
+ HostedZoneId: hostedZoneId,
86
+ ChangeBatch: {
87
+ Changes: records.map((record) => ({
88
+ Action: action,
89
+ ResourceRecordSet: record
90
+ }))
91
+ }
92
+ };
93
+ const { ChangeInfo } = await route53.send(new import_client_route_53.ChangeResourceRecordSetsCommand(changeRecordSetsInput));
94
+ const result = await (0, import_client_route_53.waitUntilResourceRecordSetsChanged)({ client: route53, maxWaitTime: 180 }, { Id: ChangeInfo?.Id });
95
+ if (result.state !== "SUCCESS") {
96
+ throw new Error(
97
+ `Record sets never changed for hosted zone ${hostedZoneId}: [${result.state}] ${result.reason ?? ""}`
98
+ );
99
+ }
100
+ return ChangeInfo?.Id;
101
+ };
102
+ var requestCertificate = async (acm, route53, requestId, properties) => {
103
+ const { HostedZoneId, DomainName, SubjectAlternativeNames, TransparencyLoggingEnabled } = properties;
104
+ console.log(`Requesting certificate for ${DomainName}`);
105
+ const requestCertificateInput = {
106
+ DomainName,
107
+ SubjectAlternativeNames,
108
+ IdempotencyToken: crypto.createHash("sha256").update(requestId).digest("hex").slice(0, 32),
109
+ ValidationMethod: "DNS",
110
+ Options: {
111
+ CertificateTransparencyLoggingPreference: TransparencyLoggingEnabled ? "ENABLED" : "DISABLED"
112
+ }
113
+ };
114
+ const { CertificateArn } = await acm.send(new import_client_acm.RequestCertificateCommand(requestCertificateInput));
115
+ console.log(`Certificate ${CertificateArn} requested`);
116
+ const validationMaxSeconds = 180;
117
+ const validationTimeoutError = `Domain validation options were not found in ${validationMaxSeconds} seconds`;
118
+ const validationRecords = await tryFor(validationMaxSeconds, validationTimeoutError, async () => {
119
+ const describeCertificateInput = {
120
+ CertificateArn
121
+ };
122
+ const { Certificate } = await acm.send(new import_client_acm.DescribeCertificateCommand(describeCertificateInput));
123
+ return parseDomainValidationRecords(Certificate);
124
+ });
125
+ console.log(`Upserting ${validationRecords.length} validation record(s) into hosted zone ${HostedZoneId}:`);
126
+ validationRecords.forEach(
127
+ (record) => console.log(`${record.Name} ${record.Type} ${record.ResourceRecords?.map((rr) => rr.Value).join(",")}`)
128
+ );
129
+ const changeId = await changeRecordSets(route53, "UPSERT", validationRecords, HostedZoneId);
130
+ console.log(`All validation records changed succesfully for change id ${changeId}`);
131
+ console.log(`Waiting for certificate ${CertificateArn} to validate`);
132
+ const result = await (0, import_client_acm.waitUntilCertificateValidated)({ client: acm, maxWaitTime: 300 }, { CertificateArn });
133
+ if (result.state !== "SUCCESS") {
134
+ throw new Error(`Certificate failed ${CertificateArn} to validate: [${result.state}] ${result.reason ?? ""}`);
135
+ }
136
+ console.log(`Certificate ${CertificateArn} successfully validated`);
137
+ return CertificateArn;
138
+ };
139
+ var deleteCertificate = async (acm, route53, certificateArn, hostedZoneId, cleanupValidationRecords) => {
140
+ console.log(`Waiting for certificate ${certificateArn} usage to drain before deletion`);
141
+ const waitUsageMaxSeconds = 600;
142
+ const waitUsageTimeoutError = `Certificate was still in use after ${waitUsageMaxSeconds} seconds`;
143
+ const certificate = await tryFor(waitUsageMaxSeconds, waitUsageTimeoutError, async () => {
144
+ const describeCertificateInput = {
145
+ CertificateArn: certificateArn
146
+ };
147
+ const { Certificate } = await acm.send(new import_client_acm.DescribeCertificateCommand(describeCertificateInput));
148
+ const inUseBy = Certificate?.InUseBy ?? [];
149
+ if (inUseBy.length > 0) {
150
+ return null;
151
+ }
152
+ return Certificate;
153
+ });
154
+ console.log("Certificate is unused and will be deleted");
155
+ const validationRecords = parseDomainValidationRecords(certificate);
156
+ if (validationRecords && cleanupValidationRecords) {
157
+ console.log(`Deleting ${validationRecords.length} validation record(s) from hosted zone ${hostedZoneId}`);
158
+ try {
159
+ const changeId = await changeRecordSets(route53, "DELETE", validationRecords, hostedZoneId);
160
+ console.log(`All validation records removed successfully for change id ${changeId}`);
161
+ } catch (error) {
162
+ if (error instanceof import_client_route_53.InvalidChangeBatch && error.message.includes("not found")) {
163
+ console.log(`All validation records have already been removed by some other certificate`);
164
+ } else {
165
+ throw error;
166
+ }
167
+ }
168
+ }
169
+ console.log(`Deleting certificate ${certificateArn}`);
170
+ const deleteCertificateInput = {
171
+ CertificateArn: certificateArn
172
+ };
173
+ await acm.send(new import_client_acm.DeleteCertificateCommand(deleteCertificateInput));
174
+ console.log(`Certificate ${certificateArn} successfully deleted`);
175
+ };
176
+ var addTags = async (acm, certificateArn, tags) => {
177
+ const tagList = Array.from(Object.entries(tags).map(([Key, Value]) => ({ Key, Value })));
178
+ const addTagsInput = {
179
+ CertificateArn: certificateArn,
180
+ Tags: tagList
181
+ };
182
+ console.log(`Adding ${tagList.length} tags to certificate ${certificateArn}`);
183
+ await acm.send(new import_client_acm.AddTagsToCertificateCommand(addTagsInput));
184
+ console.log(`All tags successfully added to certificate ${certificateArn}`);
185
+ };
186
+ var shouldRequestNew = (oldProperties, newProperties) => {
187
+ if (oldProperties.HostedZoneId !== newProperties.HostedZoneId)
188
+ return true;
189
+ if (oldProperties.DomainName !== newProperties.DomainName)
190
+ return true;
191
+ if (oldProperties.CertificateRegion !== newProperties.CertificateRegion)
192
+ return true;
193
+ if (!containsSame(oldProperties.SubjectAlternativeNames ?? [], newProperties.SubjectAlternativeNames ?? []))
194
+ return true;
195
+ if (oldProperties.CleanupValidationRecords !== newProperties.CleanupValidationRecords)
196
+ return true;
197
+ if (oldProperties.TransparencyLoggingEnabled !== newProperties.TransparencyLoggingEnabled)
198
+ return true;
199
+ if (oldProperties.RemovalPolicy !== newProperties.RemovalPolicy)
200
+ return true;
201
+ return false;
202
+ };
203
+ var assumeRole = (roleArn, externalId) => {
204
+ if (!roleArn) {
205
+ return void 0;
206
+ }
207
+ return async () => {
208
+ const sts = new import_client_sts.STSClient({ retryMode: "adaptive" });
209
+ const assumeRoleInput = {
210
+ RoleArn: roleArn,
211
+ RoleSessionName: "CertificateRequestor",
212
+ ExternalId: externalId
213
+ };
214
+ const { Credentials } = await sts.send(new import_client_sts.AssumeRoleCommand(assumeRoleInput));
215
+ return {
216
+ accessKeyId: Credentials?.AccessKeyId,
217
+ secretAccessKey: Credentials?.SecretAccessKey,
218
+ sessionToken: Credentials?.SessionToken,
219
+ expiration: Credentials?.Expiration
220
+ };
221
+ };
222
+ };
223
+ var handler = async (event) => {
224
+ const properties = parseProperties(event.ResourceProperties);
225
+ const acm = new import_client_acm.ACMClient({ region: properties.CertificateRegion, retryMode: "adaptive" });
226
+ const route53 = new import_client_route_53.Route53Client({
227
+ retryMode: "adaptive",
228
+ credentials: assumeRole(properties.ValidationRoleArn, properties.ValidationExternalId)
229
+ });
230
+ switch (event.RequestType) {
231
+ case "Create": {
232
+ const certificateArn = await requestCertificate(acm, route53, event.RequestId, properties);
233
+ if (properties.Tags && Object.entries(properties.Tags).length > 0) {
234
+ await addTags(acm, certificateArn, properties.Tags);
235
+ }
236
+ return {
237
+ PhysicalResourceId: certificateArn,
238
+ Data: {
239
+ Arn: certificateArn
240
+ }
241
+ };
242
+ }
243
+ case "Update": {
244
+ let certificateArn = event.PhysicalResourceId;
245
+ if (shouldRequestNew(parseProperties(event.OldResourceProperties), properties)) {
246
+ certificateArn = await requestCertificate(acm, route53, event.RequestId, properties);
247
+ }
248
+ if (properties.Tags && Object.entries(properties.Tags).length > 0) {
249
+ await addTags(acm, certificateArn, properties.Tags);
250
+ }
251
+ return {
252
+ PhysicalResourceId: certificateArn,
253
+ Data: {
254
+ Arn: certificateArn
255
+ }
256
+ };
257
+ }
258
+ case "Delete": {
259
+ const certificateArn = event.PhysicalResourceId;
260
+ if (properties.RemovalPolicy === "destroy") {
261
+ await deleteCertificate(
262
+ acm,
263
+ route53,
264
+ certificateArn,
265
+ properties.HostedZoneId,
266
+ properties.CleanupValidationRecords
267
+ );
268
+ }
269
+ return {
270
+ PhysicalResourceId: certificateArn,
271
+ Data: {
272
+ Arn: certificateArn
273
+ }
274
+ };
275
+ }
276
+ }
277
+ throw new Error(`Invalid request type`);
278
+ };
279
+ // Annotate the CommonJS export names for ESM import in node:
280
+ 0 && (module.exports = {
281
+ handler
282
+ });
283
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/certificate-requestor.lambda.ts"],
4
+ "sourcesContent": ["import * as crypto from 'crypto'\nimport {\n ACMClient,\n AddTagsToCertificateCommand,\n AddTagsToCertificateCommandInput,\n CertificateDetail,\n DeleteCertificateCommand,\n DeleteCertificateCommandInput,\n DescribeCertificateCommand,\n DescribeCertificateCommandInput,\n RequestCertificateCommand,\n RequestCertificateCommandInput,\n waitUntilCertificateValidated,\n} from '@aws-sdk/client-acm'\nimport {\n ChangeAction,\n ChangeResourceRecordSetsCommand,\n ChangeResourceRecordSetsCommandInput,\n InvalidChangeBatch,\n ResourceRecordSet,\n Route53Client,\n waitUntilResourceRecordSetsChanged,\n} from '@aws-sdk/client-route-53'\nimport { AssumeRoleCommand, AssumeRoleCommandInput, STSClient } from '@aws-sdk/client-sts'\nimport type { AwsCredentialIdentity, Provider } from '@aws-sdk/types'\nimport type { CloudFormationCustomResourceEvent } from 'aws-lambda'\n\nexport type Properties = {\n HostedZoneId: string\n DomainName: string\n SubjectAlternativeNames?: string[]\n CertificateRegion: string\n ValidationRoleArn?: string\n ValidationExternalId?: string\n CleanupValidationRecords: boolean\n TransparencyLoggingEnabled: boolean\n Tags?: Record<string, string>\n RemovalPolicy: string\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))\n\nconst containsSame = <T>(array1: T[], array2: T[]): boolean => {\n if (array1.length !== array2.length) return false\n return array1.every((v1) => array2.includes(v1))\n}\n\nconst tryFor = async <T>(maxSeconds: number, timeoutError: string, fn: () => Promise<T | null>): Promise<T> => {\n const startTime = Date.now()\n // eslint-disable-next-line no-constant-condition\n for (let i = 0; true; i++) {\n if (Date.now() > startTime + maxSeconds * 1000) {\n throw new Error(timeoutError)\n }\n const result = await fn()\n if (result !== null) {\n return result\n }\n const base = Math.pow(2, i)\n await sleep(Math.random() * base * 50 + base * 150)\n }\n}\n\nconst parseProperties = (properties: Record<string, any>): Properties => {\n // maybe should actually parse and not just assume\n return properties as unknown as Properties\n}\n\nconst parseDomainValidationRecords = (certificate: CertificateDetail): ResourceRecordSet[] | null => {\n const options = certificate.DomainValidationOptions ?? []\n console.log('options: ', options)\n if (options.length > 0 && options.every((opt) => opt.ResourceRecord?.Name)) {\n const uniqueRecords = [...new Map(options.map((opt) => [opt.ResourceRecord?.Name!, opt.ResourceRecord!])).values()]\n return uniqueRecords.map((record) => {\n return {\n Name: record.Name,\n Type: record.Type,\n TTL: 30,\n ResourceRecords: [\n {\n Value: record.Value,\n },\n ],\n }\n })\n }\n return null\n}\n\nconst changeRecordSets = async (\n route53: Route53Client,\n action: ChangeAction,\n records: ResourceRecordSet[],\n hostedZoneId: string\n): Promise<string> => {\n const changeRecordSetsInput: ChangeResourceRecordSetsCommandInput = {\n HostedZoneId: hostedZoneId,\n ChangeBatch: {\n Changes: records.map((record) => ({\n Action: action,\n ResourceRecordSet: record,\n })),\n },\n }\n const { ChangeInfo } = await route53.send(new ChangeResourceRecordSetsCommand(changeRecordSetsInput))\n const result = await waitUntilResourceRecordSetsChanged({ client: route53, maxWaitTime: 180 }, { Id: ChangeInfo?.Id })\n if (result.state !== 'SUCCESS') {\n throw new Error(\n `Record sets never changed for hosted zone ${hostedZoneId}: [${result.state}] ${result.reason ?? ''}`\n )\n }\n return ChangeInfo?.Id!\n}\n\nconst requestCertificate = async (\n acm: ACMClient,\n route53: Route53Client,\n requestId: string,\n properties: Properties\n): Promise<string> => {\n const { HostedZoneId, DomainName, SubjectAlternativeNames, TransparencyLoggingEnabled } = properties\n\n console.log(`Requesting certificate for ${DomainName}`)\n\n const requestCertificateInput: RequestCertificateCommandInput = {\n DomainName,\n SubjectAlternativeNames: SubjectAlternativeNames,\n IdempotencyToken: crypto.createHash('sha256').update(requestId).digest('hex').slice(0, 32),\n ValidationMethod: 'DNS',\n Options: {\n CertificateTransparencyLoggingPreference: TransparencyLoggingEnabled ? 'ENABLED' : 'DISABLED',\n },\n }\n const { CertificateArn } = await acm.send(new RequestCertificateCommand(requestCertificateInput))\n\n console.log(`Certificate ${CertificateArn} requested`)\n\n const validationMaxSeconds = 180\n const validationTimeoutError = `Domain validation options were not found in ${validationMaxSeconds} seconds`\n const validationRecords = await tryFor(validationMaxSeconds, validationTimeoutError, async () => {\n const describeCertificateInput: DescribeCertificateCommandInput = {\n CertificateArn,\n }\n const { Certificate } = await acm.send(new DescribeCertificateCommand(describeCertificateInput))\n return parseDomainValidationRecords(Certificate!)\n })\n\n console.log(`Upserting ${validationRecords.length} validation record(s) into hosted zone ${HostedZoneId}:`)\n validationRecords.forEach((record) =>\n console.log(`${record.Name} ${record.Type} ${record.ResourceRecords?.map((rr) => rr.Value).join(',')}`)\n )\n const changeId = await changeRecordSets(route53, 'UPSERT', validationRecords, HostedZoneId)\n console.log(`All validation records changed succesfully for change id ${changeId}`)\n\n console.log(`Waiting for certificate ${CertificateArn} to validate`)\n const result = await waitUntilCertificateValidated({ client: acm, maxWaitTime: 300 }, { CertificateArn })\n if (result.state !== 'SUCCESS') {\n throw new Error(`Certificate failed ${CertificateArn} to validate: [${result.state}] ${result.reason ?? ''}`)\n }\n console.log(`Certificate ${CertificateArn} successfully validated`)\n return CertificateArn!\n}\n\nconst deleteCertificate = async (\n acm: ACMClient,\n route53: Route53Client,\n certificateArn: string,\n hostedZoneId: string,\n cleanupValidationRecords: boolean\n): Promise<void> => {\n console.log(`Waiting for certificate ${certificateArn} usage to drain before deletion`)\n\n const waitUsageMaxSeconds = 600\n const waitUsageTimeoutError = `Certificate was still in use after ${waitUsageMaxSeconds} seconds`\n const certificate = await tryFor(waitUsageMaxSeconds, waitUsageTimeoutError, async () => {\n const describeCertificateInput: DescribeCertificateCommandInput = {\n CertificateArn: certificateArn,\n }\n const { Certificate } = await acm.send(new DescribeCertificateCommand(describeCertificateInput))\n const inUseBy = Certificate?.InUseBy ?? []\n if (inUseBy.length > 0) {\n return null\n }\n return Certificate!\n })\n console.log('Certificate is unused and will be deleted')\n\n const validationRecords = parseDomainValidationRecords(certificate)\n if (validationRecords && cleanupValidationRecords) {\n console.log(`Deleting ${validationRecords.length} validation record(s) from hosted zone ${hostedZoneId}`)\n try {\n const changeId = await changeRecordSets(route53, 'DELETE', validationRecords, hostedZoneId)\n console.log(`All validation records removed successfully for change id ${changeId}`)\n } catch (error) {\n if (error instanceof InvalidChangeBatch && error.message.includes('not found')) {\n // there's a deletion race condition where some other certificate has already deleted the records\n console.log(`All validation records have already been removed by some other certificate`)\n } else {\n throw error\n }\n }\n }\n\n console.log(`Deleting certificate ${certificateArn}`)\n const deleteCertificateInput: DeleteCertificateCommandInput = {\n CertificateArn: certificateArn,\n }\n await acm.send(new DeleteCertificateCommand(deleteCertificateInput))\n console.log(`Certificate ${certificateArn} successfully deleted`)\n}\n\nconst addTags = async (acm: ACMClient, certificateArn: string, tags: Record<string, string>) => {\n const tagList = Array.from(Object.entries(tags).map(([Key, Value]) => ({ Key, Value })))\n const addTagsInput: AddTagsToCertificateCommandInput = {\n CertificateArn: certificateArn,\n Tags: tagList,\n }\n\n console.log(`Adding ${tagList.length} tags to certificate ${certificateArn}`)\n await acm.send(new AddTagsToCertificateCommand(addTagsInput))\n console.log(`All tags successfully added to certificate ${certificateArn}`)\n}\n\nconst shouldRequestNew = (oldProperties: Properties, newProperties: Properties): boolean => {\n if (oldProperties.HostedZoneId !== newProperties.HostedZoneId) return true\n if (oldProperties.DomainName !== newProperties.DomainName) return true\n if (oldProperties.CertificateRegion !== newProperties.CertificateRegion) return true\n if (!containsSame(oldProperties.SubjectAlternativeNames ?? [], newProperties.SubjectAlternativeNames ?? []))\n return true\n if (oldProperties.CleanupValidationRecords !== newProperties.CleanupValidationRecords) return true\n if (oldProperties.TransparencyLoggingEnabled !== newProperties.TransparencyLoggingEnabled) return true\n if (oldProperties.RemovalPolicy !== newProperties.RemovalPolicy) return true\n return false\n}\n\nconst assumeRole = (\n roleArn: string | undefined,\n externalId: string | undefined\n): Provider<AwsCredentialIdentity> | undefined => {\n if (!roleArn) {\n return undefined\n }\n return async () => {\n const sts = new STSClient({ retryMode: 'adaptive' })\n const assumeRoleInput: AssumeRoleCommandInput = {\n RoleArn: roleArn,\n RoleSessionName: 'CertificateRequestor',\n ExternalId: externalId,\n }\n const { Credentials } = await sts.send(new AssumeRoleCommand(assumeRoleInput))\n return {\n accessKeyId: Credentials?.AccessKeyId!,\n secretAccessKey: Credentials?.SecretAccessKey!,\n sessionToken: Credentials?.SessionToken!,\n expiration: Credentials?.Expiration,\n }\n }\n}\n\nexport const handler = async (event: CloudFormationCustomResourceEvent) => {\n const properties = parseProperties(event.ResourceProperties)\n\n const acm = new ACMClient({ region: properties.CertificateRegion, retryMode: 'adaptive' })\n const route53 = new Route53Client({\n retryMode: 'adaptive',\n credentials: assumeRole(properties.ValidationRoleArn, properties.ValidationExternalId),\n })\n\n switch (event.RequestType) {\n case 'Create': {\n const certificateArn = await requestCertificate(acm, route53, event.RequestId, properties)\n if (properties.Tags && Object.entries(properties.Tags).length > 0) {\n await addTags(acm, certificateArn, properties.Tags)\n }\n return {\n PhysicalResourceId: certificateArn,\n Data: {\n Arn: certificateArn,\n },\n }\n }\n case 'Update': {\n let certificateArn = event.PhysicalResourceId\n if (shouldRequestNew(parseProperties(event.OldResourceProperties), properties)) {\n certificateArn = await requestCertificate(acm, route53, event.RequestId, properties)\n }\n if (properties.Tags && Object.entries(properties.Tags).length > 0) {\n await addTags(acm, certificateArn, properties.Tags)\n }\n return {\n PhysicalResourceId: certificateArn,\n Data: {\n Arn: certificateArn,\n },\n }\n }\n case 'Delete': {\n const certificateArn = event.PhysicalResourceId\n if (properties.RemovalPolicy === 'destroy') {\n await deleteCertificate(\n acm,\n route53,\n certificateArn,\n properties.HostedZoneId,\n properties.CleanupValidationRecords\n )\n }\n return {\n PhysicalResourceId: certificateArn,\n Data: {\n Arn: certificateArn,\n },\n }\n }\n }\n throw new Error(`Invalid request type`)\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,13 @@
1
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
2
+ import { Construct } from 'constructs';
3
+ /**
4
+ * Props for CertificateRequestorFunction
5
+ */
6
+ export interface CertificateRequestorFunctionProps extends lambda.FunctionOptions {
7
+ }
8
+ /**
9
+ * An AWS Lambda function which executes src/certificate-requestor.
10
+ */
11
+ export declare class CertificateRequestorFunction extends lambda.Function {
12
+ constructor(scope: Construct, id: string, props?: CertificateRequestorFunctionProps);
13
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CertificateRequestorFunction = void 0;
4
+ // ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen".
5
+ const path = require("path");
6
+ const lambda = require("aws-cdk-lib/aws-lambda");
7
+ /**
8
+ * An AWS Lambda function which executes src/certificate-requestor.
9
+ */
10
+ class CertificateRequestorFunction extends lambda.Function {
11
+ constructor(scope, id, props) {
12
+ super(scope, id, {
13
+ description: 'src/certificate-requestor.lambda.ts',
14
+ ...props,
15
+ runtime: new lambda.Runtime('nodejs18.x', lambda.RuntimeFamily.NODEJS),
16
+ handler: 'index.handler',
17
+ code: lambda.Code.fromAsset(path.join(__dirname, '../assets/certificate-requestor.lambda')),
18
+ });
19
+ this.addEnvironment('AWS_NODEJS_CONNECTION_REUSE_ENABLED', '1', { removeInEdge: true });
20
+ }
21
+ }
22
+ exports.CertificateRequestorFunction = CertificateRequestorFunction;
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydGlmaWNhdGUtcmVxdWVzdG9yLWZ1bmN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NlcnRpZmljYXRlLXJlcXVlc3Rvci1mdW5jdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2RUFBNkU7QUFDN0UsNkJBQTZCO0FBQzdCLGlEQUFpRDtBQVNqRDs7R0FFRztBQUNILE1BQWEsNEJBQTZCLFNBQVEsTUFBTSxDQUFDLFFBQVE7SUFDL0QsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUF5QztRQUNqRixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLFdBQVcsRUFBRSxxQ0FBcUM7WUFDbEQsR0FBRyxLQUFLO1lBQ1IsT0FBTyxFQUFFLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsTUFBTSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUM7WUFDdEUsT0FBTyxFQUFFLGVBQWU7WUFDeEIsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLHdDQUF3QyxDQUFDLENBQUM7U0FDNUYsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGNBQWMsQ0FBQyxxQ0FBcUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMxRixDQUFDO0NBQ0Y7QUFYRCxvRUFXQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIH5+IEdlbmVyYXRlZCBieSBwcm9qZW4uIFRvIG1vZGlmeSwgZWRpdCAucHJvamVucmMudHMgYW5kIHJ1biBcIm5weCBwcm9qZW5cIi5cbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcblxuLyoqXG4gKiBQcm9wcyBmb3IgQ2VydGlmaWNhdGVSZXF1ZXN0b3JGdW5jdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIENlcnRpZmljYXRlUmVxdWVzdG9yRnVuY3Rpb25Qcm9wcyBleHRlbmRzIGxhbWJkYS5GdW5jdGlvbk9wdGlvbnMge1xufVxuXG4vKipcbiAqIEFuIEFXUyBMYW1iZGEgZnVuY3Rpb24gd2hpY2ggZXhlY3V0ZXMgc3JjL2NlcnRpZmljYXRlLXJlcXVlc3Rvci5cbiAqL1xuZXhwb3J0IGNsYXNzIENlcnRpZmljYXRlUmVxdWVzdG9yRnVuY3Rpb24gZXh0ZW5kcyBsYW1iZGEuRnVuY3Rpb24ge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wcz86IENlcnRpZmljYXRlUmVxdWVzdG9yRnVuY3Rpb25Qcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge1xuICAgICAgZGVzY3JpcHRpb246ICdzcmMvY2VydGlmaWNhdGUtcmVxdWVzdG9yLmxhbWJkYS50cycsXG4gICAgICAuLi5wcm9wcyxcbiAgICAgIHJ1bnRpbWU6IG5ldyBsYW1iZGEuUnVudGltZSgnbm9kZWpzMTgueCcsIGxhbWJkYS5SdW50aW1lRmFtaWx5Lk5PREVKUyksXG4gICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQocGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL2Fzc2V0cy9jZXJ0aWZpY2F0ZS1yZXF1ZXN0b3IubGFtYmRhJykpLFxuICAgIH0pO1xuICAgIHRoaXMuYWRkRW52aXJvbm1lbnQoJ0FXU19OT0RFSlNfQ09OTkVDVElPTl9SRVVTRV9FTkFCTEVEJywgJzEnLCB7IHJlbW92ZUluRWRnZTogdHJ1ZSB9KTtcbiAgfVxufSJdfQ==