@trautonen/cdk-dns-validated-certificate 0.0.2

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.
@@ -0,0 +1,19 @@
1
+ import type { CloudFormationCustomResourceEvent } from 'aws-lambda';
2
+ export type Properties = {
3
+ HostedZoneId: string;
4
+ DomainName: string;
5
+ SubjectAlternativeNames?: string[];
6
+ CertificateRegion: string;
7
+ ValidationRoleArn?: string;
8
+ ValidationExternalId?: string;
9
+ CleanupValidationRecords: boolean;
10
+ TransparencyLoggingEnabled: boolean;
11
+ Tags?: Record<string, string>;
12
+ RemovalPolicy: string;
13
+ };
14
+ export declare const handler: (event: CloudFormationCustomResourceEvent) => Promise<{
15
+ PhysicalResourceId: string;
16
+ Data: {
17
+ Arn: string;
18
+ };
19
+ }>;
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handler = void 0;
4
+ const crypto = require("crypto");
5
+ const client_acm_1 = require("@aws-sdk/client-acm");
6
+ const client_route_53_1 = require("@aws-sdk/client-route-53");
7
+ const client_sts_1 = require("@aws-sdk/client-sts");
8
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
9
+ const containsSame = (array1, array2) => {
10
+ if (array1.length !== array2.length)
11
+ return false;
12
+ return array1.every((v1) => array2.includes(v1));
13
+ };
14
+ const tryFor = async (maxSeconds, timeoutError, fn) => {
15
+ const startTime = Date.now();
16
+ // eslint-disable-next-line no-constant-condition
17
+ for (let i = 0; true; i++) {
18
+ if (Date.now() > startTime + maxSeconds * 1000) {
19
+ throw new Error(timeoutError);
20
+ }
21
+ const result = await fn();
22
+ if (result !== null) {
23
+ return result;
24
+ }
25
+ const base = Math.pow(2, i);
26
+ await sleep(Math.random() * base * 50 + base * 150);
27
+ }
28
+ };
29
+ const parseProperties = (properties) => {
30
+ // maybe should actually parse and not just assume
31
+ return properties;
32
+ };
33
+ const parseDomainValidationRecords = (certificate) => {
34
+ const options = certificate.DomainValidationOptions ?? [];
35
+ console.log('options: ', options);
36
+ if (options.length > 0 && options.every((opt) => opt.ResourceRecord?.Name)) {
37
+ const uniqueRecords = [...new Map(options.map((opt) => [opt.ResourceRecord?.Name, opt.ResourceRecord])).values()];
38
+ return uniqueRecords.map((record) => {
39
+ return {
40
+ Name: record.Name,
41
+ Type: record.Type,
42
+ TTL: 30,
43
+ ResourceRecords: [
44
+ {
45
+ Value: record.Value,
46
+ },
47
+ ],
48
+ };
49
+ });
50
+ }
51
+ return null;
52
+ };
53
+ const changeRecordSets = async (route53, action, records, hostedZoneId) => {
54
+ const changeRecordSetsInput = {
55
+ HostedZoneId: hostedZoneId,
56
+ ChangeBatch: {
57
+ Changes: records.map((record) => ({
58
+ Action: action,
59
+ ResourceRecordSet: record,
60
+ })),
61
+ },
62
+ };
63
+ const { ChangeInfo } = await route53.send(new client_route_53_1.ChangeResourceRecordSetsCommand(changeRecordSetsInput));
64
+ const result = await (0, client_route_53_1.waitUntilResourceRecordSetsChanged)({ client: route53, maxWaitTime: 180 }, { Id: ChangeInfo?.Id });
65
+ if (result.state !== 'SUCCESS') {
66
+ throw new Error(`Record sets never changed for hosted zone ${hostedZoneId}: [${result.state}] ${result.reason ?? ''}`);
67
+ }
68
+ return ChangeInfo?.Id;
69
+ };
70
+ const requestCertificate = async (acm, route53, requestId, properties) => {
71
+ const { HostedZoneId, DomainName, SubjectAlternativeNames, TransparencyLoggingEnabled } = properties;
72
+ console.log(`Requesting certificate for ${DomainName}`);
73
+ const requestCertificateInput = {
74
+ DomainName,
75
+ SubjectAlternativeNames: SubjectAlternativeNames,
76
+ IdempotencyToken: crypto.createHash('sha256').update(requestId).digest('hex').slice(0, 32),
77
+ ValidationMethod: 'DNS',
78
+ Options: {
79
+ CertificateTransparencyLoggingPreference: TransparencyLoggingEnabled ? 'ENABLED' : 'DISABLED',
80
+ },
81
+ };
82
+ const { CertificateArn } = await acm.send(new client_acm_1.RequestCertificateCommand(requestCertificateInput));
83
+ console.log(`Certificate ${CertificateArn} requested`);
84
+ const validationMaxSeconds = 180;
85
+ const validationTimeoutError = `Domain validation options were not found in ${validationMaxSeconds} seconds`;
86
+ const validationRecords = await tryFor(validationMaxSeconds, validationTimeoutError, async () => {
87
+ const describeCertificateInput = {
88
+ CertificateArn,
89
+ };
90
+ const { Certificate } = await acm.send(new client_acm_1.DescribeCertificateCommand(describeCertificateInput));
91
+ return parseDomainValidationRecords(Certificate);
92
+ });
93
+ console.log(`Upserting ${validationRecords.length} validation record(s) into hosted zone ${HostedZoneId}:`);
94
+ validationRecords.forEach((record) => console.log(`${record.Name} ${record.Type} ${record.ResourceRecords?.map((rr) => rr.Value).join(',')}`));
95
+ const changeId = await changeRecordSets(route53, 'UPSERT', validationRecords, HostedZoneId);
96
+ console.log(`All validation records changed succesfully for change id ${changeId}`);
97
+ console.log(`Waiting for certificate ${CertificateArn} to validate`);
98
+ const result = await (0, client_acm_1.waitUntilCertificateValidated)({ client: acm, maxWaitTime: 300 }, { CertificateArn });
99
+ if (result.state !== 'SUCCESS') {
100
+ throw new Error(`Certificate failed ${CertificateArn} to validate: [${result.state}] ${result.reason ?? ''}`);
101
+ }
102
+ console.log(`Certificate ${CertificateArn} successfully validated`);
103
+ return CertificateArn;
104
+ };
105
+ const deleteCertificate = async (acm, route53, certificateArn, hostedZoneId, cleanupValidationRecords) => {
106
+ console.log(`Waiting for certificate ${certificateArn} usage to drain before deletion`);
107
+ const waitUsageMaxSeconds = 600;
108
+ const waitUsageTimeoutError = `Certificate was still in use after ${waitUsageMaxSeconds} seconds`;
109
+ const certificate = await tryFor(waitUsageMaxSeconds, waitUsageTimeoutError, async () => {
110
+ const describeCertificateInput = {
111
+ CertificateArn: certificateArn,
112
+ };
113
+ const { Certificate } = await acm.send(new client_acm_1.DescribeCertificateCommand(describeCertificateInput));
114
+ const inUseBy = Certificate?.InUseBy ?? [];
115
+ if (inUseBy.length > 0) {
116
+ return null;
117
+ }
118
+ return Certificate;
119
+ });
120
+ console.log('Certificate is unused and will be deleted');
121
+ const validationRecords = parseDomainValidationRecords(certificate);
122
+ if (validationRecords && cleanupValidationRecords) {
123
+ console.log(`Deleting ${validationRecords.length} validation record(s) from hosted zone ${hostedZoneId}`);
124
+ try {
125
+ const changeId = await changeRecordSets(route53, 'DELETE', validationRecords, hostedZoneId);
126
+ console.log(`All validation records removed successfully for change id ${changeId}`);
127
+ }
128
+ catch (error) {
129
+ if (error instanceof client_route_53_1.InvalidChangeBatch && error.message.includes('not found')) {
130
+ // there's a deletion race condition where some other certificate has already deleted the records
131
+ console.log(`All validation records have already been removed by some other certificate`);
132
+ }
133
+ else {
134
+ throw error;
135
+ }
136
+ }
137
+ }
138
+ console.log(`Deleting certificate ${certificateArn}`);
139
+ const deleteCertificateInput = {
140
+ CertificateArn: certificateArn,
141
+ };
142
+ await acm.send(new client_acm_1.DeleteCertificateCommand(deleteCertificateInput));
143
+ console.log(`Certificate ${certificateArn} successfully deleted`);
144
+ };
145
+ const addTags = async (acm, certificateArn, tags) => {
146
+ const tagList = Array.from(Object.entries(tags).map(([Key, Value]) => ({ Key, Value })));
147
+ const addTagsInput = {
148
+ CertificateArn: certificateArn,
149
+ Tags: tagList,
150
+ };
151
+ console.log(`Adding ${tagList.length} tags to certificate ${certificateArn}`);
152
+ await acm.send(new client_acm_1.AddTagsToCertificateCommand(addTagsInput));
153
+ console.log(`All tags successfully added to certificate ${certificateArn}`);
154
+ };
155
+ const shouldRequestNew = (oldProperties, newProperties) => {
156
+ if (oldProperties.HostedZoneId !== newProperties.HostedZoneId)
157
+ return true;
158
+ if (oldProperties.DomainName !== newProperties.DomainName)
159
+ return true;
160
+ if (oldProperties.CertificateRegion !== newProperties.CertificateRegion)
161
+ return true;
162
+ if (!containsSame(oldProperties.SubjectAlternativeNames ?? [], newProperties.SubjectAlternativeNames ?? []))
163
+ return true;
164
+ if (oldProperties.CleanupValidationRecords !== newProperties.CleanupValidationRecords)
165
+ return true;
166
+ if (oldProperties.TransparencyLoggingEnabled !== newProperties.TransparencyLoggingEnabled)
167
+ return true;
168
+ if (oldProperties.RemovalPolicy !== newProperties.RemovalPolicy)
169
+ return true;
170
+ return false;
171
+ };
172
+ const assumeRole = (roleArn, externalId) => {
173
+ if (!roleArn) {
174
+ return undefined;
175
+ }
176
+ return async () => {
177
+ const sts = new client_sts_1.STSClient({ retryMode: 'adaptive' });
178
+ const assumeRoleInput = {
179
+ RoleArn: roleArn,
180
+ RoleSessionName: 'CertificateRequestor',
181
+ ExternalId: externalId,
182
+ };
183
+ const { Credentials } = await sts.send(new client_sts_1.AssumeRoleCommand(assumeRoleInput));
184
+ return {
185
+ accessKeyId: Credentials?.AccessKeyId,
186
+ secretAccessKey: Credentials?.SecretAccessKey,
187
+ sessionToken: Credentials?.SessionToken,
188
+ expiration: Credentials?.Expiration,
189
+ };
190
+ };
191
+ };
192
+ const handler = async (event) => {
193
+ const properties = parseProperties(event.ResourceProperties);
194
+ const acm = new client_acm_1.ACMClient({ region: properties.CertificateRegion, retryMode: 'adaptive' });
195
+ const route53 = new client_route_53_1.Route53Client({
196
+ retryMode: 'adaptive',
197
+ credentials: assumeRole(properties.ValidationRoleArn, properties.ValidationExternalId),
198
+ });
199
+ switch (event.RequestType) {
200
+ case 'Create': {
201
+ const certificateArn = await requestCertificate(acm, route53, event.RequestId, properties);
202
+ if (properties.Tags && Object.entries(properties.Tags).length > 0) {
203
+ await addTags(acm, certificateArn, properties.Tags);
204
+ }
205
+ return {
206
+ PhysicalResourceId: certificateArn,
207
+ Data: {
208
+ Arn: certificateArn,
209
+ },
210
+ };
211
+ }
212
+ case 'Update': {
213
+ let certificateArn = event.PhysicalResourceId;
214
+ if (shouldRequestNew(parseProperties(event.OldResourceProperties), properties)) {
215
+ certificateArn = await requestCertificate(acm, route53, event.RequestId, properties);
216
+ }
217
+ if (properties.Tags && Object.entries(properties.Tags).length > 0) {
218
+ await addTags(acm, certificateArn, properties.Tags);
219
+ }
220
+ return {
221
+ PhysicalResourceId: certificateArn,
222
+ Data: {
223
+ Arn: certificateArn,
224
+ },
225
+ };
226
+ }
227
+ case 'Delete': {
228
+ const certificateArn = event.PhysicalResourceId;
229
+ if (properties.RemovalPolicy === 'destroy') {
230
+ await deleteCertificate(acm, route53, certificateArn, properties.HostedZoneId, properties.CleanupValidationRecords);
231
+ }
232
+ return {
233
+ PhysicalResourceId: certificateArn,
234
+ Data: {
235
+ Arn: certificateArn,
236
+ },
237
+ };
238
+ }
239
+ }
240
+ throw new Error(`Invalid request type`);
241
+ };
242
+ exports.handler = handler;
243
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sYW1iZGEvaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxpQ0FBZ0M7QUFDaEMsb0RBWTRCO0FBQzVCLDhEQVFpQztBQUNqQyxvREFBMEY7QUFpQjFGLE1BQU0sS0FBSyxHQUFHLENBQUMsRUFBVSxFQUFFLEVBQUUsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFBO0FBRS9FLE1BQU0sWUFBWSxHQUFHLENBQUksTUFBVyxFQUFFLE1BQVcsRUFBVyxFQUFFO0lBQzVELElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxNQUFNLENBQUMsTUFBTTtRQUFFLE9BQU8sS0FBSyxDQUFBO0lBQ2pELE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO0FBQ2xELENBQUMsQ0FBQTtBQUVELE1BQU0sTUFBTSxHQUFHLEtBQUssRUFBSyxVQUFrQixFQUFFLFlBQW9CLEVBQUUsRUFBMkIsRUFBYyxFQUFFO0lBQzVHLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQTtJQUM1QixpREFBaUQ7SUFDakQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ3pCLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLFNBQVMsR0FBRyxVQUFVLEdBQUcsSUFBSSxFQUFFO1lBQzlDLE1BQU0sSUFBSSxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUE7U0FDOUI7UUFDRCxNQUFNLE1BQU0sR0FBRyxNQUFNLEVBQUUsRUFBRSxDQUFBO1FBQ3pCLElBQUksTUFBTSxLQUFLLElBQUksRUFBRTtZQUNu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LGFBQWEsS0FBSyxTQUFTLEVBQUU7Z0JBQzFDLE1BQU0saUJBQWlCLENBQ3JCLEdBQUcsRUFDSCxPQUFPLEVBQ1AsY0FBYyxFQUNkLFVBQVUsQ0FBQyxZQUFZLEVBQ3ZCLFVBQVUsQ0FBQyx3QkFBd0IsQ0FDcEMsQ0FBQTthQUNGO1lBQ0QsT0FBTztnQkFDTCxrQkFBa0IsRUFBRSxjQUFjO2dCQUNsQyxJQUFJLEVBQUU7b0JBQ0osR0FBRyxFQUFFLGNBQWM7aUJBQ3BCO2FBQ0YsQ0FBQTtTQUNGO0tBQ0Y7SUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUE7QUFDekMsQ0FBQyxDQUFBO0FBekRZLFFBQUEsT0FBTyxXQXlEbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnY3J5cHRvJ1xuaW1wb3J0IHtcbiAgQUNNQ2xpZW50LFxuICBBZGRUYWdzVG9DZXJ0aWZpY2F0ZUNvbW1hbmQsXG4gIEFkZFRhZ3NUb0NlcnRpZmljYXRlQ29tbWFuZElucHV0LFxuICBDZXJ0aWZpY2F0ZURldGFpbCxcbiAgRGVsZXRlQ2VydGlmaWNhdGVDb21tYW5kLFxuICBEZWxldGVDZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCxcbiAgRGVzY3JpYmVDZXJ0aWZpY2F0ZUNvbW1hbmQsXG4gIERlc2NyaWJlQ2VydGlmaWNhdGVDb21tYW5kSW5wdXQsXG4gIFJlcXVlc3RDZXJ0aWZpY2F0ZUNvbW1hbmQsXG4gIFJlcXVlc3RDZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCxcbiAgd2FpdFVudGlsQ2VydGlmaWNhdGVWYWxpZGF0ZWQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1hY20nXG5pbXBvcnQge1xuICBDaGFuZ2VBY3Rpb24sXG4gIENoYW5nZVJlc291cmNlUmVjb3JkU2V0c0NvbW1hbmQsXG4gIENoYW5nZVJlc291cmNlUmVjb3JkU2V0c0NvbW1hbmRJbnB1dCxcbiAgSW52YWxpZENoYW5nZUJhdGNoLFxuICBSZXNvdXJjZVJlY29yZFNldCxcbiAgUm91dGU1M0NsaWVudCxcbiAgd2FpdFVudGlsUmVzb3VyY2VSZWNvcmRTZXRzQ2hhbmdlZCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXJvdXRlLTUzJ1xuaW1wb3J0IHsgQXNzdW1lUm9sZUNvbW1hbmQsIEFzc3VtZVJvbGVDb21tYW5kSW5wdXQsIFNUU0NsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zdHMnXG5pbXBvcnQgdHlwZSB7IEF3c0NyZWRlbnRpYWxJZGVudGl0eSwgUHJvdmlkZXIgfSBmcm9tICdAYXdzLXNkay90eXBlcydcbmltcG9ydCB0eXBlIHsgQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50IH0gZnJvbSAnYXdzLWxhbWJkYSdcblxuZXhwb3J0IHR5cGUgUHJvcGVydGllcyA9IHtcbiAgSG9zdGVkWm9uZUlkOiBzdHJpbmdcbiAgRG9tYWluTmFtZTogc3RyaW5nXG4gIFN1YmplY3RBbHRlcm5hdGl2ZU5hbWVzPzogc3RyaW5nW11cbiAgQ2VydGlmaWNhdGVSZWdpb246IHN0cmluZ1xuICBWYWxpZGF0aW9uUm9sZUFybj86IHN0cmluZ1xuICBWYWxpZGF0aW9uRXh0ZXJuYWxJZD86IHN0cmluZ1xuICBDbGVhbnVwVmFsaWRhdGlvblJlY29yZHM6IGJvb2xlYW5cbiAgVHJhbnNwYXJlbmN5TG9nZ2luZ0VuYWJsZWQ6IGJvb2xlYW5cbiAgVGFncz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cbiAgUmVtb3ZhbFBvbGljeTogc3RyaW5nXG59XG5cbmNvbnN0IHNsZWVwID0gKG1zOiBudW1iZXIpID0+IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSlcblxuY29uc3QgY29udGFpbnNTYW1lID0gPFQ+KGFycmF5MTogVFtdLCBhcnJheTI6IFRbXSk6IGJvb2xlYW4gPT4ge1xuICBpZiAoYXJyYXkxLmxlbmd0aCAhPT0gYXJyYXkyLmxlbmd0aCkgcmV0dXJuIGZhbHNlXG4gIHJldHVybiBhcnJheTEuZXZlcnkoKHYxKSA9PiBhcnJheTIuaW5jbHVkZXModjEpKVxufVxuXG5jb25zdCB0cnlGb3IgPSBhc3luYyA8VD4obWF4U2Vjb25kczogbnVtYmVyLCB0aW1lb3V0RXJyb3I6IHN0cmluZywgZm46ICgpID0+IFByb21pc2U8VCB8IG51bGw+KTogUHJvbWlzZTxUPiA9PiB7XG4gIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KClcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnN0YW50LWNvbmRpdGlvblxuICBmb3IgKGxldCBpID0gMDsgdHJ1ZTsgaSsrKSB7XG4gICAgaWYgKERhdGUubm93KCkgPiBzdGFydFRpbWUgKyBtYXhTZWNvbmRzICogMTAwMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKHRpbWVvdXRFcnJvcilcbiAgICB9XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZm4oKVxuICAgIGlmIChyZXN1bHQgIT09IG51bGwpIHtcbiAgICAgIHJldHVybiByZXN1bHRcbiAgICB9XG4gICAgY29uc3QgYmFzZSA9IE1hdGgucG93KDIsIGkpXG4gICAgYXdhaXQgc2xlZXAoTWF0aC5yYW5kb20oKSAqIGJhc2UgKiA1MCArIGJhc2UgKiAxNTApXG4gIH1cbn1cblxuY29uc3QgcGFyc2VQcm9wZXJ0aWVzID0gKHByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9wZXJ0aWVzID0+IHtcbiAgLy8gbWF5YmUgc2hvdWxkIGFjdHVhbGx5IHBhcnNlIGFuZCBub3QganVzdCBhc3N1bWVcbiAgcmV0dXJuIHByb3BlcnRpZXMgYXMgdW5rbm93biBhcyBQcm9wZXJ0aWVzXG59XG5cbmNvbnN0IHBhcnNlRG9tYWluVmFsaWRhdGlvblJlY29yZHMgPSAoY2VydGlmaWNhdGU6IENlcnRpZmljYXRlRGV0YWlsKTogUmVzb3VyY2VSZWNvcmRTZXRbXSB8IG51bGwgPT4ge1xuICBjb25zdCBvcHRpb25zID0gY2VydGlmaWNhdGUuRG9tYWluVmFsaWRhdGlvbk9wdGlvbnMgPz8gW11cbiAgY29uc29sZS5sb2coJ29wdGlvbnM6ICcsIG9wdGlvbnMpXG4gIGlmIChvcHRpb25zLmxlbmd0aCA+IDAgJiYgb3B0aW9ucy5ldmVyeSgob3B0KSA9PiBvcHQuUmVzb3VyY2VSZWNvcmQ/Lk5hbWUpKSB7XG4gICAgY29uc3QgdW5pcXVlUmVjb3JkcyA9IFsuLi5uZXcgTWFwKG9wdGlvbnMubWFwKChvcHQpID0+IFtvcHQuUmVzb3VyY2VSZWNvcmQ/Lk5hbWUhLCBvcHQuUmVzb3VyY2VSZWNvcmQhXSkpLnZhbHVlcygpXVxuICAgIHJldHVybiB1bmlxdWVSZWNvcmRzLm1hcCgocmVjb3JkKSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBOYW1lOiByZWNvcmQuTmFtZSxcbiAgICAgICAgVHlwZTogcmVjb3JkLlR5cGUsXG4gICAgICAgIFRUTDogMzAsXG4gICAgICAgIFJlc291cmNlUmVjb3JkczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIFZhbHVlOiByZWNvcmQuVmFsdWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cbiAgICB9KVxuICB9XG4gIHJldHVybiBudWxsXG59XG5cbmNvbnN0IGNoYW5nZVJlY29yZFNldHMgPSBhc3luYyAoXG4gIHJvdXRlNTM6IFJvdXRlNTNDbGllbnQsXG4gIGFjdGlvbjogQ2hhbmdlQWN0aW9uLFxuICByZWNvcmRzOiBSZXNvdXJjZVJlY29yZFNldFtdLFxuICBob3N0ZWRab25lSWQ6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcbiAgY29uc3QgY2hhbmdlUmVjb3JkU2V0c0lucHV0OiBDaGFuZ2VSZXNvdXJjZVJlY29yZFNldHNDb21tYW5kSW5wdXQgPSB7XG4gICAgSG9zdGVkWm9uZUlkOiBob3N0ZWRab25lSWQsXG4gICAgQ2hhbmdlQmF0Y2g6IHtcbiAgICAgIENoYW5nZXM6IHJlY29yZHMubWFwKChyZWNvcmQpID0+ICh7XG4gICAgICAgIEFjdGlvbjogYWN0aW9uLFxuICAgICAgICBSZXNvdXJjZVJlY29yZFNldDogcmVjb3JkLFxuICAgICAgfSkpLFxuICAgIH0sXG4gIH1cbiAgY29uc3QgeyBDaGFuZ2VJbmZvIH0gPSBhd2FpdCByb3V0ZTUzLnNlbmQobmV3IENoYW5nZVJlc291cmNlUmVjb3JkU2V0c0NvbW1hbmQoY2hhbmdlUmVjb3JkU2V0c0lucHV0KSlcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd2FpdFVudGlsUmVzb3VyY2VSZWNvcmRTZXRzQ2hhbmdlZCh7IGNsaWVudDogcm91dGU1MywgbWF4V2FpdFRpbWU6IDE4MCB9LCB7IElkOiBDaGFuZ2VJbmZvPy5JZCB9KVxuICBpZiAocmVzdWx0LnN0YXRlICE9PSAnU1VDQ0VTUycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgUmVjb3JkIHNldHMgbmV2ZXIgY2hhbmdlZCBmb3IgaG9zdGVkIHpvbmUgJHtob3N0ZWRab25lSWR9OiBbJHtyZXN1bHQuc3RhdGV9XSAke3Jlc3VsdC5yZWFzb24gPz8gJyd9YFxuICAgIClcbiAgfVxuICByZXR1cm4gQ2hhbmdlSW5mbz8uSWQhXG59XG5cbmNvbnN0IHJlcXVlc3RDZXJ0aWZpY2F0ZSA9IGFzeW5jIChcbiAgYWNtOiBBQ01DbGllbnQsXG4gIHJvdXRlNTM6IFJvdXRlNTNDbGllbnQsXG4gIHJlcXVlc3RJZDogc3RyaW5nLFxuICBwcm9wZXJ0aWVzOiBQcm9wZXJ0aWVzXG4pOiBQcm9taXNlPHN0cmluZz4gPT4ge1xuICBjb25zdCB7IEhvc3RlZFpvbmVJZCwgRG9tYWluTmFtZSwgU3ViamVjdEFsdGVybmF0aXZlTmFtZXMsIFRyYW5zcGFyZW5jeUxvZ2dpbmdFbmFibGVkIH0gPSBwcm9wZXJ0aWVzXG5cbiAgY29uc29sZS5sb2coYFJlcXVlc3RpbmcgY2VydGlmaWNhdGUgZm9yICR7RG9tYWluTmFtZX1gKVxuXG4gIGNvbnN0IHJlcXVlc3RDZXJ0aWZpY2F0ZUlucHV0OiBSZXF1ZXN0Q2VydGlmaWNhdGVDb21tYW5kSW5wdXQgPSB7XG4gICAgRG9tYWluTmFtZSxcbiAgICBTdWJqZWN0QWx0ZXJuYXRpdmVOYW1lczogU3ViamVjdEFsdGVybmF0aXZlTmFtZXMsXG4gICAgSWRlbXBvdGVuY3lUb2tlbjogY3J5cHRvLmNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShyZXF1ZXN0SWQpLmRpZ2VzdCgnaGV4Jykuc2xpY2UoMCwgMzIpLFxuICAgIFZhbGlkYXRpb25NZXRob2Q6ICdETlMnLFxuICAgIE9wdGlvbnM6IHtcbiAgICAgIENlcnRpZmljYXRlVHJhbnNwYXJlbmN5TG9nZ2luZ1ByZWZlcmVuY2U6IFRyYW5zcGFyZW5jeUxvZ2dpbmdFbmFibGVkID8gJ0VOQUJMRUQnIDogJ0RJU0FCTEVEJyxcbiAgICB9LFxuICB9XG4gIGNvbnN0IHsgQ2VydGlmaWNhdGVBcm4gfSA9IGF3YWl0IGFjbS5zZW5kKG5ldyBSZXF1ZXN0Q2VydGlmaWNhdGVDb21tYW5kKHJlcXVlc3RDZXJ0aWZpY2F0ZUlucHV0KSlcblxuICBjb25zb2xlLmxvZyhgQ2VydGlmaWNhdGUgJHtDZXJ0aWZpY2F0ZUFybn0gcmVxdWVzdGVkYClcblxuICBjb25zdCB2YWxpZGF0aW9uTWF4U2Vjb25kcyA9IDE4MFxuICBjb25zdCB2YWxpZGF0aW9uVGltZW91dEVycm9yID0gYERvbWFpbiB2YWxpZGF0aW9uIG9wdGlvbnMgd2VyZSBub3QgZm91bmQgaW4gJHt2YWxpZGF0aW9uTWF4U2Vjb25kc30gc2Vjb25kc2BcbiAgY29uc3QgdmFsaWRhdGlvblJlY29yZHMgPSBhd2FpdCB0cnlGb3IodmFsaWRhdGlvbk1heFNlY29uZHMsIHZhbGlkYXRpb25UaW1lb3V0RXJyb3IsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBkZXNjcmliZUNlcnRpZmljYXRlSW5wdXQ6IERlc2NyaWJlQ2VydGlmaWNhdGVDb21tYW5kSW5wdXQgPSB7XG4gICAgICBDZXJ0aWZpY2F0ZUFybixcbiAgICB9XG4gICAgY29uc3QgeyBDZXJ0aWZpY2F0ZSB9ID0gYXdhaXQgYWNtLnNlbmQobmV3IERlc2NyaWJlQ2VydGlmaWNhdGVDb21tYW5kKGRlc2NyaWJlQ2VydGlmaWNhdGVJbnB1dCkpXG4gICAgcmV0dXJuIHBhcnNlRG9tYWluVmFsaWRhdGlvblJlY29yZHMoQ2VydGlmaWNhdGUhKVxuICB9KVxuXG4gIGNvbnNvbGUubG9nKGBVcHNlcnRpbmcgJHt2YWxpZGF0aW9uUmVjb3Jkcy5sZW5ndGh9IHZhbGlkYXRpb24gcmVjb3JkKHMpIGludG8gaG9zdGVkIHpvbmUgJHtIb3N0ZWRab25lSWR9OmApXG4gIHZhbGlkYXRpb25SZWNvcmRzLmZvckVhY2goKHJlY29yZCkgPT5cbiAgICBjb25zb2xlLmxvZyhgJHtyZWNvcmQuTmFtZX0gJHtyZWNvcmQuVHlwZX0gJHtyZWNvcmQuUmVzb3VyY2VSZWNvcmRzPy5tYXAoKHJyKSA9PiByci5WYWx1ZSkuam9pbignLCcpfWApXG4gIClcbiAgY29uc3QgY2hhbmdlSWQgPSBhd2FpdCBjaGFuZ2VSZWNvcmRTZXRzKHJvdXRlNTMsICdVUFNFUlQnLCB2YWxpZGF0aW9uUmVjb3JkcywgSG9zdGVkWm9uZUlkKVxuICBjb25zb2xlLmxvZyhgQWxsIHZhbGlkYXRpb24gcmVjb3JkcyBjaGFuZ2VkIHN1Y2Nlc2Z1bGx5IGZvciBjaGFuZ2UgaWQgJHtjaGFuZ2VJZH1gKVxuXG4gIGNvbnNvbGUubG9nKGBXYWl0aW5nIGZvciBjZXJ0aWZpY2F0ZSAke0NlcnRpZmljYXRlQXJufSB0byB2YWxpZGF0ZWApXG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdhaXRVbnRpbENlcnRpZmljYXRlVmFsaWRhdGVkKHsgY2xpZW50OiBhY20sIG1heFdhaXRUaW1lOiAzMDAgfSwgeyBDZXJ0aWZpY2F0ZUFybiB9KVxuICBpZiAocmVzdWx0LnN0YXRlICE9PSAnU1VDQ0VTUycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYENlcnRpZmljYXRlIGZhaWxlZCAke0NlcnRpZmljYXRlQXJufSB0byB2YWxpZGF0ZTogWyR7cmVzdWx0LnN0YXRlfV0gJHtyZXN1bHQucmVhc29uID8/ICcnfWApXG4gIH1cbiAgY29uc29sZS5sb2coYENlcnRpZmljYXRlICR7Q2VydGlmaWNhdGVBcm59IHN1Y2Nlc3NmdWxseSB2YWxpZGF0ZWRgKVxuICByZXR1cm4gQ2VydGlmaWNhdGVBcm4hXG59XG5cbmNvbnN0IGRlbGV0ZUNlcnRpZmljYXRlID0gYXN5bmMgKFxuICBhY206IEFDTUNsaWVudCxcbiAgcm91dGU1MzogUm91dGU1M0NsaWVudCxcbiAgY2VydGlmaWNhdGVBcm46IHN0cmluZyxcbiAgaG9zdGVkWm9uZUlkOiBzdHJpbmcsXG4gIGNsZWFudXBWYWxpZGF0aW9uUmVjb3JkczogYm9vbGVhblxuKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGNvbnNvbGUubG9nKGBXYWl0aW5nIGZvciBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlQXJufSB1c2FnZSB0byBkcmFpbiBiZWZvcmUgZGVsZXRpb25gKVxuXG4gIGNvbnN0IHdhaXRVc2FnZU1heFNlY29uZHMgPSA2MDBcbiAgY29uc3Qgd2FpdFVzYWdlVGltZW91dEVycm9yID0gYENlcnRpZmljYXRlIHdhcyBzdGlsbCBpbiB1c2UgYWZ0ZXIgJHt3YWl0VXNhZ2VNYXhTZWNvbmRzfSBzZWNvbmRzYFxuICBjb25zdCBjZXJ0aWZpY2F0ZSA9IGF3YWl0IHRyeUZvcih3YWl0VXNhZ2VNYXhTZWNvbmRzLCB3YWl0VXNhZ2VUaW1lb3V0RXJyb3IsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBkZXNjcmliZUNlcnRpZmljYXRlSW5wdXQ6IERlc2NyaWJlQ2VydGlmaWNhdGVDb21tYW5kSW5wdXQgPSB7XG4gICAgICBDZXJ0aWZpY2F0ZUFybjogY2VydGlmaWNhdGVBcm4sXG4gICAgfVxuICAgIGNvbnN0IHsgQ2VydGlmaWNhdGUgfSA9IGF3YWl0IGFjbS5zZW5kKG5ldyBEZXNjcmliZUNlcnRpZmljYXRlQ29tbWFuZChkZXNjcmliZUNlcnRpZmljYXRlSW5wdXQpKVxuICAgIGNvbnN0IGluVXNlQnkgPSBDZXJ0aWZpY2F0ZT8uSW5Vc2VCeSA/PyBbXVxuICAgIGlmIChpblVzZUJ5Lmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuICAgIHJldHVybiBDZXJ0aWZpY2F0ZSFcbiAgfSlcbiAgY29uc29sZS5sb2coJ0NlcnRpZmljYXRlIGlzIHVudXNlZCBhbmQgd2lsbCBiZSBkZWxldGVkJylcblxuICBjb25zdCB2YWxpZGF0aW9uUmVjb3JkcyA9IHBhcnNlRG9tYWluVmFsaWRhdGlvblJlY29yZHMoY2VydGlmaWNhdGUpXG4gIGlmICh2YWxpZGF0aW9uUmVjb3JkcyAmJiBjbGVhbnVwVmFsaWRhdGlvblJlY29yZHMpIHtcbiAgICBjb25zb2xlLmxvZyhgRGVsZXRpbmcgJHt2YWxpZGF0aW9uUmVjb3Jkcy5sZW5ndGh9IHZhbGlkYXRpb24gcmVjb3JkKHMpIGZyb20gaG9zdGVkIHpvbmUgJHtob3N0ZWRab25lSWR9YClcbiAgICB0cnkge1xuICAgICAgY29uc3QgY2hhbmdlSWQgPSBhd2FpdCBjaGFuZ2VSZWNvcmRTZXRzKHJvdXRlNTMsICdERUxFVEUnLCB2YWxpZGF0aW9uUmVjb3JkcywgaG9zdGVkWm9uZUlkKVxuICAgICAgY29uc29sZS5sb2coYEFsbCB2YWxpZGF0aW9uIHJlY29yZHMgcmVtb3ZlZCBzdWNjZXNzZnVsbHkgZm9yIGNoYW5nZSBpZCAke2NoYW5nZUlkfWApXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEludmFsaWRDaGFuZ2VCYXRjaCAmJiBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKCdub3QgZm91bmQnKSkge1xuICAgICAgICAvLyB0aGVyZSdzIGEgZGVsZXRpb24gcmFjZSBjb25kaXRpb24gd2hlcmUgc29tZSBvdGhlciBjZXJ0aWZpY2F0ZSBoYXMgYWxyZWFkeSBkZWxldGVkIHRoZSByZWNvcmRzXG4gICAgICAgIGNvbnNvbGUubG9nKGBBbGwgdmFsaWRhdGlvbiByZWNvcmRzIGhhdmUgYWxyZWFkeSBiZWVuIHJlbW92ZWQgYnkgc29tZSBvdGhlciBjZXJ0aWZpY2F0ZWApXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnJvclxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnNvbGUubG9nKGBEZWxldGluZyBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlQXJufWApXG4gIGNvbnN0IGRlbGV0ZUNlcnRpZmljYXRlSW5wdXQ6IERlbGV0ZUNlcnRpZmljYXRlQ29tbWFuZElucHV0ID0ge1xuICAgIENlcnRpZmljYXRlQXJuOiBjZXJ0aWZpY2F0ZUFybixcbiAgfVxuICBhd2FpdCBhY20uc2VuZChuZXcgRGVsZXRlQ2VydGlmaWNhdGVDb21tYW5kKGRlbGV0ZUNlcnRpZmljYXRlSW5wdXQpKVxuICBjb25zb2xlLmxvZyhgQ2VydGlmaWNhdGUgJHtjZXJ0aWZpY2F0ZUFybn0gc3VjY2Vzc2Z1bGx5IGRlbGV0ZWRgKVxufVxuXG5jb25zdCBhZGRUYWdzID0gYXN5bmMgKGFjbTogQUNNQ2xpZW50LCBjZXJ0aWZpY2F0ZUFybjogc3RyaW5nLCB0YWdzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KSA9PiB7XG4gIGNvbnN0IHRhZ0xpc3QgPSBBcnJheS5mcm9tKE9iamVjdC5lbnRyaWVzKHRhZ3MpLm1hcCgoW0tleSwgVmFsdWVdKSA9PiAoeyBLZXksIFZhbHVlIH0pKSlcbiAgY29uc3QgYWRkVGFnc0lucHV0OiBBZGRUYWdzVG9DZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCA9IHtcbiAgICBDZXJ0aWZpY2F0ZUFybjogY2VydGlmaWNhdGVBcm4sXG4gICAgVGFnczogdGFnTGlzdCxcbiAgfVxuXG4gIGNvbnNvbGUubG9nKGBBZGRpbmcgJHt0YWdMaXN0Lmxlbmd0aH0gdGFncyB0byBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlQXJufWApXG4gIGF3YWl0IGFjbS5zZW5kKG5ldyBBZGRUYWdzVG9DZXJ0aWZpY2F0ZUNvbW1hbmQoYWRkVGFnc0lucHV0KSlcbiAgY29uc29sZS5sb2coYEFsbCB0YWdzIHN1Y2Nlc3NmdWxseSBhZGRlZCB0byBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlQXJufWApXG59XG5cbmNvbnN0IHNob3VsZFJlcXVlc3ROZXcgPSAob2xkUHJvcGVydGllczogUHJvcGVydGllcywgbmV3UHJvcGVydGllczogUHJvcGVydGllcyk6IGJvb2xlYW4gPT4ge1xuICBpZiAob2xkUHJvcGVydGllcy5Ib3N0ZWRab25lSWQgIT09IG5ld1Byb3BlcnRpZXMuSG9zdGVkWm9uZUlkKSByZXR1cm4gdHJ1ZVxuICBpZiAob2xkUHJvcGVydGllcy5Eb21haW5OYW1lICE9PSBuZXdQcm9wZXJ0aWVzLkRvbWFpbk5hbWUpIHJldHVybiB0cnVlXG4gIGlmIChvbGRQcm9wZXJ0aWVzLkNlcnRpZmljYXRlUmVnaW9uICE9PSBuZXdQcm9wZXJ0aWVzLkNlcnRpZmljYXRlUmVnaW9uKSByZXR1cm4gdHJ1ZVxuICBpZiAoIWNvbnRhaW5zU2FtZShvbGRQcm9wZXJ0aWVzLlN1YmplY3RBbHRlcm5hdGl2ZU5hbWVzID8/IFtdLCBuZXdQcm9wZXJ0aWVzLlN1YmplY3RBbHRlcm5hdGl2ZU5hbWVzID8/IFtdKSlcbiAgICByZXR1cm4gdHJ1ZVxuICBpZiAob2xkUHJvcGVydGllcy5DbGVhbnVwVmFsaWRhdGlvblJlY29yZHMgIT09IG5ld1Byb3BlcnRpZXMuQ2xlYW51cFZhbGlkYXRpb25SZWNvcmRzKSByZXR1cm4gdHJ1ZVxuICBpZiAob2xkUHJvcGVydGllcy5UcmFuc3BhcmVuY3lMb2dnaW5nRW5hYmxlZCAhPT0gbmV3UHJvcGVydGllcy5UcmFuc3BhcmVuY3lMb2dnaW5nRW5hYmxlZCkgcmV0dXJuIHRydWVcbiAgaWYgKG9sZFByb3BlcnRpZXMuUmVtb3ZhbFBvbGljeSAhPT0gbmV3UHJvcGVydGllcy5SZW1vdmFsUG9saWN5KSByZXR1cm4gdHJ1ZVxuICByZXR1cm4gZmFsc2Vcbn1cblxuY29uc3QgYXNzdW1lUm9sZSA9IChcbiAgcm9sZUFybjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBleHRlcm5hbElkOiBzdHJpbmcgfCB1bmRlZmluZWRcbik6IFByb3ZpZGVyPEF3c0NyZWRlbnRpYWxJZGVudGl0eT4gfCB1bmRlZmluZWQgPT4ge1xuICBpZiAoIXJvbGVBcm4pIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cbiAgcmV0dXJuIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzdHMgPSBuZXcgU1RTQ2xpZW50KHsgcmV0cnlNb2RlOiAnYWRhcHRpdmUnIH0pXG4gICAgY29uc3QgYXNzdW1lUm9sZUlucHV0OiBBc3N1bWVSb2xlQ29tbWFuZElucHV0ID0ge1xuICAgICAgUm9sZUFybjogcm9sZUFybixcbiAgICAgIFJvbGVTZXNzaW9uTmFtZTogJ0NlcnRpZmljYXRlUmVxdWVzdG9yJyxcbiAgICAgIEV4dGVybmFsSWQ6IGV4dGVybmFsSWQsXG4gICAgfVxuICAgIGNvbnN0IHsgQ3JlZGVudGlhbHMgfSA9IGF3YWl0IHN0cy5zZW5kKG5ldyBBc3N1bWVSb2xlQ29tbWFuZChhc3N1bWVSb2xlSW5wdXQpKVxuICAgIHJldHVybiB7XG4gICAgICBhY2Nlc3NLZXlJZDogQ3JlZGVudGlhbHM/LkFjY2Vzc0tleUlkISxcbiAgICAgIHNlY3JldEFjY2Vzc0tleTogQ3JlZGVudGlhbHM/LlNlY3JldEFjY2Vzc0tleSEsXG4gICAgICBzZXNzaW9uVG9rZW46IENyZWRlbnRpYWxzPy5TZXNzaW9uVG9rZW4hLFxuICAgICAgZXhwaXJhdGlvbjogQ3JlZGVudGlhbHM/LkV4cGlyYXRpb24sXG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBoYW5kbGVyID0gYXN5bmMgKGV2ZW50OiBDbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQpID0+IHtcbiAgY29uc3QgcHJvcGVydGllcyA9IHBhcnNlUHJvcGVydGllcyhldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpXG5cbiAgY29uc3QgYWNtID0gbmV3IEFDTUNsaWVudCh7IHJlZ2lvbjogcHJvcGVydGllcy5DZXJ0aWZpY2F0ZVJlZ2lvbiwgcmV0cnlNb2RlOiAnYWRhcHRpdmUnIH0pXG4gIGNvbnN0IHJvdXRlNTMgPSBuZXcgUm91dGU1M0NsaWVudCh7XG4gICAgcmV0cnlNb2RlOiAnYWRhcHRpdmUnLFxuICAgIGNyZWRlbnRpYWxzOiBhc3N1bWVSb2xlKHByb3BlcnRpZXMuVmFsaWRhdGlvblJvbGVBcm4sIHByb3BlcnRpZXMuVmFsaWRhdGlvbkV4dGVybmFsSWQpLFxuICB9KVxuXG4gIHN3aXRjaCAoZXZlbnQuUmVxdWVzdFR5cGUpIHtcbiAgICBjYXNlICdDcmVhdGUnOiB7XG4gICAgICBjb25zdCBjZXJ0aWZpY2F0ZUFybiA9IGF3YWl0IHJlcXVlc3RDZXJ0aWZpY2F0ZShhY20sIHJvdXRlNTMsIGV2ZW50LlJlcXVlc3RJZCwgcHJvcGVydGllcylcbiAgICAgIGlmIChwcm9wZXJ0aWVzLlRhZ3MgJiYgT2JqZWN0LmVudHJpZXMocHJvcGVydGllcy5UYWdzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IGFkZFRhZ3MoYWNtLCBjZXJ0aWZpY2F0ZUFybiwgcHJvcGVydGllcy5UYWdzKVxuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIEFybjogY2VydGlmaWNhdGVBcm4sXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgfVxuICAgIGNhc2UgJ1VwZGF0ZSc6IHtcbiAgICAgIGxldCBjZXJ0aWZpY2F0ZUFybiA9IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZFxuICAgICAgaWYgKHNob3VsZFJlcXVlc3ROZXcocGFyc2VQcm9wZXJ0aWVzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcyksIHByb3BlcnRpZXMpKSB7XG4gICAgICAgIGNlcnRpZmljYXRlQXJuID0gYXdhaXQgcmVxdWVzdENlcnRpZmljYXRlKGFjbSwgcm91dGU1MywgZXZlbnQuUmVxdWVzdElkLCBwcm9wZXJ0aWVzKVxuICAgICAgfVxuICAgICAgaWYgKHByb3BlcnRpZXMuVGFncyAmJiBPYmplY3QuZW50cmllcyhwcm9wZXJ0aWVzLlRhZ3MpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgYXdhaXQgYWRkVGFncyhhY20sIGNlcnRpZmljYXRlQXJuLCBwcm9wZXJ0aWVzLlRhZ3MpXG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IGNlcnRpZmljYXRlQXJuLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgQXJuOiBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgfSxcbiAgICAgIH1cbiAgICB9XG4gICAgY2FzZSAnRGVsZXRlJzoge1xuICAgICAgY29uc3QgY2VydGlmaWNhdGVBcm4gPSBldmVudC5QaHlzaWNhbFJlc291cmNlSWRcbiAgICAgIGlmIChwcm9wZXJ0aWVzLlJlbW92YWxQb2xpY3kgPT09ICdkZXN0cm95Jykge1xuICAgICAgICBhd2FpdCBkZWxldGVDZXJ0aWZpY2F0ZShcbiAgICAgICAgICBhY20sXG4gICAgICAgICAgcm91dGU1MyxcbiAgICAgICAgICBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgICBwcm9wZXJ0aWVzLkhvc3RlZFpvbmVJZCxcbiAgICAgICAgICBwcm9wZXJ0aWVzLkNsZWFudXBWYWxpZGF0aW9uUmVjb3Jkc1xuICAgICAgICApXG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IGNlcnRpZmljYXRlQXJuLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgQXJuOiBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgfSxcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHJlcXVlc3QgdHlwZWApXG59XG4iXX0=
package/package.json ADDED
@@ -0,0 +1,140 @@
1
+ {
2
+ "name": "@trautonen/cdk-dns-validated-certificate",
3
+ "description": "CDK certificate construct that supports cross-region and cross-account DNS validation",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "https://github.com/trautonen/cdk-dns-validated-certificate.git"
7
+ },
8
+ "scripts": {
9
+ "build": "npx projen build",
10
+ "bump": "npx projen bump",
11
+ "clobber": "npx projen clobber",
12
+ "compat": "npx projen compat",
13
+ "compile": "npx projen compile",
14
+ "default": "npx projen default",
15
+ "docgen": "npx projen docgen",
16
+ "eject": "npx projen eject",
17
+ "eslint": "npx projen eslint",
18
+ "package": "npx projen package",
19
+ "package-all": "npx projen package-all",
20
+ "package:js": "npx projen package:js",
21
+ "post-compile": "npx projen post-compile",
22
+ "post-upgrade": "npx projen post-upgrade",
23
+ "pre-compile": "npx projen pre-compile",
24
+ "release": "npx projen release",
25
+ "test": "npx projen test",
26
+ "test:watch": "npx projen test:watch",
27
+ "unbump": "npx projen unbump",
28
+ "upgrade": "npx projen upgrade",
29
+ "watch": "npx projen watch",
30
+ "projen": "npx projen"
31
+ },
32
+ "author": {
33
+ "name": "Tapio Rautonen",
34
+ "email": "trautonen@users.noreply.github.com",
35
+ "organization": false
36
+ },
37
+ "devDependencies": {
38
+ "@aws-sdk/client-acm": "^3.0.0",
39
+ "@aws-sdk/client-route-53": "^3.0.0",
40
+ "@aws-sdk/client-sts": "^3.0.0",
41
+ "@aws-sdk/types": "^3.0.0",
42
+ "@types/aws-lambda": "^8.10.117",
43
+ "@types/jest": "^29.5.2",
44
+ "@types/node": "^16",
45
+ "@typescript-eslint/eslint-plugin": "^5",
46
+ "@typescript-eslint/parser": "^5",
47
+ "aws-cdk-lib": "2.83.1",
48
+ "aws-lambda": "^1.0.7",
49
+ "constructs": "10.0.5",
50
+ "esbuild": "^0.18.2",
51
+ "eslint": "^8",
52
+ "eslint-config-prettier": "^8.8.0",
53
+ "eslint-import-resolver-node": "^0.3.7",
54
+ "eslint-import-resolver-typescript": "^3.5.5",
55
+ "eslint-plugin-import": "^2.27.5",
56
+ "eslint-plugin-prettier": "^4.2.1",
57
+ "jest": "^29.5.0",
58
+ "jest-junit": "^15",
59
+ "jsii": "~5.0.0",
60
+ "jsii-diff": "^1.83.0",
61
+ "jsii-docgen": "^8.0.44",
62
+ "jsii-pacmak": "^1.83.0",
63
+ "npm-check-updates": "^16",
64
+ "prettier": "^2.8.8",
65
+ "projen": "^0.71.87",
66
+ "standard-version": "^9",
67
+ "ts-jest": "^29.1.0",
68
+ "ts-node": "^10.9.1",
69
+ "typescript": "^5.1.3"
70
+ },
71
+ "peerDependencies": {
72
+ "aws-cdk-lib": "^2.83.1",
73
+ "constructs": "^10.0.5"
74
+ },
75
+ "keywords": [
76
+ "aws",
77
+ "cdk",
78
+ "certificate",
79
+ "cross-account",
80
+ "cross-region",
81
+ "dns"
82
+ ],
83
+ "main": "lib/index.js",
84
+ "license": "Apache-2.0",
85
+ "publishConfig": {
86
+ "access": "public"
87
+ },
88
+ "version": "0.0.2",
89
+ "jest": {
90
+ "testMatch": [
91
+ "<rootDir>/src/**/__tests__/**/*.ts?(x)",
92
+ "<rootDir>/(test|src)/**/*(*.)@(spec|test).ts?(x)"
93
+ ],
94
+ "clearMocks": true,
95
+ "collectCoverage": true,
96
+ "coverageReporters": [
97
+ "json",
98
+ "lcov",
99
+ "clover",
100
+ "cobertura",
101
+ "text"
102
+ ],
103
+ "coverageDirectory": "coverage",
104
+ "coveragePathIgnorePatterns": [
105
+ "/node_modules/"
106
+ ],
107
+ "testPathIgnorePatterns": [
108
+ "/node_modules/"
109
+ ],
110
+ "watchPathIgnorePatterns": [
111
+ "/node_modules/"
112
+ ],
113
+ "reporters": [
114
+ "default",
115
+ [
116
+ "jest-junit",
117
+ {
118
+ "outputDirectory": "test-reports"
119
+ }
120
+ ]
121
+ ],
122
+ "preset": "ts-jest",
123
+ "globals": {
124
+ "ts-jest": {
125
+ "tsconfig": "tsconfig.dev.json"
126
+ }
127
+ }
128
+ },
129
+ "types": "lib/index.d.ts",
130
+ "stability": "stable",
131
+ "jsii": {
132
+ "outdir": "dist",
133
+ "targets": {},
134
+ "tsc": {
135
+ "outDir": "lib",
136
+ "rootDir": "src"
137
+ }
138
+ },
139
+ "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
140
+ }