@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.
- package/.gitattributes +25 -0
- package/.jsii +3894 -0
- package/.prettierignore +1 -0
- package/.prettierrc.json +7 -0
- package/.projenrc.ts +49 -0
- package/API.md +560 -0
- package/LICENSE +202 -0
- package/README.md +40 -0
- package/lib/dns-validated-certificate.d.ts +161 -0
- package/lib/dns-validated-certificate.js +179 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +18 -0
- package/lib/lambda/handler.d.ts +19 -0
- package/lib/lambda/handler.js +243 -0
- package/package.json +140 -0
|
@@ -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
|
+
}
|