@trautonen/cdk-dns-validated-certificate 0.0.52 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +90 -73
- package/API.md +129 -65
- package/README.md +31 -4
- package/assets/certificate-requestor.lambda/index.js +116 -37
- package/assets/certificate-requestor.lambda/index.js.map +2 -2
- package/lib/certificate-requestor.lambda.d.ts +8 -4
- package/lib/certificate-requestor.lambda.js +75 -33
- package/lib/dns-validated-certificate.d.ts +73 -40
- package/lib/dns-validated-certificate.js +73 -37
- package/lib/utils.d.ts +4 -0
- package/lib/utils.js +33 -2
- package/package.json +2 -2
|
@@ -39,19 +39,54 @@ const changeRecordSets = async (route53, action, records, hostedZoneId) => {
|
|
|
39
39
|
})),
|
|
40
40
|
},
|
|
41
41
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
try {
|
|
43
|
+
const { ChangeInfo } = await route53.send(new client_route_53_1.ChangeResourceRecordSetsCommand(changeRecordSetsInput));
|
|
44
|
+
const changeId = ChangeInfo?.Id;
|
|
45
|
+
const result = await (0, client_route_53_1.waitUntilResourceRecordSetsChanged)({ client: route53, maxWaitTime: 180 }, { Id: changeId });
|
|
46
|
+
if (result.state !== 'SUCCESS') {
|
|
47
|
+
throw new Error(`Validation records never changed for hosted zone ${hostedZoneId}: [${result.state}] ${result.reason ?? ''}`);
|
|
48
|
+
}
|
|
49
|
+
const operation = action === 'CREATE' || action === 'UPSERT' ? 'changed' : 'deleted';
|
|
50
|
+
const change = (0, utils_1.cleanChangeId)(changeId);
|
|
51
|
+
console.log(`Validation records succesfully ${operation} for hosted zone ${hostedZoneId} with change id ${change}`);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (action === 'DELETE' && error instanceof client_route_53_1.InvalidChangeBatch && error.message.includes('not found')) {
|
|
55
|
+
// there's a deletion race condition where some other certificate has already deleted the records
|
|
56
|
+
console.log(`All validation records have already been removed by some other certificate`);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const getRecordsForZoneNames = (records, zoneNames, result) => {
|
|
64
|
+
const [zoneName, ...restZoneNames] = zoneNames;
|
|
65
|
+
if (!zoneName) {
|
|
66
|
+
return result ?? {};
|
|
67
|
+
}
|
|
68
|
+
const matchingRecords = [];
|
|
69
|
+
const unmatchingRecords = [];
|
|
70
|
+
for (const record of records) {
|
|
71
|
+
const normalizedRecordName = (0, utils_1.cleanDomainName)(record.Name);
|
|
72
|
+
if (normalizedRecordName.endsWith(zoneName)) {
|
|
73
|
+
matchingRecords.push(record);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
unmatchingRecords.push(record);
|
|
77
|
+
}
|
|
46
78
|
}
|
|
47
|
-
return
|
|
79
|
+
return getRecordsForZoneNames(unmatchingRecords, restZoneNames, {
|
|
80
|
+
...(result ?? {}),
|
|
81
|
+
[zoneName]: matchingRecords,
|
|
82
|
+
});
|
|
48
83
|
};
|
|
49
84
|
const requestCertificate = async (acm, route53, requestId, properties) => {
|
|
50
|
-
const {
|
|
85
|
+
const { DomainName, AlternativeDomainNames, TransparencyLoggingEnabled } = properties;
|
|
51
86
|
console.log(`Requesting certificate for ${DomainName}`);
|
|
52
87
|
const requestCertificateInput = {
|
|
53
88
|
DomainName,
|
|
54
|
-
SubjectAlternativeNames:
|
|
89
|
+
SubjectAlternativeNames: AlternativeDomainNames,
|
|
55
90
|
IdempotencyToken: crypto.createHash('sha256').update(requestId).digest('hex').slice(0, 32),
|
|
56
91
|
ValidationMethod: 'DNS',
|
|
57
92
|
Options: {
|
|
@@ -69,10 +104,17 @@ const requestCertificate = async (acm, route53, requestId, properties) => {
|
|
|
69
104
|
const { Certificate } = await acm.send(new client_acm_1.DescribeCertificateCommand(describeCertificateInput));
|
|
70
105
|
return parseDomainValidationRecords(Certificate);
|
|
71
106
|
});
|
|
72
|
-
|
|
107
|
+
const hostedZones = Object.values(properties.ValidationHostedZones);
|
|
108
|
+
const hostedZoneIds = hostedZones.map((zone) => zone.HostedZoneId);
|
|
109
|
+
console.log(`Upserting ${validationRecords.length} validation record(s) into hosted zone(s) ${hostedZoneIds.join(', ')}:`);
|
|
73
110
|
validationRecords.forEach((record) => console.log(`${record.Name} ${record.Type} ${record.ResourceRecords?.map((rr) => rr.Value).join(',')}`));
|
|
74
|
-
const
|
|
75
|
-
|
|
111
|
+
const recordsForZoneNames = getRecordsForZoneNames(validationRecords, (0, utils_1.orderBySignificance)(Object.keys(properties.ValidationHostedZones)));
|
|
112
|
+
for (const hostedZone of hostedZones) {
|
|
113
|
+
const records = recordsForZoneNames[hostedZone.DomainName];
|
|
114
|
+
if (records.length > 0) {
|
|
115
|
+
await changeRecordSets(route53(hostedZone.ValidationRoleArn, hostedZone.ValidationExternalId), 'UPSERT', records, hostedZone.HostedZoneId);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
76
118
|
console.log(`Waiting for certificate ${CertificateArn} to validate`);
|
|
77
119
|
const result = await (0, client_acm_1.waitUntilCertificateValidated)({ client: acm, maxWaitTime: 300 }, { CertificateArn });
|
|
78
120
|
if (result.state !== 'SUCCESS') {
|
|
@@ -81,7 +123,7 @@ const requestCertificate = async (acm, route53, requestId, properties) => {
|
|
|
81
123
|
console.log(`Certificate ${CertificateArn} successfully validated`);
|
|
82
124
|
return CertificateArn;
|
|
83
125
|
};
|
|
84
|
-
const deleteCertificate = async (acm, route53, certificateArn,
|
|
126
|
+
const deleteCertificate = async (acm, route53, certificateArn, properties) => {
|
|
85
127
|
console.log(`Waiting for certificate ${certificateArn} usage to drain before deletion`);
|
|
86
128
|
const waitUsageMaxSeconds = 600;
|
|
87
129
|
const waitUsageTimeoutError = `Certificate was still in use after ${waitUsageMaxSeconds} seconds`;
|
|
@@ -98,19 +140,15 @@ const deleteCertificate = async (acm, route53, certificateArn, hostedZoneId, cle
|
|
|
98
140
|
});
|
|
99
141
|
console.log('Certificate is unused and will be deleted');
|
|
100
142
|
const validationRecords = parseDomainValidationRecords(certificate);
|
|
101
|
-
if (validationRecords &&
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (
|
|
109
|
-
|
|
110
|
-
console.log(`All validation records have already been removed by some other certificate`);
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
throw error;
|
|
143
|
+
if (validationRecords && (0, utils_1.stringToBoolean)(properties.CleanupValidationRecords)) {
|
|
144
|
+
const hostedZones = Object.values(properties.ValidationHostedZones);
|
|
145
|
+
const hostedZoneIds = hostedZones.map((zone) => zone.HostedZoneId);
|
|
146
|
+
console.log(`Deleting ${validationRecords.length} validation record(s) from hosted zone(s) ${hostedZoneIds.join(', ')}`);
|
|
147
|
+
const recordsForZoneNames = getRecordsForZoneNames(validationRecords, (0, utils_1.orderBySignificance)(Object.keys(properties.ValidationHostedZones)));
|
|
148
|
+
for (const hostedZone of hostedZones) {
|
|
149
|
+
const records = recordsForZoneNames[hostedZone.DomainName];
|
|
150
|
+
if (records.length > 0) {
|
|
151
|
+
await changeRecordSets(route53(hostedZone.ValidationRoleArn, hostedZone.ValidationExternalId), 'DELETE', records, hostedZone.HostedZoneId);
|
|
114
152
|
}
|
|
115
153
|
}
|
|
116
154
|
}
|
|
@@ -132,13 +170,15 @@ const addTags = async (acm, certificateArn, tags) => {
|
|
|
132
170
|
console.log(`All tags successfully added to certificate ${certificateArn}`);
|
|
133
171
|
};
|
|
134
172
|
const shouldRequestNew = (oldProperties, newProperties) => {
|
|
135
|
-
|
|
173
|
+
const oldHostedZoneIds = Object.values(oldProperties.ValidationHostedZones ?? {}).map((zone) => zone.HostedZoneId);
|
|
174
|
+
const newHostedZoneIds = Object.values(newProperties.ValidationHostedZones ?? {}).map((zone) => zone.HostedZoneId);
|
|
175
|
+
if (!(0, utils_1.containsSame)(oldHostedZoneIds, newHostedZoneIds))
|
|
136
176
|
return true;
|
|
137
177
|
if (oldProperties.DomainName !== newProperties.DomainName)
|
|
138
178
|
return true;
|
|
139
|
-
if (oldProperties.
|
|
179
|
+
if (!(0, utils_1.containsSame)(oldProperties.AlternativeDomainNames ?? [], newProperties.AlternativeDomainNames ?? []))
|
|
140
180
|
return true;
|
|
141
|
-
if (
|
|
181
|
+
if (oldProperties.CertificateRegion !== newProperties.CertificateRegion)
|
|
142
182
|
return true;
|
|
143
183
|
if (oldProperties.CleanupValidationRecords !== newProperties.CleanupValidationRecords)
|
|
144
184
|
return true;
|
|
@@ -171,10 +211,12 @@ const assumeRole = (roleArn, externalId) => {
|
|
|
171
211
|
const handler = async (event) => {
|
|
172
212
|
const properties = parseProperties(event.ResourceProperties);
|
|
173
213
|
const acm = new client_acm_1.ACMClient({ region: properties.CertificateRegion, retryMode: 'adaptive' });
|
|
174
|
-
const route53 =
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
214
|
+
const route53 = (roleArn, externalId) => {
|
|
215
|
+
return new client_route_53_1.Route53Client({
|
|
216
|
+
retryMode: 'adaptive',
|
|
217
|
+
credentials: assumeRole(roleArn, externalId),
|
|
218
|
+
});
|
|
219
|
+
};
|
|
178
220
|
switch (event.RequestType) {
|
|
179
221
|
case 'Create': {
|
|
180
222
|
console.log(`Requesting new certificate:\n${(0, utils_1.objectToString)(properties)}`);
|
|
@@ -209,7 +251,7 @@ const handler = async (event) => {
|
|
|
209
251
|
const certificateArn = event.PhysicalResourceId;
|
|
210
252
|
if (properties.RemovalPolicy === 'destroy') {
|
|
211
253
|
console.log(`Deleting old certificate as per removal policy:\n${(0, utils_1.objectToString)(properties)}`);
|
|
212
|
-
await deleteCertificate(acm, route53, certificateArn, properties
|
|
254
|
+
await deleteCertificate(acm, route53, certificateArn, properties);
|
|
213
255
|
}
|
|
214
256
|
return {
|
|
215
257
|
PhysicalResourceId: certificateArn,
|
|
@@ -222,4 +264,4 @@ const handler = async (event) => {
|
|
|
222
264
|
throw new Error(`Invalid request type`);
|
|
223
265
|
};
|
|
224
266
|
exports.handler = handler;
|
|
225
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydGlmaWNhdGUtcmVxdWVzdG9yLmxhbWJkYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jZXJ0aWZpY2F0ZS1yZXF1ZXN0b3IubGFtYmRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGlDQUFnQztBQUNoQyxvREFZNEI7QUFDNUIsOERBUWlDO0FBQ2pDLG9EQUEwRjtBQUcxRixtQ0FBK0U7QUFlL0UsTUFBTSxlQUFlLEdBQUcsQ0FBQyxVQUErQixFQUFjLEVBQUU7SUFDdEUsa0RBQWtEO0lBQ2xELE9BQU8sVUFBbUMsQ0FBQTtBQUM1QyxDQUFDLENBQUE7QUFFRCxNQUFNLDRCQUE0QixHQUFHLENBQUMsV0FBOEIsRUFBOEIsRUFBRTtJQUNsRyxNQUFNLE9BQU8sR0FBRyxXQUFXLENBQUMsdUJBQXVCLElBQUksRUFBRSxDQUFBO0lBQ3pELElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsRUFBRTtRQUMxRSxNQUFNLGFBQWEsR0FBRyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsY0FBYyxFQUFFLElBQUssRUFBRSxHQUFHLENBQUMsY0FBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUE7UUFDbkgsT0FBTyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDbEMsT0FBTztnQkFDTCxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7Z0JBQ2pCLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtnQkFDakIsR0FBRyxFQUFFLEVBQUU7Z0JBQ1AsZUFBZSxFQUFFO29CQUNmO3dCQUNFLEtBQUssRUFBRSxNQUFNLENBQUMs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QUksQ0FBQyxDQUFBO2FBQ3BEO1lBQ0QsT0FBTztnQkFDTCxrQkFBa0IsRUFBRSxjQUFjO2dCQUNsQyxJQUFJLEVBQUU7b0JBQ0osR0FBRyxFQUFFLGNBQWM7aUJBQ3BCO2FBQ0YsQ0FBQTtTQUNGO1FBQ0QsS0FBSyxRQUFRLENBQUMsQ0FBQztZQUNiLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQTtZQUMvQyxJQUFJLFVBQVUsQ0FBQyxhQUFhLEtBQUssU0FBUyxFQUFFO2dCQUMxQyxPQUFPLENBQUMsR0FBRyxDQUFDLG9EQUFvRCxJQUFBLHNCQUFjLEVBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFBO2dCQUM3RixNQUFNLGlCQUFpQixDQUNyQixHQUFHLEVBQ0gsT0FBTyxFQUNQLGNBQWMsRUFDZCxVQUFVLENBQUMsWUFBWSxFQUN2QixJQUFBLHVCQUFlLEVBQUMsVUFBVSxDQUFDLHdCQUF3QixDQUFDLENBQ3JELENBQUE7YUFDRjtZQUNELE9BQU87Z0JBQ0wsa0JBQWtCLEVBQUUsY0FBYztnQkFDbEMsSUFBSSxFQUFFO29CQUNKLEdBQUcsRUFBRSxjQUFjO2lCQUNwQjthQUNGLENBQUE7U0FDRjtLQUNGO0lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFBO0FBQ3pDLENBQUMsQ0FBQTtBQTVEWSxRQUFBLE9BQU8sV0E0RG5CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gJ2NyeXB0bydcbmltcG9ydCB7XG4gIEFDTUNsaWVudCxcbiAgQWRkVGFnc1RvQ2VydGlmaWNhdGVDb21tYW5kLFxuICBBZGRUYWdzVG9DZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCxcbiAgQ2VydGlmaWNhdGVEZXRhaWwsXG4gIERlbGV0ZUNlcnRpZmljYXRlQ29tbWFuZCxcbiAgRGVsZXRlQ2VydGlmaWNhdGVDb21tYW5kSW5wdXQsXG4gIERlc2NyaWJlQ2VydGlmaWNhdGVDb21tYW5kLFxuICBEZXNjcmliZUNlcnRpZmljYXRlQ29tbWFuZElucHV0LFxuICBSZXF1ZXN0Q2VydGlmaWNhdGVDb21tYW5kLFxuICBSZXF1ZXN0Q2VydGlmaWNhdGVDb21tYW5kSW5wdXQsXG4gIHdhaXRVbnRpbENlcnRpZmljYXRlVmFsaWRhdGVkLFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtYWNtJ1xuaW1wb3J0IHtcbiAgQ2hhbmdlQWN0aW9uLFxuICBDaGFuZ2VSZXNvdXJjZVJlY29yZFNldHNDb21tYW5kLFxuICBDaGFuZ2VSZXNvdXJjZVJlY29yZFNldHNDb21tYW5kSW5wdXQsXG4gIEludmFsaWRDaGFuZ2VCYXRjaCxcbiAgUmVzb3VyY2VSZWNvcmRTZXQsXG4gIFJvdXRlNTNDbGllbnQsXG4gIHdhaXRVbnRpbFJlc291cmNlUmVjb3JkU2V0c0NoYW5nZWQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1yb3V0ZS01MydcbmltcG9ydCB7IEFzc3VtZVJvbGVDb21tYW5kLCBBc3N1bWVSb2xlQ29tbWFuZElucHV0LCBTVFNDbGllbnQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtc3RzJ1xuaW1wb3J0IHR5cGUgeyBBd3NDcmVkZW50aWFsSWRlbnRpdHksIFByb3ZpZGVyIH0gZnJvbSAnQGF3cy1zZGsvdHlwZXMnXG5pbXBvcnQgdHlwZSB7IENsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCB9IGZyb20gJ2F3cy1sYW1iZGEnXG5pbXBvcnQgeyBjb250YWluc1NhbWUsIG9iamVjdFRvU3RyaW5nLCBzdHJpbmdUb0Jvb2xlYW4sIHRyeUZvciB9IGZyb20gJy4vdXRpbHMnXG5cbmV4cG9ydCB0eXBlIFByb3BlcnRpZXMgPSB7XG4gIEhvc3RlZFpvbmVJZDogc3RyaW5nXG4gIERvbWFpbk5hbWU6IHN0cmluZ1xuICBTdWJqZWN0QWx0ZXJuYXRpdmVOYW1lcz86IHN0cmluZ1tdXG4gIENlcnRpZmljYXRlUmVnaW9uOiBzdHJpbmdcbiAgVmFsaWRhdGlvblJvbGVBcm4/OiBzdHJpbmdcbiAgVmFsaWRhdGlvbkV4dGVybmFsSWQ/OiBzdHJpbmdcbiAgQ2xlYW51cFZhbGlkYXRpb25SZWNvcmRzOiBzdHJpbmdcbiAgVHJhbnNwYXJlbmN5TG9nZ2luZ0VuYWJsZWQ6IHN0cmluZ1xuICBUYWdzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPlxuICBSZW1vdmFsUG9saWN5OiBzdHJpbmdcbn1cblxuY29uc3QgcGFyc2VQcm9wZXJ0aWVzID0gKHByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9wZXJ0aWVzID0+IHtcbiAgLy8gbWF5YmUgc2hvdWxkIGFjdHVhbGx5IHBhcnNlIGFuZCBub3QganVzdCBhc3N1bWVcbiAgcmV0dXJuIHByb3BlcnRpZXMgYXMgdW5rbm93biBhcyBQcm9wZXJ0aWVzXG59XG5cbmNvbnN0IHBhcnNlRG9tYWluVmFsaWRhdGlvblJlY29yZHMgPSAoY2VydGlmaWNhdGU6IENlcnRpZmljYXRlRGV0YWlsKTogUmVzb3VyY2VSZWNvcmRTZXRbXSB8IG51bGwgPT4ge1xuICBjb25zdCBvcHRpb25zID0gY2VydGlmaWNhdGUuRG9tYWluVmFsaWRhdGlvbk9wdGlvbnMgPz8gW11cbiAgaWYgKG9wdGlvbnMubGVuZ3RoID4gMCAmJiBvcHRpb25zLmV2ZXJ5KChvcHQpID0+IG9wdC5SZXNvdXJjZVJlY29yZD8uTmFtZSkpIHtcbiAgICBjb25zdCB1bmlxdWVSZWNvcmRzID0gWy4uLm5ldyBNYXAob3B0aW9ucy5tYXAoKG9wdCkgPT4gW29wdC5SZXNvdXJjZVJlY29yZD8uTmFtZSEsIG9wdC5SZXNvdXJjZVJlY29yZCFdKSkudmFsdWVzKCldXG4gICAgcmV0dXJuIHVuaXF1ZVJlY29yZHMubWFwKChyZWNvcmQpID0+IHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIE5hbWU6IHJlY29yZC5OYW1lLFxuICAgICAgICBUeXBlOiByZWNvcmQuVHlwZSxcbiAgICAgICAgVFRMOiAzMCxcbiAgICAgICAgUmVzb3VyY2VSZWNvcmRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgVmFsdWU6IHJlY29yZC5WYWx1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfVxuICAgIH0pXG4gIH1cbiAgcmV0dXJuIG51bGxcbn1cblxuY29uc3QgY2hhbmdlUmVjb3JkU2V0cyA9IGFzeW5jIChcbiAgcm91dGU1MzogUm91dGU1M0NsaWVudCxcbiAgYWN0aW9uOiBDaGFuZ2VBY3Rpb24sXG4gIHJlY29yZHM6IFJlc291cmNlUmVjb3JkU2V0W10sXG4gIGhvc3RlZFpvbmVJZDogc3RyaW5nXG4pOiBQcm9taXNlPHN0cmluZz4gPT4ge1xuICBjb25zdCBjaGFuZ2VSZWNvcmRTZXRzSW5wdXQ6IENoYW5nZVJlc291cmNlUmVjb3JkU2V0c0NvbW1hbmRJbnB1dCA9IHtcbiAgICBIb3N0ZWRab25lSWQ6IGhvc3RlZFpvbmVJZCxcbiAgICBDaGFuZ2VCYXRjaDoge1xuICAgICAgQ2hhbmdlczogcmVjb3Jkcy5tYXAoKHJlY29yZCkgPT4gKHtcbiAgICAgICAgQWN0aW9uOiBhY3Rpb24sXG4gICAgICAgIFJlc291cmNlUmVjb3JkU2V0OiByZWNvcmQsXG4gICAgICB9KSksXG4gICAgfSxcbiAgfVxuICBjb25zdCB7IENoYW5nZUluZm8gfSA9IGF3YWl0IHJvdXRlNTMuc2VuZChuZXcgQ2hhbmdlUmVzb3VyY2VSZWNvcmRTZXRzQ29tbWFuZChjaGFuZ2VSZWNvcmRTZXRzSW5wdXQpKVxuICBjb25zdCByZXN1bHQgPSBhd2FpdCB3YWl0VW50aWxSZXNvdXJjZVJlY29yZFNldHNDaGFuZ2VkKHsgY2xpZW50OiByb3V0ZTUzLCBtYXhXYWl0VGltZTogMTgwIH0sIHsgSWQ6IENoYW5nZUluZm8/LklkIH0pXG4gIGlmIChyZXN1bHQuc3RhdGUgIT09ICdTVUNDRVNTJykge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBSZWNvcmQgc2V0cyBuZXZlciBjaGFuZ2VkIGZvciBob3N0ZWQgem9uZSAke2hvc3RlZFpvbmVJZH06IFske3Jlc3VsdC5zdGF0ZX1dICR7cmVzdWx0LnJlYXNvbiA/PyAnJ31gXG4gICAgKVxuICB9XG4gIHJldHVybiBDaGFuZ2VJbmZvPy5JZCFcbn1cblxuY29uc3QgcmVxdWVzdENlcnRpZmljYXRlID0gYXN5bmMgKFxuICBhY206IEFDTUNsaWVudCxcbiAgcm91dGU1MzogUm91dGU1M0NsaWVudCxcbiAgcmVxdWVzdElkOiBzdHJpbmcsXG4gIHByb3BlcnRpZXM6IFByb3BlcnRpZXNcbik6IFByb21pc2U8c3RyaW5nPiA9PiB7XG4gIGNvbnN0IHsgSG9zdGVkWm9uZUlkLCBEb21haW5OYW1lLCBTdWJqZWN0QWx0ZXJuYXRpdmVOYW1lcywgVHJhbnNwYXJlbmN5TG9nZ2luZ0VuYWJsZWQgfSA9IHByb3BlcnRpZXNcblxuICBjb25zb2xlLmxvZyhgUmVxdWVzdGluZyBjZXJ0aWZpY2F0ZSBmb3IgJHtEb21haW5OYW1lfWApXG5cbiAgY29uc3QgcmVxdWVzdENlcnRpZmljYXRlSW5wdXQ6IFJlcXVlc3RDZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCA9IHtcbiAgICBEb21haW5OYW1lLFxuICAgIFN1YmplY3RBbHRlcm5hdGl2ZU5hbWVzOiBTdWJqZWN0QWx0ZXJuYXRpdmVOYW1lcyxcbiAgICBJZGVtcG90ZW5jeVRva2VuOiBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKHJlcXVlc3RJZCkuZGlnZXN0KCdoZXgnKS5zbGljZSgwLCAzMiksXG4gICAgVmFsaWRhdGlvbk1ldGhvZDogJ0ROUycsXG4gICAgT3B0aW9uczoge1xuICAgICAgQ2VydGlmaWNhdGVUcmFuc3BhcmVuY3lMb2dnaW5nUHJlZmVyZW5jZTogVHJhbnNwYXJlbmN5TG9nZ2luZ0VuYWJsZWQgPyAnRU5BQkxFRCcgOiAnRElTQUJMRUQnLFxuICAgIH0sXG4gIH1cbiAgY29uc3QgeyBDZXJ0aWZpY2F0ZUFybiB9ID0gYXdhaXQgYWNtLnNlbmQobmV3IFJlcXVlc3RDZXJ0aWZpY2F0ZUNvbW1hbmQocmVxdWVzdENlcnRpZmljYXRlSW5wdXQpKVxuXG4gIGNvbnNvbGUubG9nKGBDZXJ0aWZpY2F0ZSAke0NlcnRpZmljYXRlQXJufSByZXF1ZXN0ZWRgKVxuXG4gIGNvbnN0IHZhbGlkYXRpb25NYXhTZWNvbmRzID0gMTgwXG4gIGNvbnN0IHZhbGlkYXRpb25UaW1lb3V0RXJyb3IgPSBgRG9tYWluIHZhbGlkYXRpb24gb3B0aW9ucyB3ZXJlIG5vdCBmb3VuZCBpbiAke3ZhbGlkYXRpb25NYXhTZWNvbmRzfSBzZWNvbmRzYFxuICBjb25zdCB2YWxpZGF0aW9uUmVjb3JkcyA9IGF3YWl0IHRyeUZvcih2YWxpZGF0aW9uTWF4U2Vjb25kcywgdmFsaWRhdGlvblRpbWVvdXRFcnJvciwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGRlc2NyaWJlQ2VydGlmaWNhdGVJbnB1dDogRGVzY3JpYmVDZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCA9IHtcbiAgICAgIENlcnRpZmljYXRlQXJuLFxuICAgIH1cbiAgICBjb25zdCB7IENlcnRpZmljYXRlIH0gPSBhd2FpdCBhY20uc2VuZChuZXcgRGVzY3JpYmVDZXJ0aWZpY2F0ZUNvbW1hbmQoZGVzY3JpYmVDZXJ0aWZpY2F0ZUlucHV0KSlcbiAgICByZXR1cm4gcGFyc2VEb21haW5WYWxpZGF0aW9uUmVjb3JkcyhDZXJ0aWZpY2F0ZSEpXG4gIH0pXG5cbiAgY29uc29sZS5sb2coYFVwc2VydGluZyAke3ZhbGlkYXRpb25SZWNvcmRzLmxlbmd0aH0gdmFsaWRhdGlvbiByZWNvcmQocykgaW50byBob3N0ZWQgem9uZSAke0hvc3RlZFpvbmVJZH06YClcbiAgdmFsaWRhdGlvblJlY29yZHMuZm9yRWFjaCgocmVjb3JkKSA9PlxuICAgIGNvbnNvbGUubG9nKGAke3JlY29yZC5OYW1lfSAke3JlY29yZC5UeXBlfSAke3JlY29yZC5SZXNvdXJjZVJlY29yZHM/Lm1hcCgocnIpID0+IHJyLlZhbHVlKS5qb2luKCcsJyl9YClcbiAgKVxuICBjb25zdCBjaGFuZ2VJZCA9IGF3YWl0IGNoYW5nZVJlY29yZFNldHMocm91dGU1MywgJ1VQU0VSVCcsIHZhbGlkYXRpb25SZWNvcmRzLCBIb3N0ZWRab25lSWQpXG4gIGNvbnNvbGUubG9nKGBBbGwgdmFsaWRhdGlvbiByZWNvcmRzIGNoYW5nZWQgc3VjY2VzZnVsbHkgZm9yIGNoYW5nZSBpZCAke2NoYW5nZUlkLnJlcGxhY2UoJy9jaGFuZ2UvJywgJycpfWApXG5cbiAgY29uc29sZS5sb2coYFdhaXRpbmcgZm9yIGNlcnRpZmljYXRlICR7Q2VydGlmaWNhdGVBcm59IHRvIHZhbGlkYXRlYClcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd2FpdFVudGlsQ2VydGlmaWNhdGVWYWxpZGF0ZWQoeyBjbGllbnQ6IGFjbSwgbWF4V2FpdFRpbWU6IDMwMCB9LCB7IENlcnRpZmljYXRlQXJuIH0pXG4gIGlmIChyZXN1bHQuc3RhdGUgIT09ICdTVUNDRVNTJykge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ2VydGlmaWNhdGUgZmFpbGVkICR7Q2VydGlmaWNhdGVBcm59IHRvIHZhbGlkYXRlOiBbJHtyZXN1bHQuc3RhdGV9XSAke3Jlc3VsdC5yZWFzb24gPz8gJyd9YClcbiAgfVxuICBjb25zb2xlLmxvZyhgQ2VydGlmaWNhdGUgJHtDZXJ0aWZpY2F0ZUFybn0gc3VjY2Vzc2Z1bGx5IHZhbGlkYXRlZGApXG4gIHJldHVybiBDZXJ0aWZpY2F0ZUFybiFcbn1cblxuY29uc3QgZGVsZXRlQ2VydGlmaWNhdGUgPSBhc3luYyAoXG4gIGFjbTogQUNNQ2xpZW50LFxuICByb3V0ZTUzOiBSb3V0ZTUzQ2xpZW50LFxuICBjZXJ0aWZpY2F0ZUFybjogc3RyaW5nLFxuICBob3N0ZWRab25lSWQ6IHN0cmluZyxcbiAgY2xlYW51cFZhbGlkYXRpb25SZWNvcmRzOiBib29sZWFuXG4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgY29uc29sZS5sb2coYFdhaXRpbmcgZm9yIGNlcnRpZmljYXRlICR7Y2VydGlmaWNhdGVBcm59IHVzYWdlIHRvIGRyYWluIGJlZm9yZSBkZWxldGlvbmApXG5cbiAgY29uc3Qgd2FpdFVzYWdlTWF4U2Vjb25kcyA9IDYwMFxuICBjb25zdCB3YWl0VXNhZ2VUaW1lb3V0RXJyb3IgPSBgQ2VydGlmaWNhdGUgd2FzIHN0aWxsIGluIHVzZSBhZnRlciAke3dhaXRVc2FnZU1heFNlY29uZHN9IHNlY29uZHNgXG4gIGNvbnN0IGNlcnRpZmljYXRlID0gYXdhaXQgdHJ5Rm9yKHdhaXRVc2FnZU1heFNlY29uZHMsIHdhaXRVc2FnZVRpbWVvdXRFcnJvciwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGRlc2NyaWJlQ2VydGlmaWNhdGVJbnB1dDogRGVzY3JpYmVDZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCA9IHtcbiAgICAgIENlcnRpZmljYXRlQXJuOiBjZXJ0aWZpY2F0ZUFybixcbiAgICB9XG4gICAgY29uc3QgeyBDZXJ0aWZpY2F0ZSB9ID0gYXdhaXQgYWNtLnNlbmQobmV3IERlc2NyaWJlQ2VydGlmaWNhdGVDb21tYW5kKGRlc2NyaWJlQ2VydGlmaWNhdGVJbnB1dCkpXG4gICAgY29uc3QgaW5Vc2VCeSA9IENlcnRpZmljYXRlPy5JblVzZUJ5ID8/IFtdXG4gICAgaWYgKGluVXNlQnkubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIG51bGxcbiAgICB9XG4gICAgcmV0dXJuIENlcnRpZmljYXRlIVxuICB9KVxuICBjb25zb2xlLmxvZygnQ2VydGlmaWNhdGUgaXMgdW51c2VkIGFuZCB3aWxsIGJlIGRlbGV0ZWQnKVxuXG4gIGNvbnN0IHZhbGlkYXRpb25SZWNvcmRzID0gcGFyc2VEb21haW5WYWxpZGF0aW9uUmVjb3JkcyhjZXJ0aWZpY2F0ZSlcbiAgaWYgKHZhbGlkYXRpb25SZWNvcmRzICYmIGNsZWFudXBWYWxpZGF0aW9uUmVjb3Jkcykge1xuICAgIGNvbnNvbGUubG9nKGBEZWxldGluZyAke3ZhbGlkYXRpb25SZWNvcmRzLmxlbmd0aH0gdmFsaWRhdGlvbiByZWNvcmQocykgZnJvbSBob3N0ZWQgem9uZSAke2hvc3RlZFpvbmVJZH1gKVxuICAgIHRyeSB7XG4gICAgICBjb25zdCBjaGFuZ2VJZCA9IGF3YWl0IGNoYW5nZVJlY29yZFNldHMocm91dGU1MywgJ0RFTEVURScsIHZhbGlkYXRpb25SZWNvcmRzLCBob3N0ZWRab25lSWQpXG4gICAgICBjb25zb2xlLmxvZyhgQWxsIHZhbGlkYXRpb24gcmVjb3JkcyByZW1vdmVkIHN1Y2Nlc3NmdWxseSBmb3IgY2hhbmdlIGlkICR7Y2hhbmdlSWQucmVwbGFjZSgnL2NoYW5nZS8nLCAnJyl9YClcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgSW52YWxpZENoYW5nZUJhdGNoICYmIGVycm9yLm1lc3NhZ2UuaW5jbHVkZXMoJ25vdCBmb3VuZCcpKSB7XG4gICAgICAgIC8vIHRoZXJlJ3MgYSBkZWxldGlvbiByYWNlIGNvbmRpdGlvbiB3aGVyZSBzb21lIG90aGVyIGNlcnRpZmljYXRlIGhhcyBhbHJlYWR5IGRlbGV0ZWQgdGhlIHJlY29yZHNcbiAgICAgICAgY29uc29sZS5sb2coYEFsbCB2YWxpZGF0aW9uIHJlY29yZHMgaGF2ZSBhbHJlYWR5IGJlZW4gcmVtb3ZlZCBieSBzb21lIG90aGVyIGNlcnRpZmljYXRlYClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGVycm9yXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc29sZS5sb2coYERlbGV0aW5nIGNlcnRpZmljYXRlICR7Y2VydGlmaWNhdGVBcm59IGZyb20gQUNNYClcbiAgY29uc3QgZGVsZXRlQ2VydGlmaWNhdGVJbnB1dDogRGVsZXRlQ2VydGlmaWNhdGVDb21tYW5kSW5wdXQgPSB7XG4gICAgQ2VydGlmaWNhdGVBcm46IGNlcnRpZmljYXRlQXJuLFxuICB9XG4gIGF3YWl0IGFjbS5zZW5kKG5ldyBEZWxldGVDZXJ0aWZpY2F0ZUNvbW1hbmQoZGVsZXRlQ2VydGlmaWNhdGVJbnB1dCkpXG4gIGNvbnNvbGUubG9nKGBDZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlQXJufSBzdWNjZXNzZnVsbHkgZGVsZXRlZGApXG59XG5cbmNvbnN0IGFkZFRhZ3MgPSBhc3luYyAoYWNtOiBBQ01DbGllbnQsIGNlcnRpZmljYXRlQXJuOiBzdHJpbmcsIHRhZ3M6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pID0+IHtcbiAgY29uc3QgdGFnTGlzdCA9IEFycmF5LmZyb20oT2JqZWN0LmVudHJpZXModGFncykubWFwKChbS2V5LCBWYWx1ZV0pID0+ICh7IEtleSwgVmFsdWUgfSkpKVxuICBjb25zdCBhZGRUYWdzSW5wdXQ6IEFkZFRhZ3NUb0NlcnRpZmljYXRlQ29tbWFuZElucHV0ID0ge1xuICAgIENlcnRpZmljYXRlQXJuOiBjZXJ0aWZpY2F0ZUFybixcbiAgICBUYWdzOiB0YWdMaXN0LFxuICB9XG5cbiAgY29uc29sZS5sb2coYEFkZGluZyAke3RhZ0xpc3QubGVuZ3RofSB0YWdzIHRvIGNlcnRpZmljYXRlICR7Y2VydGlmaWNhdGVBcm59YClcbiAgYXdhaXQgYWNtLnNlbmQobmV3IEFkZFRhZ3NUb0NlcnRpZmljYXRlQ29tbWFuZChhZGRUYWdzSW5wdXQpKVxuICBjb25zb2xlLmxvZyhgQWxsIHRhZ3Mgc3VjY2Vzc2Z1bGx5IGFkZGVkIHRvIGNlcnRpZmljYXRlICR7Y2VydGlmaWNhdGVBcm59YClcbn1cblxuY29uc3Qgc2hvdWxkUmVxdWVzdE5ldyA9IChvbGRQcm9wZXJ0aWVzOiBQcm9wZXJ0aWVzLCBuZXdQcm9wZXJ0aWVzOiBQcm9wZXJ0aWVzKTogYm9vbGVhbiA9PiB7XG4gIGlmIChvbGRQcm9wZXJ0aWVzLkhvc3RlZFpvbmVJZCAhPT0gbmV3UHJvcGVydGllcy5Ib3N0ZWRab25lSWQpIHJldHVybiB0cnVlXG4gIGlmIChvbGRQcm9wZXJ0aWVzLkRvbWFpbk5hbWUgIT09IG5ld1Byb3BlcnRpZXMuRG9tYWluTmFtZSkgcmV0dXJuIHRydWVcbiAgaWYgKG9sZFByb3BlcnRpZXMuQ2VydGlmaWNhdGVSZWdpb24gIT09IG5ld1Byb3BlcnRpZXMuQ2VydGlmaWNhdGVSZWdpb24pIHJldHVybiB0cnVlXG4gIGlmICghY29udGFpbnNTYW1lKG9sZFByb3BlcnRpZXMuU3ViamVjdEFsdGVybmF0aXZlTmFtZXMgPz8gW10sIG5ld1Byb3BlcnRpZXMuU3ViamVjdEFsdGVybmF0aXZlTmFtZXMgPz8gW10pKVxuICAgIHJldHVybiB0cnVlXG4gIGlmIChvbGRQcm9wZXJ0aWVzLkNsZWFudXBWYWxpZGF0aW9uUmVjb3JkcyAhPT0gbmV3UHJvcGVydGllcy5DbGVhbnVwVmFsaWRhdGlvblJlY29yZHMpIHJldHVybiB0cnVlXG4gIGlmIChvbGRQcm9wZXJ0aWVzLlRyYW5zcGFyZW5jeUxvZ2dpbmdFbmFibGVkICE9PSBuZXdQcm9wZXJ0aWVzLlRyYW5zcGFyZW5jeUxvZ2dpbmdFbmFibGVkKSByZXR1cm4gdHJ1ZVxuICBpZiAob2xkUHJvcGVydGllcy5SZW1vdmFsUG9saWN5ICE9PSBuZXdQcm9wZXJ0aWVzLlJlbW92YWxQb2xpY3kpIHJldHVybiB0cnVlXG4gIHJldHVybiBmYWxzZVxufVxuXG5jb25zdCBhc3N1bWVSb2xlID0gKFxuICByb2xlQXJuOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIGV4dGVybmFsSWQ6IHN0cmluZyB8IHVuZGVmaW5lZFxuKTogUHJvdmlkZXI8QXdzQ3JlZGVudGlhbElkZW50aXR5PiB8IHVuZGVmaW5lZCA9PiB7XG4gIGlmICghcm9sZUFybikge1xuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfVxuICByZXR1cm4gYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHN0cyA9IG5ldyBTVFNDbGllbnQoeyByZXRyeU1vZGU6ICdhZGFwdGl2ZScgfSlcbiAgICBjb25zdCBhc3N1bWVSb2xlSW5wdXQ6IEFzc3VtZVJvbGVDb21tYW5kSW5wdXQgPSB7XG4gICAgICBSb2xlQXJuOiByb2xlQXJuLFxuICAgICAgUm9sZVNlc3Npb25OYW1lOiAnQ2VydGlmaWNhdGVSZXF1ZXN0b3InLFxuICAgICAgRXh0ZXJuYWxJZDogZXh0ZXJuYWxJZCxcbiAgICB9XG4gICAgY29uc3QgeyBDcmVkZW50aWFscyB9ID0gYXdhaXQgc3RzLnNlbmQobmV3IEFzc3VtZVJvbGVDb21tYW5kKGFzc3VtZVJvbGVJbnB1dCkpXG4gICAgcmV0dXJuIHtcbiAgICAgIGFjY2Vzc0tleUlkOiBDcmVkZW50aWFscz8uQWNjZXNzS2V5SWQhLFxuICAgICAgc2VjcmV0QWNjZXNzS2V5OiBDcmVkZW50aWFscz8uU2VjcmV0QWNjZXNzS2V5ISxcbiAgICAgIHNlc3Npb25Ub2tlbjogQ3JlZGVudGlhbHM/LlNlc3Npb25Ub2tlbiEsXG4gICAgICBleHBpcmF0aW9uOiBDcmVkZW50aWFscz8uRXhwaXJhdGlvbixcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGhhbmRsZXIgPSBhc3luYyAoZXZlbnQ6IENsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCkgPT4ge1xuICBjb25zdCBwcm9wZXJ0aWVzID0gcGFyc2VQcm9wZXJ0aWVzKGV2ZW50LlJlc291cmNlUHJvcGVydGllcylcblxuICBjb25zdCBhY20gPSBuZXcgQUNNQ2xpZW50KHsgcmVnaW9uOiBwcm9wZXJ0aWVzLkNlcnRpZmljYXRlUmVnaW9uLCByZXRyeU1vZGU6ICdhZGFwdGl2ZScgfSlcbiAgY29uc3Qgcm91dGU1MyA9IG5ldyBSb3V0ZTUzQ2xpZW50KHtcbiAgICByZXRyeU1vZGU6ICdhZGFwdGl2ZScsXG4gICAgY3JlZGVudGlhbHM6IGFzc3VtZVJvbGUocHJvcGVydGllcy5WYWxpZGF0aW9uUm9sZUFybiwgcHJvcGVydGllcy5WYWxpZGF0aW9uRXh0ZXJuYWxJZCksXG4gIH0pXG5cbiAgc3dpdGNoIChldmVudC5SZXF1ZXN0VHlwZSkge1xuICAgIGNhc2UgJ0NyZWF0ZSc6IHtcbiAgICAgIGNvbnNvbGUubG9nKGBSZXF1ZXN0aW5nIG5ldyBjZXJ0aWZpY2F0ZTpcXG4ke29iamVjdFRvU3RyaW5nKHByb3BlcnRpZXMpfWApXG4gICAgICBjb25zdCBjZXJ0aWZpY2F0ZUFybiA9IGF3YWl0IHJlcXVlc3RDZXJ0aWZpY2F0ZShhY20sIHJvdXRlNTMsIGV2ZW50LlJlcXVlc3RJZCwgcHJvcGVydGllcylcbiAgICAgIGlmIChwcm9wZXJ0aWVzLlRhZ3MgJiYgT2JqZWN0LmVudHJpZXMocHJvcGVydGllcy5UYWdzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IGFkZFRhZ3MoYWNtLCBjZXJ0aWZpY2F0ZUFybiwgcHJvcGVydGllcy5UYWdzKVxuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIEFybjogY2VydGlmaWNhdGVBcm4sXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgfVxuICAgIGNhc2UgJ1VwZGF0ZSc6IHtcbiAgICAgIGxldCBjZXJ0aWZpY2F0ZUFybiA9IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZFxuICAgICAgaWYgKHNob3VsZFJlcXVlc3ROZXcocGFyc2VQcm9wZXJ0aWVzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcyksIHByb3BlcnRpZXMpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBSZXF1ZXN0aW5nIG5ldyBjZXJ0aWZpY2F0ZSBkdWUgdG8gY2hhbmdlIG9mIHByb3BlcnRpZXM6XFxuJHtvYmplY3RUb1N0cmluZyhwcm9wZXJ0aWVzKX1gKVxuICAgICAgICBjZXJ0aWZpY2F0ZUFybiA9IGF3YWl0IHJlcXVlc3RDZXJ0aWZpY2F0ZShhY20sIHJvdXRlNTMsIGV2ZW50LlJlcXVlc3RJZCwgcHJvcGVydGllcylcbiAgICAgIH1cbiAgICAgIGlmIChwcm9wZXJ0aWVzLlRhZ3MgJiYgT2JqZWN0LmVudHJpZXMocHJvcGVydGllcy5UYWdzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IGFkZFRhZ3MoYWNtLCBjZXJ0aWZpY2F0ZUFybiwgcHJvcGVydGllcy5UYWdzKVxuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIEFybjogY2VydGlmaWNhdGVBcm4sXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgfVxuICAgIGNhc2UgJ0RlbGV0ZSc6IHtcbiAgICAgIGNvbnN0IGNlcnRpZmljYXRlQXJuID0gZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkXG4gICAgICBpZiAocHJvcGVydGllcy5SZW1vdmFsUG9saWN5ID09PSAnZGVzdHJveScpIHtcbiAgICAgICAgY29uc29sZS5sb2coYERlbGV0aW5nIG9sZCBjZXJ0aWZpY2F0ZSBhcyBwZXIgcmVtb3ZhbCBwb2xpY3k6XFxuJHtvYmplY3RUb1N0cmluZyhwcm9wZXJ0aWVzKX1gKVxuICAgICAgICBhd2FpdCBkZWxldGVDZXJ0aWZpY2F0ZShcbiAgICAgICAgICBhY20sXG4gICAgICAgICAgcm91dGU1MyxcbiAgICAgICAgICBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgICBwcm9wZXJ0aWVzLkhvc3RlZFpvbmVJZCxcbiAgICAgICAgICBzdHJpbmdUb0Jvb2xlYW4ocHJvcGVydGllcy5DbGVhbnVwVmFsaWRhdGlvblJlY29yZHMpXG4gICAgICAgIClcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogY2VydGlmaWNhdGVBcm4sXG4gICAgICAgIERhdGE6IHtcbiAgICAgICAgICBBcm46IGNlcnRpZmljYXRlQXJuLFxuICAgICAgICB9LFxuICAgICAgfVxuICAgIH1cbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcmVxdWVzdCB0eXBlYClcbn1cbiJdfQ==
|
|
267
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydGlmaWNhdGUtcmVxdWVzdG9yLmxhbWJkYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jZXJ0aWZpY2F0ZS1yZXF1ZXN0b3IubGFtYmRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGlDQUFnQztBQUNoQyxvREFZNEI7QUFDNUIsOERBUWlDO0FBQ2pDLG9EQUEwRjtBQUcxRixtQ0FRZ0I7QUFzQmhCLE1BQU0sZUFBZSxHQUFHLENBQUMsVUFBK0IsRUFBYyxFQUFFO0lBQ3RFLGtEQUFrRDtJQUNsRCxPQUFPLFVBQW1DLENBQUE7QUFDNUMsQ0FBQyxDQUFBO0FBRUQsTUFBTSw0QkFBNEIsR0FBRyxDQUFDLFdBQThCLEVBQThCLEVBQUU7SUFDbEcsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLHVCQUF1QixJQUFJLEVBQUUsQ0FBQTtJQUN6RCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLEVBQUU7UUFDMUUsTUFBTSxhQUFhLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxJQUFLLEVBQUUsR0FBRyxDQUFDLGNBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBQ25ILE9BQU8sYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ2xDLE9BQU87Z0JBQ0wsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJO2dCQUNqQixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7Z0JBQ2pCLEdBQUcsRUFBRSxFQUFFO2dCQUNQLGVBQWUsRUFBRTtvQkFDZjt3QkFDRSxLQUFLLEVBQUUsTUFBTSxDQUFD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QkFDckcsY0FBYyxHQUFHLE1BQU0sa0JBQWtCLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxDQUFBO2FBQ3JGO1lBQ0QsSUFBSSxVQUFVLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ2pFLE1BQU0sT0FBTyxDQUFDLEdBQUcsRUFBRSxjQUFjLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFBO2FBQ3BEO1lBQ0QsT0FBTztnQkFDTCxrQkFBa0IsRUFBRSxjQUFjO2dCQUNsQyxJQUFJLEVBQUU7b0JBQ0osR0FBRyxFQUFFLGNBQWM7aUJBQ3BCO2FBQ0YsQ0FBQTtTQUNGO1FBQ0QsS0FBSyxRQUFRLENBQUMsQ0FBQztZQUNiLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQTtZQUMvQyxJQUFJLFVBQVUsQ0FBQyxhQUFhLEtBQUssU0FBUyxFQUFFO2dCQUMxQyxPQUFPLENBQUMsR0FBRyxDQUFDLG9EQUFvRCxJQUFBLHNCQUFjLEVBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFBO2dCQUM3RixNQUFNLGlCQUFpQixDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLFVBQVUsQ0FBQyxDQUFBO2FBQ2xFO1lBQ0QsT0FBTztnQkFDTCxrQkFBa0IsRUFBRSxjQUFjO2dCQUNsQyxJQUFJLEVBQUU7b0JBQ0osR0FBRyxFQUFFLGNBQWM7aUJBQ3BCO2FBQ0YsQ0FBQTtTQUNGO0tBQ0Y7SUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUE7QUFDekMsQ0FBQyxDQUFBO0FBeERZLFFBQUEsT0FBTyxXQXdEbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnY3J5cHRvJ1xuaW1wb3J0IHtcbiAgQUNNQ2xpZW50LFxuICBBZGRUYWdzVG9DZXJ0aWZpY2F0ZUNvbW1hbmQsXG4gIEFkZFRhZ3NUb0NlcnRpZmljYXRlQ29tbWFuZElucHV0LFxuICBDZXJ0aWZpY2F0ZURldGFpbCxcbiAgRGVsZXRlQ2VydGlmaWNhdGVDb21tYW5kLFxuICBEZWxldGVDZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCxcbiAgRGVzY3JpYmVDZXJ0aWZpY2F0ZUNvbW1hbmQsXG4gIERlc2NyaWJlQ2VydGlmaWNhdGVDb21tYW5kSW5wdXQsXG4gIFJlcXVlc3RDZXJ0aWZpY2F0ZUNvbW1hbmQsXG4gIFJlcXVlc3RDZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCxcbiAgd2FpdFVudGlsQ2VydGlmaWNhdGVWYWxpZGF0ZWQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1hY20nXG5pbXBvcnQge1xuICBDaGFuZ2VBY3Rpb24sXG4gIENoYW5nZVJlc291cmNlUmVjb3JkU2V0c0NvbW1hbmQsXG4gIENoYW5nZVJlc291cmNlUmVjb3JkU2V0c0NvbW1hbmRJbnB1dCxcbiAgSW52YWxpZENoYW5nZUJhdGNoLFxuICBSZXNvdXJjZVJlY29yZFNldCxcbiAgUm91dGU1M0NsaWVudCxcbiAgd2FpdFVudGlsUmVzb3VyY2VSZWNvcmRTZXRzQ2hhbmdlZCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXJvdXRlLTUzJ1xuaW1wb3J0IHsgQXNzdW1lUm9sZUNvbW1hbmQsIEFzc3VtZVJvbGVDb21tYW5kSW5wdXQsIFNUU0NsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zdHMnXG5pbXBvcnQgdHlwZSB7IEF3c0NyZWRlbnRpYWxJZGVudGl0eSwgUHJvdmlkZXIgfSBmcm9tICdAYXdzLXNkay90eXBlcydcbmltcG9ydCB0eXBlIHsgQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50IH0gZnJvbSAnYXdzLWxhbWJkYSdcbmltcG9ydCB7XG4gIGNsZWFuQ2hhbmdlSWQsXG4gIGNsZWFuRG9tYWluTmFtZSxcbiAgY29udGFpbnNTYW1lLFxuICBvYmplY3RUb1N0cmluZyxcbiAgb3JkZXJCeVNpZ25pZmljYW5jZSxcbiAgc3RyaW5nVG9Cb29sZWFuLFxuICB0cnlGb3IsXG59IGZyb20gJy4vdXRpbHMnXG5cbmV4cG9ydCB0eXBlIFZhbGlkYXRpb25Ib3N0ZWRab25lUHJvcGVydGllcyA9IHtcbiAgRG9tYWluTmFtZTogc3RyaW5nXG4gIEhvc3RlZFpvbmVJZDogc3RyaW5nXG4gIFZhbGlkYXRpb25Sb2xlQXJuPzogc3RyaW5nXG4gIFZhbGlkYXRpb25FeHRlcm5hbElkPzogc3RyaW5nXG59XG5cbmV4cG9ydCB0eXBlIFByb3BlcnRpZXMgPSB7XG4gIERvbWFpbk5hbWU6IHN0cmluZ1xuICBBbHRlcm5hdGl2ZURvbWFpbk5hbWVzPzogc3RyaW5nW11cbiAgVmFsaWRhdGlvbkhvc3RlZFpvbmVzOiBSZWNvcmQ8c3RyaW5nLCBWYWxpZGF0aW9uSG9zdGVkWm9uZVByb3BlcnRpZXM+XG4gIENlcnRpZmljYXRlUmVnaW9uOiBzdHJpbmdcbiAgQ2xlYW51cFZhbGlkYXRpb25SZWNvcmRzOiBzdHJpbmdcbiAgVHJhbnNwYXJlbmN5TG9nZ2luZ0VuYWJsZWQ6IHN0cmluZ1xuICBUYWdzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPlxuICBSZW1vdmFsUG9saWN5OiBzdHJpbmdcbn1cblxudHlwZSBSb3V0ZTUzRmFjdG9yeSA9IChyb2xlQXJuOiBzdHJpbmcgfCB1bmRlZmluZWQsIGV4dGVybmFsSWQ6IHN0cmluZyB8IHVuZGVmaW5lZCkgPT4gUm91dGU1M0NsaWVudFxuXG5jb25zdCBwYXJzZVByb3BlcnRpZXMgPSAocHJvcGVydGllczogUmVjb3JkPHN0cmluZywgYW55Pik6IFByb3BlcnRpZXMgPT4ge1xuICAvLyBtYXliZSBzaG91bGQgYWN0dWFsbHkgcGFyc2UgYW5kIG5vdCBqdXN0IGFzc3VtZVxuICByZXR1cm4gcHJvcGVydGllcyBhcyB1bmtub3duIGFzIFByb3BlcnRpZXNcbn1cblxuY29uc3QgcGFyc2VEb21haW5WYWxpZGF0aW9uUmVjb3JkcyA9IChjZXJ0aWZpY2F0ZTogQ2VydGlmaWNhdGVEZXRhaWwpOiBSZXNvdXJjZVJlY29yZFNldFtdIHwgbnVsbCA9PiB7XG4gIGNvbnN0IG9wdGlvbnMgPSBjZXJ0aWZpY2F0ZS5Eb21haW5WYWxpZGF0aW9uT3B0aW9ucyA/PyBbXVxuICBpZiAob3B0aW9ucy5sZW5ndGggPiAwICYmIG9wdGlvbnMuZXZlcnkoKG9wdCkgPT4gb3B0LlJlc291cmNlUmVjb3JkPy5OYW1lKSkge1xuICAgIGNvbnN0IHVuaXF1ZVJlY29yZHMgPSBbLi4ubmV3IE1hcChvcHRpb25zLm1hcCgob3B0KSA9PiBbb3B0LlJlc291cmNlUmVjb3JkPy5OYW1lISwgb3B0LlJlc291cmNlUmVjb3JkIV0pKS52YWx1ZXMoKV1cbiAgICByZXR1cm4gdW5pcXVlUmVjb3Jkcy5tYXAoKHJlY29yZCkgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgTmFtZTogcmVjb3JkLk5hbWUsXG4gICAgICAgIFR5cGU6IHJlY29yZC5UeXBlLFxuICAgICAgICBUVEw6IDMwLFxuICAgICAgICBSZXNvdXJjZVJlY29yZHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBWYWx1ZTogcmVjb3JkLlZhbHVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG4gICAgfSlcbiAgfVxuICByZXR1cm4gbnVsbFxufVxuXG5jb25zdCBjaGFuZ2VSZWNvcmRTZXRzID0gYXN5bmMgKFxuICByb3V0ZTUzOiBSb3V0ZTUzQ2xpZW50LFxuICBhY3Rpb246IENoYW5nZUFjdGlvbixcbiAgcmVjb3JkczogUmVzb3VyY2VSZWNvcmRTZXRbXSxcbiAgaG9zdGVkWm9uZUlkOiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBjb25zdCBjaGFuZ2VSZWNvcmRTZXRzSW5wdXQ6IENoYW5nZVJlc291cmNlUmVjb3JkU2V0c0NvbW1hbmRJbnB1dCA9IHtcbiAgICBIb3N0ZWRab25lSWQ6IGhvc3RlZFpvbmVJZCxcbiAgICBDaGFuZ2VCYXRjaDoge1xuICAgICAgQ2hhbmdlczogcmVjb3Jkcy5tYXAoKHJlY29yZCkgPT4gKHtcbiAgICAgICAgQWN0aW9uOiBhY3Rpb24sXG4gICAgICAgIFJlc291cmNlUmVjb3JkU2V0OiByZWNvcmQsXG4gICAgICB9KSksXG4gICAgfSxcbiAgfVxuICB0cnkge1xuICAgIGNvbnN0IHsgQ2hhbmdlSW5mbyB9ID0gYXdhaXQgcm91dGU1My5zZW5kKG5ldyBDaGFuZ2VSZXNvdXJjZVJlY29yZFNldHNDb21tYW5kKGNoYW5nZVJlY29yZFNldHNJbnB1dCkpXG4gICAgY29uc3QgY2hhbmdlSWQgPSBDaGFuZ2VJbmZvPy5JZCFcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3YWl0VW50aWxSZXNvdXJjZVJlY29yZFNldHNDaGFuZ2VkKHsgY2xpZW50OiByb3V0ZTUzLCBtYXhXYWl0VGltZTogMTgwIH0sIHsgSWQ6IGNoYW5nZUlkIH0pXG4gICAgaWYgKHJlc3VsdC5zdGF0ZSAhPT0gJ1NVQ0NFU1MnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBWYWxpZGF0aW9uIHJlY29yZHMgbmV2ZXIgY2hhbmdlZCBmb3IgaG9zdGVkIHpvbmUgJHtob3N0ZWRab25lSWR9OiBbJHtyZXN1bHQuc3RhdGV9XSAke3Jlc3VsdC5yZWFzb24gPz8gJyd9YFxuICAgICAgKVxuICAgIH1cbiAgICBjb25zdCBvcGVyYXRpb24gPSBhY3Rpb24gPT09ICdDUkVBVEUnIHx8IGFjdGlvbiA9PT0gJ1VQU0VSVCcgPyAnY2hhbmdlZCcgOiAnZGVsZXRlZCdcbiAgICBjb25zdCBjaGFuZ2UgPSBjbGVhbkNoYW5nZUlkKGNoYW5nZUlkKVxuICAgIGNvbnNvbGUubG9nKGBWYWxpZGF0aW9uIHJlY29yZHMgc3VjY2VzZnVsbHkgJHtvcGVyYXRpb259IGZvciBob3N0ZWQgem9uZSAke2hvc3RlZFpvbmVJZH0gd2l0aCBjaGFuZ2UgaWQgJHtjaGFuZ2V9YClcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBpZiAoYWN0aW9uID09PSAnREVMRVRFJyAmJiBlcnJvciBpbnN0YW5jZW9mIEludmFsaWRDaGFuZ2VCYXRjaCAmJiBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKCdub3QgZm91bmQnKSkge1xuICAgICAgLy8gdGhlcmUncyBhIGRlbGV0aW9uIHJhY2UgY29uZGl0aW9uIHdoZXJlIHNvbWUgb3RoZXIgY2VydGlmaWNhdGUgaGFzIGFscmVhZHkgZGVsZXRlZCB0aGUgcmVjb3Jkc1xuICAgICAgY29uc29sZS5sb2coYEFsbCB2YWxpZGF0aW9uIHJlY29yZHMgaGF2ZSBhbHJlYWR5IGJlZW4gcmVtb3ZlZCBieSBzb21lIG90aGVyIGNlcnRpZmljYXRlYClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG4gIH1cbn1cblxuY29uc3QgZ2V0UmVjb3Jkc0ZvclpvbmVOYW1lcyA9IChcbiAgcmVjb3JkczogUmVzb3VyY2VSZWNvcmRTZXRbXSxcbiAgem9uZU5hbWVzOiBzdHJpbmdbXSxcbiAgcmVzdWx0PzogUmVjb3JkPHN0cmluZywgUmVzb3VyY2VSZWNvcmRTZXRbXT5cbik6IFJlY29yZDxzdHJpbmcsIFJlc291cmNlUmVjb3JkU2V0W10+ID0+IHtcbiAgY29uc3QgW3pvbmVOYW1lLCAuLi5yZXN0Wm9uZU5hbWVzXSA9IHpvbmVOYW1lc1xuICBpZiAoIXpvbmVOYW1lKSB7XG4gICAgcmV0dXJuIHJlc3VsdCA/PyB7fVxuICB9XG4gIGNvbnN0IG1hdGNoaW5nUmVjb3JkczogUmVzb3VyY2VSZWNvcmRTZXRbXSA9IFtdXG4gIGNvbnN0IHVubWF0Y2hpbmdSZWNvcmRzOiBSZXNvdXJjZVJlY29yZFNldFtdID0gW11cbiAgZm9yIChjb25zdCByZWNvcmQgb2YgcmVjb3Jkcykge1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRSZWNvcmROYW1lID0gY2xlYW5Eb21haW5OYW1lKHJlY29yZC5OYW1lISlcbiAgICBpZiAobm9ybWFsaXplZFJlY29yZE5hbWUuZW5kc1dpdGgoem9uZU5hbWUpKSB7XG4gICAgICBtYXRjaGluZ1JlY29yZHMucHVzaChyZWNvcmQpXG4gICAgfSBlbHNlIHtcbiAgICAgIHVubWF0Y2hpbmdSZWNvcmRzLnB1c2gocmVjb3JkKVxuICAgIH1cbiAgfVxuICByZXR1cm4gZ2V0UmVjb3Jkc0ZvclpvbmVOYW1lcyh1bm1hdGNoaW5nUmVjb3JkcywgcmVzdFpvbmVOYW1lcywge1xuICAgIC4uLihyZXN1bHQgPz8ge30pLFxuICAgIFt6b25lTmFtZV06IG1hdGNoaW5nUmVjb3JkcyxcbiAgfSlcbn1cblxuY29uc3QgcmVxdWVzdENlcnRpZmljYXRlID0gYXN5bmMgKFxuICBhY206IEFDTUNsaWVudCxcbiAgcm91dGU1MzogUm91dGU1M0ZhY3RvcnksXG4gIHJlcXVlc3RJZDogc3RyaW5nLFxuICBwcm9wZXJ0aWVzOiBQcm9wZXJ0aWVzXG4pOiBQcm9taXNlPHN0cmluZz4gPT4ge1xuICBjb25zdCB7IERvbWFpbk5hbWUsIEFsdGVybmF0aXZlRG9tYWluTmFtZXMsIFRyYW5zcGFyZW5jeUxvZ2dpbmdFbmFibGVkIH0gPSBwcm9wZXJ0aWVzXG5cbiAgY29uc29sZS5sb2coYFJlcXVlc3RpbmcgY2VydGlmaWNhdGUgZm9yICR7RG9tYWluTmFtZX1gKVxuXG4gIGNvbnN0IHJlcXVlc3RDZXJ0aWZpY2F0ZUlucHV0OiBSZXF1ZXN0Q2VydGlmaWNhdGVDb21tYW5kSW5wdXQgPSB7XG4gICAgRG9tYWluTmFtZSxcbiAgICBTdWJqZWN0QWx0ZXJuYXRpdmVOYW1lczogQWx0ZXJuYXRpdmVEb21haW5OYW1lcyxcbiAgICBJZGVtcG90ZW5jeVRva2VuOiBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKHJlcXVlc3RJZCkuZGlnZXN0KCdoZXgnKS5zbGljZSgwLCAzMiksXG4gICAgVmFsaWRhdGlvbk1ldGhvZDogJ0ROUycsXG4gICAgT3B0aW9uczoge1xuICAgICAgQ2VydGlmaWNhdGVUcmFuc3BhcmVuY3lMb2dnaW5nUHJlZmVyZW5jZTogVHJhbnNwYXJlbmN5TG9nZ2luZ0VuYWJsZWQgPyAnRU5BQkxFRCcgOiAnRElTQUJMRUQnLFxuICAgIH0sXG4gIH1cbiAgY29uc3QgeyBDZXJ0aWZpY2F0ZUFybiB9ID0gYXdhaXQgYWNtLnNlbmQobmV3IFJlcXVlc3RDZXJ0aWZpY2F0ZUNvbW1hbmQocmVxdWVzdENlcnRpZmljYXRlSW5wdXQpKVxuXG4gIGNvbnNvbGUubG9nKGBDZXJ0aWZpY2F0ZSAke0NlcnRpZmljYXRlQXJufSByZXF1ZXN0ZWRgKVxuXG4gIGNvbnN0IHZhbGlkYXRpb25NYXhTZWNvbmRzID0gMTgwXG4gIGNvbnN0IHZhbGlkYXRpb25UaW1lb3V0RXJyb3IgPSBgRG9tYWluIHZhbGlkYXRpb24gb3B0aW9ucyB3ZXJlIG5vdCBmb3VuZCBpbiAke3ZhbGlkYXRpb25NYXhTZWNvbmRzfSBzZWNvbmRzYFxuICBjb25zdCB2YWxpZGF0aW9uUmVjb3JkcyA9IGF3YWl0IHRyeUZvcih2YWxpZGF0aW9uTWF4U2Vjb25kcywgdmFsaWRhdGlvblRpbWVvdXRFcnJvciwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGRlc2NyaWJlQ2VydGlmaWNhdGVJbnB1dDogRGVzY3JpYmVDZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCA9IHtcbiAgICAgIENlcnRpZmljYXRlQXJuLFxuICAgIH1cbiAgICBjb25zdCB7IENlcnRpZmljYXRlIH0gPSBhd2FpdCBhY20uc2VuZChuZXcgRGVzY3JpYmVDZXJ0aWZpY2F0ZUNvbW1hbmQoZGVzY3JpYmVDZXJ0aWZpY2F0ZUlucHV0KSlcbiAgICByZXR1cm4gcGFyc2VEb21haW5WYWxpZGF0aW9uUmVjb3JkcyhDZXJ0aWZpY2F0ZSEpXG4gIH0pXG5cbiAgY29uc3QgaG9zdGVkWm9uZXMgPSBPYmplY3QudmFsdWVzKHByb3BlcnRpZXMuVmFsaWRhdGlvbkhvc3RlZFpvbmVzKVxuICBjb25zdCBob3N0ZWRab25lSWRzID0gaG9zdGVkWm9uZXMubWFwKCh6b25lKSA9PiB6b25lLkhvc3RlZFpvbmVJZClcblxuICBjb25zb2xlLmxvZyhcbiAgICBgVXBzZXJ0aW5nICR7dmFsaWRhdGlvblJlY29yZHMubGVuZ3RofSB2YWxpZGF0aW9uIHJlY29yZChzKSBpbnRvIGhvc3RlZCB6b25lKHMpICR7aG9zdGVkWm9uZUlkcy5qb2luKCcsICcpfTpgXG4gIClcbiAgdmFsaWRhdGlvblJlY29yZHMuZm9yRWFjaCgocmVjb3JkKSA9PlxuICAgIGNvbnNvbGUubG9nKGAke3JlY29yZC5OYW1lfSAke3JlY29yZC5UeXBlfSAke3JlY29yZC5SZXNvdXJjZVJlY29yZHM/Lm1hcCgocnIpID0+IHJyLlZhbHVlKS5qb2luKCcsJyl9YClcbiAgKVxuXG4gIGNvbnN0IHJlY29yZHNGb3Jab25lTmFtZXMgPSBnZXRSZWNvcmRzRm9yWm9uZU5hbWVzKFxuICAgIHZhbGlkYXRpb25SZWNvcmRzLFxuICAgIG9yZGVyQnlTaWduaWZpY2FuY2UoT2JqZWN0LmtleXMocHJvcGVydGllcy5WYWxpZGF0aW9uSG9zdGVkWm9uZXMpKVxuICApXG4gIGZvciAoY29uc3QgaG9zdGVkWm9uZSBvZiBob3N0ZWRab25lcykge1xuICAgIGNvbnN0IHJlY29yZHMgPSByZWNvcmRzRm9yWm9uZU5hbWVzW2hvc3RlZFpvbmUuRG9tYWluTmFtZV1cbiAgICBpZiAocmVjb3Jkcy5sZW5ndGggPiAwKSB7XG4gICAgICBhd2FpdCBjaGFuZ2VSZWNvcmRTZXRzKFxuICAgICAgICByb3V0ZTUzKGhvc3RlZFpvbmUuVmFsaWRhdGlvblJvbGVBcm4sIGhvc3RlZFpvbmUuVmFsaWRhdGlvbkV4dGVybmFsSWQpLFxuICAgICAgICAnVVBTRVJUJyxcbiAgICAgICAgcmVjb3JkcyxcbiAgICAgICAgaG9zdGVkWm9uZS5Ib3N0ZWRab25lSWRcbiAgICAgIClcbiAgICB9XG4gIH1cblxuICBjb25zb2xlLmxvZyhgV2FpdGluZyBmb3IgY2VydGlmaWNhdGUgJHtDZXJ0aWZpY2F0ZUFybn0gdG8gdmFsaWRhdGVgKVxuICBjb25zdCByZXN1bHQgPSBhd2FpdCB3YWl0VW50aWxDZXJ0aWZpY2F0ZVZhbGlkYXRlZCh7IGNsaWVudDogYWNtLCBtYXhXYWl0VGltZTogMzAwIH0sIHsgQ2VydGlmaWNhdGVBcm4gfSlcbiAgaWYgKHJlc3VsdC5zdGF0ZSAhPT0gJ1NVQ0NFU1MnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDZXJ0aWZpY2F0ZSBmYWlsZWQgJHtDZXJ0aWZpY2F0ZUFybn0gdG8gdmFsaWRhdGU6IFske3Jlc3VsdC5zdGF0ZX1dICR7cmVzdWx0LnJlYXNvbiA/PyAnJ31gKVxuICB9XG4gIGNvbnNvbGUubG9nKGBDZXJ0aWZpY2F0ZSAke0NlcnRpZmljYXRlQXJufSBzdWNjZXNzZnVsbHkgdmFsaWRhdGVkYClcbiAgcmV0dXJuIENlcnRpZmljYXRlQXJuIVxufVxuXG5jb25zdCBkZWxldGVDZXJ0aWZpY2F0ZSA9IGFzeW5jIChcbiAgYWNtOiBBQ01DbGllbnQsXG4gIHJvdXRlNTM6IFJvdXRlNTNGYWN0b3J5LFxuICBjZXJ0aWZpY2F0ZUFybjogc3RyaW5nLFxuICBwcm9wZXJ0aWVzOiBQcm9wZXJ0aWVzXG4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgY29uc29sZS5sb2coYFdhaXRpbmcgZm9yIGNlcnRpZmljYXRlICR7Y2VydGlmaWNhdGVBcm59IHVzYWdlIHRvIGRyYWluIGJlZm9yZSBkZWxldGlvbmApXG5cbiAgY29uc3Qgd2FpdFVzYWdlTWF4U2Vjb25kcyA9IDYwMFxuICBjb25zdCB3YWl0VXNhZ2VUaW1lb3V0RXJyb3IgPSBgQ2VydGlmaWNhdGUgd2FzIHN0aWxsIGluIHVzZSBhZnRlciAke3dhaXRVc2FnZU1heFNlY29uZHN9IHNlY29uZHNgXG4gIGNvbnN0IGNlcnRpZmljYXRlID0gYXdhaXQgdHJ5Rm9yKHdhaXRVc2FnZU1heFNlY29uZHMsIHdhaXRVc2FnZVRpbWVvdXRFcnJvciwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGRlc2NyaWJlQ2VydGlmaWNhdGVJbnB1dDogRGVzY3JpYmVDZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCA9IHtcbiAgICAgIENlcnRpZmljYXRlQXJuOiBjZXJ0aWZpY2F0ZUFybixcbiAgICB9XG4gICAgY29uc3QgeyBDZXJ0aWZpY2F0ZSB9ID0gYXdhaXQgYWNtLnNlbmQobmV3IERlc2NyaWJlQ2VydGlmaWNhdGVDb21tYW5kKGRlc2NyaWJlQ2VydGlmaWNhdGVJbnB1dCkpXG4gICAgY29uc3QgaW5Vc2VCeSA9IENlcnRpZmljYXRlPy5JblVzZUJ5ID8/IFtdXG4gICAgaWYgKGluVXNlQnkubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIG51bGxcbiAgICB9XG4gICAgcmV0dXJuIENlcnRpZmljYXRlIVxuICB9KVxuICBjb25zb2xlLmxvZygnQ2VydGlmaWNhdGUgaXMgdW51c2VkIGFuZCB3aWxsIGJlIGRlbGV0ZWQnKVxuXG4gIGNvbnN0IHZhbGlkYXRpb25SZWNvcmRzID0gcGFyc2VEb21haW5WYWxpZGF0aW9uUmVjb3JkcyhjZXJ0aWZpY2F0ZSlcbiAgaWYgKHZhbGlkYXRpb25SZWNvcmRzICYmIHN0cmluZ1RvQm9vbGVhbihwcm9wZXJ0aWVzLkNsZWFudXBWYWxpZGF0aW9uUmVjb3JkcykpIHtcbiAgICBjb25zdCBob3N0ZWRab25lcyA9IE9iamVjdC52YWx1ZXMocHJvcGVydGllcy5WYWxpZGF0aW9uSG9zdGVkWm9uZXMpXG4gICAgY29uc3QgaG9zdGVkWm9uZUlkcyA9IGhvc3RlZFpvbmVzLm1hcCgoem9uZSkgPT4gem9uZS5Ib3N0ZWRab25lSWQpXG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGBEZWxldGluZyAke3ZhbGlkYXRpb25SZWNvcmRzLmxlbmd0aH0gdmFsaWRhdGlvbiByZWNvcmQocykgZnJvbSBob3N0ZWQgem9uZShzKSAke2hvc3RlZFpvbmVJZHMuam9pbignLCAnKX1gXG4gICAgKVxuXG4gICAgY29uc3QgcmVjb3Jkc0ZvclpvbmVOYW1lcyA9IGdldFJlY29yZHNGb3Jab25lTmFtZXMoXG4gICAgICB2YWxpZGF0aW9uUmVjb3JkcyxcbiAgICAgIG9yZGVyQnlTaWduaWZpY2FuY2UoT2JqZWN0LmtleXMocHJvcGVydGllcy5WYWxpZGF0aW9uSG9zdGVkWm9uZXMpKVxuICAgIClcbiAgICBmb3IgKGNvbnN0IGhvc3RlZFpvbmUgb2YgaG9zdGVkWm9uZXMpIHtcbiAgICAgIGNvbnN0IHJlY29yZHMgPSByZWNvcmRzRm9yWm9uZU5hbWVzW2hvc3RlZFpvbmUuRG9tYWluTmFtZV1cbiAgICAgIGlmIChyZWNvcmRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgYXdhaXQgY2hhbmdlUmVjb3JkU2V0cyhcbiAgICAgICAgICByb3V0ZTUzKGhvc3RlZFpvbmUuVmFsaWRhdGlvblJvbGVBcm4sIGhvc3RlZFpvbmUuVmFsaWRhdGlvbkV4dGVybmFsSWQpLFxuICAgICAgICAgICdERUxFVEUnLFxuICAgICAgICAgIHJlY29yZHMsXG4gICAgICAgICAgaG9zdGVkWm9uZS5Ib3N0ZWRab25lSWRcbiAgICAgICAgKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnNvbGUubG9nKGBEZWxldGluZyBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlQXJufSBmcm9tIEFDTWApXG4gIGNvbnN0IGRlbGV0ZUNlcnRpZmljYXRlSW5wdXQ6IERlbGV0ZUNlcnRpZmljYXRlQ29tbWFuZElucHV0ID0ge1xuICAgIENlcnRpZmljYXRlQXJuOiBjZXJ0aWZpY2F0ZUFybixcbiAgfVxuICBhd2FpdCBhY20uc2VuZChuZXcgRGVsZXRlQ2VydGlmaWNhdGVDb21tYW5kKGRlbGV0ZUNlcnRpZmljYXRlSW5wdXQpKVxuICBjb25zb2xlLmxvZyhgQ2VydGlmaWNhdGUgJHtjZXJ0aWZpY2F0ZUFybn0gc3VjY2Vzc2Z1bGx5IGRlbGV0ZWRgKVxufVxuXG5jb25zdCBhZGRUYWdzID0gYXN5bmMgKGFjbTogQUNNQ2xpZW50LCBjZXJ0aWZpY2F0ZUFybjogc3RyaW5nLCB0YWdzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KSA9PiB7XG4gIGNvbnN0IHRhZ0xpc3QgPSBBcnJheS5mcm9tKE9iamVjdC5lbnRyaWVzKHRhZ3MpLm1hcCgoW0tleSwgVmFsdWVdKSA9PiAoeyBLZXksIFZhbHVlIH0pKSlcbiAgY29uc3QgYWRkVGFnc0lucHV0OiBBZGRUYWdzVG9DZXJ0aWZpY2F0ZUNvbW1hbmRJbnB1dCA9IHtcbiAgICBDZXJ0aWZpY2F0ZUFybjogY2VydGlmaWNhdGVBcm4sXG4gICAgVGFnczogdGFnTGlzdCxcbiAgfVxuXG4gIGNvbnNvbGUubG9nKGBBZGRpbmcgJHt0YWdMaXN0Lmxlbmd0aH0gdGFncyB0byBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlQXJufWApXG4gIGF3YWl0IGFjbS5zZW5kKG5ldyBBZGRUYWdzVG9DZXJ0aWZpY2F0ZUNvbW1hbmQoYWRkVGFnc0lucHV0KSlcbiAgY29uc29sZS5sb2coYEFsbCB0YWdzIHN1Y2Nlc3NmdWxseSBhZGRlZCB0byBjZXJ0aWZpY2F0ZSAke2NlcnRpZmljYXRlQXJufWApXG59XG5cbmNvbnN0IHNob3VsZFJlcXVlc3ROZXcgPSAob2xkUHJvcGVydGllczogUHJvcGVydGllcywgbmV3UHJvcGVydGllczogUHJvcGVydGllcyk6IGJvb2xlYW4gPT4ge1xuICBjb25zdCBvbGRIb3N0ZWRab25lSWRzID0gT2JqZWN0LnZhbHVlcyhvbGRQcm9wZXJ0aWVzLlZhbGlkYXRpb25Ib3N0ZWRab25lcyA/PyB7fSkubWFwKCh6b25lKSA9PiB6b25lLkhvc3RlZFpvbmVJZClcbiAgY29uc3QgbmV3SG9zdGVkWm9uZUlkcyA9IE9iamVjdC52YWx1ZXMobmV3UHJvcGVydGllcy5WYWxpZGF0aW9uSG9zdGVkWm9uZXMgPz8ge30pLm1hcCgoem9uZSkgPT4gem9uZS5Ib3N0ZWRab25lSWQpXG4gIGlmICghY29udGFpbnNTYW1lKG9sZEhvc3RlZFpvbmVJZHMsIG5ld0hvc3RlZFpvbmVJZHMpKSByZXR1cm4gdHJ1ZVxuICBpZiAob2xkUHJvcGVydGllcy5Eb21haW5OYW1lICE9PSBuZXdQcm9wZXJ0aWVzLkRvbWFpbk5hbWUpIHJldHVybiB0cnVlXG4gIGlmICghY29udGFpbnNTYW1lKG9sZFByb3BlcnRpZXMuQWx0ZXJuYXRpdmVEb21haW5OYW1lcyA/PyBbXSwgbmV3UHJvcGVydGllcy5BbHRlcm5hdGl2ZURvbWFpbk5hbWVzID8/IFtdKSkgcmV0dXJuIHRydWVcbiAgaWYgKG9sZFByb3BlcnRpZXMuQ2VydGlmaWNhdGVSZWdpb24gIT09IG5ld1Byb3BlcnRpZXMuQ2VydGlmaWNhdGVSZWdpb24pIHJldHVybiB0cnVlXG4gIGlmIChvbGRQcm9wZXJ0aWVzLkNsZWFudXBWYWxpZGF0aW9uUmVjb3JkcyAhPT0gbmV3UHJvcGVydGllcy5DbGVhbnVwVmFsaWRhdGlvblJlY29yZHMpIHJldHVybiB0cnVlXG4gIGlmIChvbGRQcm9wZXJ0aWVzLlRyYW5zcGFyZW5jeUxvZ2dpbmdFbmFibGVkICE9PSBuZXdQcm9wZXJ0aWVzLlRyYW5zcGFyZW5jeUxvZ2dpbmdFbmFibGVkKSByZXR1cm4gdHJ1ZVxuICBpZiAob2xkUHJvcGVydGllcy5SZW1vdmFsUG9saWN5ICE9PSBuZXdQcm9wZXJ0aWVzLlJlbW92YWxQb2xpY3kpIHJldHVybiB0cnVlXG4gIHJldHVybiBmYWxzZVxufVxuXG5jb25zdCBhc3N1bWVSb2xlID0gKFxuICByb2xlQXJuOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIGV4dGVybmFsSWQ6IHN0cmluZyB8IHVuZGVmaW5lZFxuKTogUHJvdmlkZXI8QXdzQ3JlZGVudGlhbElkZW50aXR5PiB8IHVuZGVmaW5lZCA9PiB7XG4gIGlmICghcm9sZUFybikge1xuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfVxuICByZXR1cm4gYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHN0cyA9IG5ldyBTVFNDbGllbnQoeyByZXRyeU1vZGU6ICdhZGFwdGl2ZScgfSlcbiAgICBjb25zdCBhc3N1bWVSb2xlSW5wdXQ6IEFzc3VtZVJvbGVDb21tYW5kSW5wdXQgPSB7XG4gICAgICBSb2xlQXJuOiByb2xlQXJuLFxuICAgICAgUm9sZVNlc3Npb25OYW1lOiAnQ2VydGlmaWNhdGVSZXF1ZXN0b3InLFxuICAgICAgRXh0ZXJuYWxJZDogZXh0ZXJuYWxJZCxcbiAgICB9XG4gICAgY29uc3QgeyBDcmVkZW50aWFscyB9ID0gYXdhaXQgc3RzLnNlbmQobmV3IEFzc3VtZVJvbGVDb21tYW5kKGFzc3VtZVJvbGVJbnB1dCkpXG4gICAgcmV0dXJuIHtcbiAgICAgIGFjY2Vzc0tleUlkOiBDcmVkZW50aWFscz8uQWNjZXNzS2V5SWQhLFxuICAgICAgc2VjcmV0QWNjZXNzS2V5OiBDcmVkZW50aWFscz8uU2VjcmV0QWNjZXNzS2V5ISxcbiAgICAgIHNlc3Npb25Ub2tlbjogQ3JlZGVudGlhbHM/LlNlc3Npb25Ub2tlbiEsXG4gICAgICBleHBpcmF0aW9uOiBDcmVkZW50aWFscz8uRXhwaXJhdGlvbixcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGhhbmRsZXIgPSBhc3luYyAoZXZlbnQ6IENsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCkgPT4ge1xuICBjb25zdCBwcm9wZXJ0aWVzID0gcGFyc2VQcm9wZXJ0aWVzKGV2ZW50LlJlc291cmNlUHJvcGVydGllcylcblxuICBjb25zdCBhY20gPSBuZXcgQUNNQ2xpZW50KHsgcmVnaW9uOiBwcm9wZXJ0aWVzLkNlcnRpZmljYXRlUmVnaW9uLCByZXRyeU1vZGU6ICdhZGFwdGl2ZScgfSlcbiAgY29uc3Qgcm91dGU1MyA9IChyb2xlQXJuOiBzdHJpbmcgfCB1bmRlZmluZWQsIGV4dGVybmFsSWQ6IHN0cmluZyB8IHVuZGVmaW5lZCk6IFJvdXRlNTNDbGllbnQgPT4ge1xuICAgIHJldHVybiBuZXcgUm91dGU1M0NsaWVudCh7XG4gICAgICByZXRyeU1vZGU6ICdhZGFwdGl2ZScsXG4gICAgICBjcmVkZW50aWFsczogYXNzdW1lUm9sZShyb2xlQXJuLCBleHRlcm5hbElkKSxcbiAgICB9KVxuICB9XG5cbiAgc3dpdGNoIChldmVudC5SZXF1ZXN0VHlwZSkge1xuICAgIGNhc2UgJ0NyZWF0ZSc6IHtcbiAgICAgIGNvbnNvbGUubG9nKGBSZXF1ZXN0aW5nIG5ldyBjZXJ0aWZpY2F0ZTpcXG4ke29iamVjdFRvU3RyaW5nKHByb3BlcnRpZXMpfWApXG4gICAgICBjb25zdCBjZXJ0aWZpY2F0ZUFybiA9IGF3YWl0IHJlcXVlc3RDZXJ0aWZpY2F0ZShhY20sIHJvdXRlNTMsIGV2ZW50LlJlcXVlc3RJZCwgcHJvcGVydGllcylcbiAgICAgIGlmIChwcm9wZXJ0aWVzLlRhZ3MgJiYgT2JqZWN0LmVudHJpZXMocHJvcGVydGllcy5UYWdzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IGFkZFRhZ3MoYWNtLCBjZXJ0aWZpY2F0ZUFybiwgcHJvcGVydGllcy5UYWdzKVxuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIEFybjogY2VydGlmaWNhdGVBcm4sXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgfVxuICAgIGNhc2UgJ1VwZGF0ZSc6IHtcbiAgICAgIGxldCBjZXJ0aWZpY2F0ZUFybiA9IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZFxuICAgICAgaWYgKHNob3VsZFJlcXVlc3ROZXcocGFyc2VQcm9wZXJ0aWVzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcyksIHByb3BlcnRpZXMpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBSZXF1ZXN0aW5nIG5ldyBjZXJ0aWZpY2F0ZSBkdWUgdG8gY2hhbmdlIG9mIHByb3BlcnRpZXM6XFxuJHtvYmplY3RUb1N0cmluZyhwcm9wZXJ0aWVzKX1gKVxuICAgICAgICBjZXJ0aWZpY2F0ZUFybiA9IGF3YWl0IHJlcXVlc3RDZXJ0aWZpY2F0ZShhY20sIHJvdXRlNTMsIGV2ZW50LlJlcXVlc3RJZCwgcHJvcGVydGllcylcbiAgICAgIH1cbiAgICAgIGlmIChwcm9wZXJ0aWVzLlRhZ3MgJiYgT2JqZWN0LmVudHJpZXMocHJvcGVydGllcy5UYWdzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IGFkZFRhZ3MoYWNtLCBjZXJ0aWZpY2F0ZUFybiwgcHJvcGVydGllcy5UYWdzKVxuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIEFybjogY2VydGlmaWNhdGVBcm4sXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgfVxuICAgIGNhc2UgJ0RlbGV0ZSc6IHtcbiAgICAgIGNvbnN0IGNlcnRpZmljYXRlQXJuID0gZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkXG4gICAgICBpZiAocHJvcGVydGllcy5SZW1vdmFsUG9saWN5ID09PSAnZGVzdHJveScpIHtcbiAgICAgICAgY29uc29sZS5sb2coYERlbGV0aW5nIG9sZCBjZXJ0aWZpY2F0ZSBhcyBwZXIgcmVtb3ZhbCBwb2xpY3k6XFxuJHtvYmplY3RUb1N0cmluZyhwcm9wZXJ0aWVzKX1gKVxuICAgICAgICBhd2FpdCBkZWxldGVDZXJ0aWZpY2F0ZShhY20sIHJvdXRlNTMsIGNlcnRpZmljYXRlQXJuLCBwcm9wZXJ0aWVzKVxuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIEFybjogY2VydGlmaWNhdGVBcm4sXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByZXF1ZXN0IHR5cGVgKVxufVxuIl19
|
|
@@ -3,6 +3,35 @@ import * as certificatemanager from 'aws-cdk-lib/aws-certificatemanager';
|
|
|
3
3
|
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
4
4
|
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
5
5
|
import { Construct } from 'constructs';
|
|
6
|
+
export interface ValidationHostedZone {
|
|
7
|
+
/**
|
|
8
|
+
* Hosted zone to use for DNS validation. The zone name is matched to domain name to use the right
|
|
9
|
+
* hosted zone for validation.
|
|
10
|
+
*
|
|
11
|
+
* If the hosted zone is not managed by the CDK application, it needs to be provided via
|
|
12
|
+
* ``HostedZone.fromHostedZoneAttributes()``.
|
|
13
|
+
*/
|
|
14
|
+
readonly hostedZone: route53.IHostedZone;
|
|
15
|
+
/**
|
|
16
|
+
* The role that is assumed for DNS record changes for certificate validation.
|
|
17
|
+
*
|
|
18
|
+
* This role should exist in the same account as the hosted zone and include permissions to change the DNS records
|
|
19
|
+
* for the given ``hostedZone``. The ``customResourceRole`` or the default execution role is given permission to
|
|
20
|
+
* assume this role.
|
|
21
|
+
*
|
|
22
|
+
* @default - No separate role for DNS record changes. The given customResourceRole or the default role is used
|
|
23
|
+
* for DNS record changes.
|
|
24
|
+
*/
|
|
25
|
+
readonly validationRole?: iam.IRole;
|
|
26
|
+
/**
|
|
27
|
+
* External id for ``validationRole`` role assume verification.
|
|
28
|
+
*
|
|
29
|
+
* This should be used only when ``validationRole`` is given and the role expects an external id provided on assume.
|
|
30
|
+
*
|
|
31
|
+
* @default - No external id provided during assume.
|
|
32
|
+
*/
|
|
33
|
+
readonly validationExternalId?: string;
|
|
34
|
+
}
|
|
6
35
|
export interface DnsValidatedCertificateProps {
|
|
7
36
|
/**
|
|
8
37
|
* Fully-qualified domain name to request a certificate for.
|
|
@@ -11,12 +40,15 @@ export interface DnsValidatedCertificateProps {
|
|
|
11
40
|
*/
|
|
12
41
|
readonly domainName: string;
|
|
13
42
|
/**
|
|
14
|
-
*
|
|
43
|
+
* Fully-qualified alternative domain names to request a certificate for.
|
|
15
44
|
*
|
|
16
|
-
*
|
|
17
|
-
* ``HostedZone.fromHostedZoneAttributes()``.
|
|
45
|
+
* May contain wildcards, such as ``*.otherdomain.com``.
|
|
18
46
|
*/
|
|
19
|
-
readonly
|
|
47
|
+
readonly alternativeDomainNames?: string[];
|
|
48
|
+
/**
|
|
49
|
+
* List of hosted zones to use for validation. Hosted zones are mapped to domain names by the zone name.
|
|
50
|
+
*/
|
|
51
|
+
readonly validationHostedZones: ValidationHostedZone[];
|
|
20
52
|
/**
|
|
21
53
|
* AWS region where the certificate is deployed.
|
|
22
54
|
*
|
|
@@ -29,32 +61,13 @@ export interface DnsValidatedCertificateProps {
|
|
|
29
61
|
/**
|
|
30
62
|
* The role that is used for the custom resource Lambda execution.
|
|
31
63
|
*
|
|
32
|
-
* The role is given permissions to request certificates from ACM. If
|
|
33
|
-
* is also given permission to assume the ``validationRole``. Otherwise it is assumed that the hosted zone
|
|
34
|
-
* account and the execution role is given permissions to change DNS records for the given ``domainName``.
|
|
64
|
+
* The role is given permissions to request certificates from ACM. If there are any ``validationRole``s provided,
|
|
65
|
+
* this role is also given permission to assume the ``validationRole``. Otherwise it is assumed that the hosted zone
|
|
66
|
+
* is in same account and the execution role is given permissions to change DNS records for the given ``domainName``.
|
|
35
67
|
*
|
|
36
68
|
* @default - Lambda creates a default execution role.
|
|
37
69
|
*/
|
|
38
70
|
readonly customResourceRole?: iam.IRole;
|
|
39
|
-
/**
|
|
40
|
-
* The role that is assumed for DNS record changes for certificate validation.
|
|
41
|
-
*
|
|
42
|
-
* This role should exist in the same account as the hosted zone and include permissions to change the DNS records
|
|
43
|
-
* for the given ``hostedZone``. The ``customResourceRole`` or the default execution role is given permission to
|
|
44
|
-
* assume this role.
|
|
45
|
-
*
|
|
46
|
-
* @default - No separate role for DNS record changes. The given customResourceRole or the default role is used
|
|
47
|
-
* for DNS record changes.
|
|
48
|
-
*/
|
|
49
|
-
readonly validationRole?: iam.IRole;
|
|
50
|
-
/**
|
|
51
|
-
* External id for ``validationRole`` role assume verification.
|
|
52
|
-
*
|
|
53
|
-
* This should be used only when ``validationRole`` is given and the role expects an external id provided on assume.
|
|
54
|
-
*
|
|
55
|
-
* @default - No external id provided during assume
|
|
56
|
-
*/
|
|
57
|
-
readonly validationExternalId?: string;
|
|
58
71
|
/**
|
|
59
72
|
* Enable or disable cleaning of validation DNS records from the hosted zone.
|
|
60
73
|
*
|
|
@@ -99,32 +112,58 @@ export interface DnsValidatedCertificateProps {
|
|
|
99
112
|
* Please note that this construct does not support alternative names yet as it would require domain to role mapping.
|
|
100
113
|
*
|
|
101
114
|
* @example
|
|
102
|
-
* //
|
|
115
|
+
* // ### Cross-region certificate validation
|
|
103
116
|
* // hosted zone managed by the CDK application
|
|
104
117
|
* const hostedZone: route53.IHostedZone = ...
|
|
105
118
|
* // no separate validation role is needed
|
|
106
119
|
* const certificate = new DnsValidatedCertificate(this, 'CrossRegionCertificate', {
|
|
107
|
-
* hostedZone: hostedZone,
|
|
108
120
|
* domainName: 'example.com', // must be compatible with the hosted zone
|
|
121
|
+
* validationHostedZones: [{ // hosted zone used with the execution role's permissions
|
|
122
|
+
* hostedZone: hostedZone
|
|
123
|
+
* }],
|
|
109
124
|
* certificateRegion: 'us-east-1' // used by for example CloudFront
|
|
110
125
|
* })
|
|
111
|
-
* //
|
|
126
|
+
* // ### Cross-account certificate validation
|
|
112
127
|
* // external hosted zone
|
|
113
128
|
* const hostedZone: route53.IHostedZone =
|
|
114
129
|
* route53.HostedZone.fromHostedZoneAttributes(this, 'HostedZone', {
|
|
115
130
|
* hostedZoneId: 'Z532DGDEDFS123456789',
|
|
116
131
|
* zoneName: 'example.com'
|
|
117
132
|
* })
|
|
118
|
-
* // validation role
|
|
133
|
+
* // validation role in the same account as the hosted zone
|
|
119
134
|
* const roleArn = 'arn:aws:iam::123456789:role/ChangeDnsRecordsRole'
|
|
120
135
|
* const externalId = 'domain-assume'
|
|
121
136
|
* const validationRole: iam.IRole =
|
|
122
137
|
* iam.Role.fromRoleArn(this, 'ValidationRole', roleArn)
|
|
123
138
|
* const certificate = new DnsValidatedCertificate(this, 'CrossAccountCertificate', {
|
|
124
|
-
* hostedZone: hostedZone,
|
|
125
139
|
* domainName: 'example.com',
|
|
126
|
-
*
|
|
127
|
-
|
|
140
|
+
* validationHostedZones: [{
|
|
141
|
+
* hostedZone: hostedZone,
|
|
142
|
+
* validationRole: validationRole,
|
|
143
|
+
* validationExternalId: externalId
|
|
144
|
+
* }]
|
|
145
|
+
* })
|
|
146
|
+
* // ### Cross-account alternative name validation
|
|
147
|
+
* // example.com is validated on same account against managed hosted zone
|
|
148
|
+
* // and secondary.com is validated against external hosted zone on other account
|
|
149
|
+
* const hostedZoneForMain: route53.IHostedZone = ...
|
|
150
|
+
* const hostedZoneForAlternative: route53.IHostedZone =
|
|
151
|
+
* route53.HostedZone.fromHostedZoneAttributes(this, 'SecondaryHostedZone', {
|
|
152
|
+
* hostedZoneId: 'Z532DGDEDFS123456789',
|
|
153
|
+
* zoneName: 'secondary.com'
|
|
154
|
+
* })
|
|
155
|
+
* const certificate = new DnsValidatedCertificate(this, 'CrossAccountCertificate', {
|
|
156
|
+
* domainName: 'example.com',
|
|
157
|
+
* alternativeDomainNames: ['secondary.com'],
|
|
158
|
+
* validationHostedZones: [{
|
|
159
|
+
* hostedZone: hostedZoneForMain
|
|
160
|
+
* },{
|
|
161
|
+
* hostedZone: hostedZoneForAlternative,
|
|
162
|
+
* validationRole: iam.Role.fromRoleArn(
|
|
163
|
+
* this, 'SecondaryValidationRole', 'arn:aws:iam::123456789:role/ChangeDnsRecordsRole'
|
|
164
|
+
* ),
|
|
165
|
+
* validationExternalId: 'domain-assume'
|
|
166
|
+
* }]
|
|
128
167
|
* })
|
|
129
168
|
*
|
|
130
169
|
* @resource Custom::DnsValidatedCertificate
|
|
@@ -135,12 +174,6 @@ export declare class DnsValidatedCertificate extends cdk.Resource implements cer
|
|
|
135
174
|
readonly certificateArn: string;
|
|
136
175
|
/** The region where the certificate is deployed to */
|
|
137
176
|
readonly certificateRegion: string;
|
|
138
|
-
/** The hosted zone identifier authoritative for the certificate */
|
|
139
|
-
readonly hostedZoneId: string;
|
|
140
|
-
/** The hosted zone name authoritative for the certificate */
|
|
141
|
-
readonly hostedZoneName: string;
|
|
142
|
-
/** The domain name included in the certificate */
|
|
143
|
-
readonly domainName: string;
|
|
144
177
|
/** The tag manager to set, remove and format tags for the certificate */
|
|
145
178
|
readonly tags: cdk.TagManager;
|
|
146
179
|
/** The removal policy for the certificate */
|
|
@@ -158,5 +191,5 @@ export declare class DnsValidatedCertificate extends cdk.Resource implements cer
|
|
|
158
191
|
private normalizeDomainName;
|
|
159
192
|
private normalizeHostedZoneId;
|
|
160
193
|
private wildcardDomainName;
|
|
161
|
-
private
|
|
194
|
+
private validateDomainsToHostedZones;
|
|
162
195
|
}
|