@aws-solutions-constructs/aws-cloudfront-s3 2.99.0 → 2.100.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.
|
@@ -1,847 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
|
|
6
|
-
* with the License. A copy of the License is located at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
|
|
11
|
-
* OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
|
|
12
|
-
* and limitations under the License.
|
|
13
|
-
*/
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
const assertions_1 = require("aws-cdk-lib/assertions");
|
|
16
|
-
const s3 = require("aws-cdk-lib/aws-s3");
|
|
17
|
-
const cdk = require("aws-cdk-lib");
|
|
18
|
-
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
19
|
-
const lib_1 = require("../lib");
|
|
20
|
-
const acm = require("aws-cdk-lib/aws-certificatemanager");
|
|
21
|
-
const defaults = require("@aws-solutions-constructs/core");
|
|
22
|
-
const aws_kms_1 = require("aws-cdk-lib/aws-kms");
|
|
23
|
-
const origins = require("aws-cdk-lib/aws-cloudfront-origins");
|
|
24
|
-
const aws_cloudfront_1 = require("aws-cdk-lib/aws-cloudfront");
|
|
25
|
-
function deploy(stack, props) {
|
|
26
|
-
return new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
|
|
27
|
-
bucketProps: {
|
|
28
|
-
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
29
|
-
},
|
|
30
|
-
...props
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
test('construct defaults set properties correctly', () => {
|
|
34
|
-
const stack = new cdk.Stack();
|
|
35
|
-
const construct = new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {});
|
|
36
|
-
expect(construct.cloudFrontWebDistribution).toBeDefined();
|
|
37
|
-
expect(construct.cloudFrontFunction).toBeDefined();
|
|
38
|
-
expect(construct.cloudFrontLoggingBucket).toBeDefined();
|
|
39
|
-
expect(construct.s3Bucket).toBeDefined();
|
|
40
|
-
expect(construct.s3LoggingBucket).toBeDefined();
|
|
41
|
-
expect(construct.s3BucketInterface).toBeDefined();
|
|
42
|
-
expect(construct.cloudFrontLoggingBucketAccessLogBucket).toBeDefined();
|
|
43
|
-
expect(construct.originAccessControl).toBeDefined();
|
|
44
|
-
});
|
|
45
|
-
test('check s3Bucket default encryption', () => {
|
|
46
|
-
const stack = new cdk.Stack();
|
|
47
|
-
deploy(stack);
|
|
48
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
49
|
-
template.hasResourceProperties('AWS::S3::Bucket', {
|
|
50
|
-
BucketEncryption: {
|
|
51
|
-
ServerSideEncryptionConfiguration: [{
|
|
52
|
-
ServerSideEncryptionByDefault: {
|
|
53
|
-
SSEAlgorithm: "AES256"
|
|
54
|
-
}
|
|
55
|
-
}]
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
test('check s3Bucket public access block configuration', () => {
|
|
60
|
-
const stack = new cdk.Stack();
|
|
61
|
-
deploy(stack);
|
|
62
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
63
|
-
template.hasResourceProperties('AWS::S3::Bucket', {
|
|
64
|
-
PublicAccessBlockConfiguration: {
|
|
65
|
-
BlockPublicAcls: true,
|
|
66
|
-
BlockPublicPolicy: true,
|
|
67
|
-
IgnorePublicAcls: true,
|
|
68
|
-
RestrictPublicBuckets: true
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
test('test s3Bucket override publicAccessBlockConfiguration', () => {
|
|
73
|
-
const stack = new cdk.Stack();
|
|
74
|
-
const props = {
|
|
75
|
-
bucketProps: {
|
|
76
|
-
blockPublicAccess: {
|
|
77
|
-
blockPublicAcls: false,
|
|
78
|
-
blockPublicPolicy: true,
|
|
79
|
-
ignorePublicAcls: false,
|
|
80
|
-
restrictPublicBuckets: true
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', props);
|
|
85
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
86
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
87
|
-
PublicAccessBlockConfiguration: {
|
|
88
|
-
BlockPublicAcls: false,
|
|
89
|
-
BlockPublicPolicy: true,
|
|
90
|
-
IgnorePublicAcls: false,
|
|
91
|
-
RestrictPublicBuckets: true
|
|
92
|
-
},
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
test('check existing bucket', () => {
|
|
96
|
-
const stack = new cdk.Stack();
|
|
97
|
-
const existingBucket = new s3.Bucket(stack, 'my-bucket', {
|
|
98
|
-
bucketName: 'my-bucket'
|
|
99
|
-
});
|
|
100
|
-
const props = {
|
|
101
|
-
existingBucketObj: existingBucket
|
|
102
|
-
};
|
|
103
|
-
new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', props);
|
|
104
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
105
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
106
|
-
BucketName: "my-bucket"
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
test('check exception for Missing existingObj from props for deploy = false', () => {
|
|
110
|
-
const stack = new cdk.Stack();
|
|
111
|
-
try {
|
|
112
|
-
new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {});
|
|
113
|
-
}
|
|
114
|
-
catch (e) {
|
|
115
|
-
expect(e).toBeInstanceOf(Error);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
test('check properties', () => {
|
|
119
|
-
const stack = new cdk.Stack();
|
|
120
|
-
const construct = deploy(stack);
|
|
121
|
-
expect(construct.cloudFrontWebDistribution).toBeDefined();
|
|
122
|
-
expect(construct.s3Bucket).toBeDefined();
|
|
123
|
-
});
|
|
124
|
-
test("Confirm CheckS3Props is called", () => {
|
|
125
|
-
// Stack
|
|
126
|
-
const stack = new cdk.Stack();
|
|
127
|
-
const testBucket = new s3.Bucket(stack, 'test-bucket', {});
|
|
128
|
-
const app = () => {
|
|
129
|
-
// Helper declaration
|
|
130
|
-
new lib_1.CloudFrontToS3(stack, "bad-s3-args", {
|
|
131
|
-
existingBucketObj: testBucket,
|
|
132
|
-
bucketProps: {
|
|
133
|
-
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
};
|
|
137
|
-
// Assertion
|
|
138
|
-
expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n');
|
|
139
|
-
});
|
|
140
|
-
test("Test existingBucketObj", () => {
|
|
141
|
-
// Stack
|
|
142
|
-
const stack = new cdk.Stack();
|
|
143
|
-
const construct = new lib_1.CloudFrontToS3(stack, "existingIBucket", {
|
|
144
|
-
existingBucketObj: s3.Bucket.fromBucketName(stack, 'mybucket', 'mybucket')
|
|
145
|
-
});
|
|
146
|
-
// Assertion
|
|
147
|
-
expect(construct.cloudFrontWebDistribution).toBeDefined();
|
|
148
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
149
|
-
template.hasResourceProperties("AWS::CloudFront::Distribution", {
|
|
150
|
-
DistributionConfig: {
|
|
151
|
-
Origins: [
|
|
152
|
-
{
|
|
153
|
-
DomainName: {
|
|
154
|
-
"Fn::Join": [
|
|
155
|
-
"",
|
|
156
|
-
[
|
|
157
|
-
"mybucket.s3.",
|
|
158
|
-
{
|
|
159
|
-
Ref: "AWS::Region"
|
|
160
|
-
},
|
|
161
|
-
".",
|
|
162
|
-
{
|
|
163
|
-
Ref: "AWS::URLSuffix"
|
|
164
|
-
}
|
|
165
|
-
]
|
|
166
|
-
]
|
|
167
|
-
},
|
|
168
|
-
Id: "existingIBucketCloudFrontDistributionOrigin1D5849125",
|
|
169
|
-
OriginAccessControlId: { "Fn::GetAtt": ["existingIBucketCloudFrontOacEB42E98F", "Id"] },
|
|
170
|
-
S3OriginConfig: {}
|
|
171
|
-
}
|
|
172
|
-
]
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
test('test cloudfront with custom domain names', () => {
|
|
177
|
-
const stack = new cdk.Stack();
|
|
178
|
-
const certificate = acm.Certificate.fromCertificateArn(stack, 'Cert', 'arn:${Aws.PARTITION}:acm:us-east-1:123456789012:certificate/11112222-3333-1234-1234-123456789012');
|
|
179
|
-
const props = {
|
|
180
|
-
cloudFrontDistributionProps: {
|
|
181
|
-
domainNames: ['mydomains'],
|
|
182
|
-
certificate
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', props);
|
|
186
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
187
|
-
template.hasResourceProperties("AWS::CloudFront::Distribution", {
|
|
188
|
-
DistributionConfig: {
|
|
189
|
-
Aliases: [
|
|
190
|
-
"mydomains"
|
|
191
|
-
]
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
test('Cloudfront logging bucket with destroy removal policy and auto delete objects', () => {
|
|
196
|
-
const stack = new cdk.Stack();
|
|
197
|
-
const cloudfrontLogBucketName = 'cf-log-bucket';
|
|
198
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
199
|
-
cloudFrontLoggingBucketProps: {
|
|
200
|
-
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
201
|
-
autoDeleteObjects: true,
|
|
202
|
-
bucketName: cloudfrontLogBucketName
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
206
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
207
|
-
OwnershipControls: { Rules: [{ ObjectOwnership: "ObjectWriter" }] },
|
|
208
|
-
BucketName: cloudfrontLogBucketName,
|
|
209
|
-
});
|
|
210
|
-
template.hasResourceProperties("Custom::S3AutoDeleteObjects", {
|
|
211
|
-
ServiceToken: {
|
|
212
|
-
"Fn::GetAtt": [
|
|
213
|
-
"CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F",
|
|
214
|
-
"Arn"
|
|
215
|
-
]
|
|
216
|
-
},
|
|
217
|
-
BucketName: {
|
|
218
|
-
Ref: "cloudfronts3CloudfrontLoggingBucket5B845143"
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
test('s3 bucket with one content bucket and no access logging of CONTENT bucket', () => {
|
|
223
|
-
const stack = new cdk.Stack();
|
|
224
|
-
const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
225
|
-
bucketProps: {
|
|
226
|
-
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
227
|
-
},
|
|
228
|
-
logS3AccessLogs: false
|
|
229
|
-
});
|
|
230
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
231
|
-
// Content bucket+Cloudfront Logs bucket+
|
|
232
|
-
// Access Log bucket for Cloudfront Logs bucket = 3 buckets
|
|
233
|
-
template.resourceCountIs("AWS::S3::Bucket", 3);
|
|
234
|
-
expect(construct.s3LoggingBucket).toEqual(undefined);
|
|
235
|
-
});
|
|
236
|
-
test('CloudFront origin path present when provided', () => {
|
|
237
|
-
const stack = new cdk.Stack();
|
|
238
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
239
|
-
originPath: '/testPath'
|
|
240
|
-
});
|
|
241
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
242
|
-
template.hasResourceProperties("AWS::CloudFront::Distribution", {
|
|
243
|
-
DistributionConfig: {
|
|
244
|
-
Origins: [
|
|
245
|
-
{
|
|
246
|
-
OriginPath: "/testPath",
|
|
247
|
-
}
|
|
248
|
-
]
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
test('CloudFront origin path should not be present if not provided', () => {
|
|
253
|
-
const stack = new cdk.Stack();
|
|
254
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {});
|
|
255
|
-
defaults.expectNonexistence(stack, "AWS::CloudFront::Distribution", {
|
|
256
|
-
DistributionConfig: {
|
|
257
|
-
Origins: [
|
|
258
|
-
{
|
|
259
|
-
OriginPath: "/testPath",
|
|
260
|
-
}
|
|
261
|
-
]
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
test('Test the deployment with securityHeadersBehavior instead of HTTP security headers', () => {
|
|
266
|
-
// Initial setup
|
|
267
|
-
const stack = new aws_cdk_lib_1.Stack();
|
|
268
|
-
const cloudFrontToS3 = new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
|
|
269
|
-
insertHttpSecurityHeaders: false,
|
|
270
|
-
responseHeadersPolicyProps: {
|
|
271
|
-
securityHeadersBehavior: {
|
|
272
|
-
strictTransportSecurity: {
|
|
273
|
-
accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(63072),
|
|
274
|
-
includeSubdomains: true,
|
|
275
|
-
override: true,
|
|
276
|
-
preload: true
|
|
277
|
-
},
|
|
278
|
-
contentSecurityPolicy: {
|
|
279
|
-
contentSecurityPolicy: "upgrade-insecure-requests; default-src 'none';",
|
|
280
|
-
override: true
|
|
281
|
-
},
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
// Assertion
|
|
286
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
287
|
-
template.hasResourceProperties("AWS::CloudFront::ResponseHeadersPolicy", {
|
|
288
|
-
ResponseHeadersPolicyConfig: {
|
|
289
|
-
SecurityHeadersConfig: {
|
|
290
|
-
ContentSecurityPolicy: {
|
|
291
|
-
ContentSecurityPolicy: "upgrade-insecure-requests; default-src 'none';",
|
|
292
|
-
Override: true
|
|
293
|
-
},
|
|
294
|
-
StrictTransportSecurity: {
|
|
295
|
-
AccessControlMaxAgeSec: 63072,
|
|
296
|
-
IncludeSubdomains: true,
|
|
297
|
-
Override: true,
|
|
298
|
-
Preload: true
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
expect(cloudFrontToS3.cloudFrontFunction).toEqual(undefined);
|
|
304
|
-
});
|
|
305
|
-
test("throw exception if insertHttpSecurityHeaders and responseHeadersPolicyProps are provided", () => {
|
|
306
|
-
const stack = new cdk.Stack();
|
|
307
|
-
expect(() => {
|
|
308
|
-
new lib_1.CloudFrontToS3(stack, "test-cloudfront-s3", {
|
|
309
|
-
insertHttpSecurityHeaders: true,
|
|
310
|
-
responseHeadersPolicyProps: {
|
|
311
|
-
securityHeadersBehavior: {
|
|
312
|
-
strictTransportSecurity: {
|
|
313
|
-
accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(63072),
|
|
314
|
-
includeSubdomains: true,
|
|
315
|
-
override: false,
|
|
316
|
-
preload: true
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
}).toThrowError();
|
|
322
|
-
});
|
|
323
|
-
test("Confirm CheckCloudFrontProps is being called", () => {
|
|
324
|
-
const stack = new cdk.Stack();
|
|
325
|
-
expect(() => {
|
|
326
|
-
new lib_1.CloudFrontToS3(stack, "test-cloudfront-apigateway", {
|
|
327
|
-
insertHttpSecurityHeaders: true,
|
|
328
|
-
responseHeadersPolicyProps: {
|
|
329
|
-
securityHeadersBehavior: {
|
|
330
|
-
strictTransportSecurity: {
|
|
331
|
-
accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(63072),
|
|
332
|
-
includeSubdomains: true,
|
|
333
|
-
override: false,
|
|
334
|
-
preload: true
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
});
|
|
339
|
-
}).toThrowError('responseHeadersPolicyProps.securityHeadersBehavior can only be passed if httpSecurityHeaders is set to `false`.');
|
|
340
|
-
});
|
|
341
|
-
test("Custom resource is provisioned if encryption key is provided as bucketProp", () => {
|
|
342
|
-
const stack = new cdk.Stack();
|
|
343
|
-
const encryptionKey = new aws_kms_1.Key(stack, 'cmkKey', {
|
|
344
|
-
enableKeyRotation: true,
|
|
345
|
-
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY
|
|
346
|
-
});
|
|
347
|
-
deploy(stack, {
|
|
348
|
-
bucketProps: {
|
|
349
|
-
encryptionKey,
|
|
350
|
-
encryption: s3.BucketEncryption.KMS
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
354
|
-
// 2 Functions - our custom resource and a function created by the CDK
|
|
355
|
-
template.resourceCountIs('AWS::Lambda::Function', 2);
|
|
356
|
-
template.hasResourceProperties('AWS::Lambda::Function', {
|
|
357
|
-
Description: "Custom resource function that updates a provided key policy to allow CloudFront access.",
|
|
358
|
-
Role: {
|
|
359
|
-
"Fn::GetAtt": ["testcloudfronts3LambdaFunctionServiceRole2A43EA92", "Arn"]
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
});
|
|
363
|
-
test("Custom resource is provisioned if CMK was used to encrypt an existing bucket", () => {
|
|
364
|
-
const stack = new cdk.Stack();
|
|
365
|
-
const encryptionKey = new aws_kms_1.Key(stack, 'cmkKey', {
|
|
366
|
-
enableKeyRotation: true,
|
|
367
|
-
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY
|
|
368
|
-
});
|
|
369
|
-
const existingBucketObj = defaults.buildS3Bucket(stack, {
|
|
370
|
-
bucketProps: {
|
|
371
|
-
encryption: s3.BucketEncryption.KMS,
|
|
372
|
-
encryptionKey
|
|
373
|
-
}
|
|
374
|
-
}, 'existing-s3-bucket-encrypted-with-cmk').bucket;
|
|
375
|
-
new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
|
|
376
|
-
existingBucketObj
|
|
377
|
-
});
|
|
378
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
379
|
-
// 2 Functions - our custom resource and a function created by the CDK
|
|
380
|
-
template.resourceCountIs('AWS::Lambda::Function', 2);
|
|
381
|
-
// ensure that our Function has the correct role attached
|
|
382
|
-
template.hasResourceProperties('AWS::Lambda::Function', {
|
|
383
|
-
Description: "Custom resource function that updates a provided key policy to allow CloudFront access.",
|
|
384
|
-
Role: {
|
|
385
|
-
"Fn::GetAtt": ["testcloudfronts3LambdaFunctionServiceRole2A43EA92", "Arn"]
|
|
386
|
-
}
|
|
387
|
-
});
|
|
388
|
-
});
|
|
389
|
-
test("Custom resource is not provisioned if encryption key is not provided as bucketProp", () => {
|
|
390
|
-
const stack = new cdk.Stack();
|
|
391
|
-
deploy(stack);
|
|
392
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
393
|
-
template.resourceCountIs('AWS::Lambda::Function', 0);
|
|
394
|
-
});
|
|
395
|
-
test("Custom resource is not provisioned if CMK was not used to encrypt an existing bucket", () => {
|
|
396
|
-
const stack = new cdk.Stack();
|
|
397
|
-
const existingBucketObj = defaults.buildS3Bucket(stack, {}, 'existing-s3-bucket-encrypted-with-cmk').bucket;
|
|
398
|
-
new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
|
|
399
|
-
existingBucketObj
|
|
400
|
-
});
|
|
401
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
402
|
-
template.resourceCountIs('AWS::Lambda::Function', 0);
|
|
403
|
-
});
|
|
404
|
-
test("HttpOrigin is provisioned if a static website bucket is used", () => {
|
|
405
|
-
const stack = new cdk.Stack();
|
|
406
|
-
const blockPublicAccess = false;
|
|
407
|
-
const props = {
|
|
408
|
-
bucketProps: {
|
|
409
|
-
enforceSSL: false,
|
|
410
|
-
publicReadAccess: true, // <-- required for isWebsite
|
|
411
|
-
blockPublicAccess: {
|
|
412
|
-
blockPublicAcls: blockPublicAccess,
|
|
413
|
-
restrictPublicBuckets: blockPublicAccess,
|
|
414
|
-
blockPublicPolicy: blockPublicAccess,
|
|
415
|
-
ignorePublicAcls: blockPublicAccess
|
|
416
|
-
},
|
|
417
|
-
websiteIndexDocument: "index.html" // <-- required for isWebsite
|
|
418
|
-
},
|
|
419
|
-
insertHttpSecurityHeaders: false
|
|
420
|
-
};
|
|
421
|
-
const construct = new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', props);
|
|
422
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
423
|
-
// Assert resources
|
|
424
|
-
template.resourceCountIs('AWS::CloudFront::OriginAccessControl', 0);
|
|
425
|
-
template.hasResourceProperties('AWS::CloudFront::Distribution', {
|
|
426
|
-
DistributionConfig: {
|
|
427
|
-
Origins: [
|
|
428
|
-
{
|
|
429
|
-
CustomOriginConfig: {
|
|
430
|
-
OriginProtocolPolicy: "http-only"
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
]
|
|
434
|
-
}
|
|
435
|
-
});
|
|
436
|
-
template.resourceCountIs('AWS::CloudFront::OriginAccessIdentity', 0);
|
|
437
|
-
// Assert pattern properties (output props)
|
|
438
|
-
expect(construct.originAccessControl).toBe(undefined);
|
|
439
|
-
});
|
|
440
|
-
test("OAC is provisioned in all other cases", () => {
|
|
441
|
-
const stack = new cdk.Stack();
|
|
442
|
-
const construct = new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {});
|
|
443
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
444
|
-
// Assert resources
|
|
445
|
-
template.resourceCountIs('AWS::CloudFront::OriginAccessControl', 1);
|
|
446
|
-
template.resourceCountIs('AWS::CloudFront::OriginAccessIdentity', 0);
|
|
447
|
-
// Assert pattern properties (output props)
|
|
448
|
-
expect(construct.originAccessControl).not.toBe(undefined);
|
|
449
|
-
});
|
|
450
|
-
test("If a customer provides their own httpOrigin, or other origin type, use that one", () => {
|
|
451
|
-
const stack = new cdk.Stack();
|
|
452
|
-
const blockPublicAccess = false;
|
|
453
|
-
const props = {
|
|
454
|
-
bucketProps: {
|
|
455
|
-
enforceSSL: false,
|
|
456
|
-
publicReadAccess: true, // <-- required for isWebsite
|
|
457
|
-
blockPublicAccess: {
|
|
458
|
-
blockPublicAcls: blockPublicAccess,
|
|
459
|
-
restrictPublicBuckets: blockPublicAccess,
|
|
460
|
-
blockPublicPolicy: blockPublicAccess,
|
|
461
|
-
ignorePublicAcls: blockPublicAccess
|
|
462
|
-
},
|
|
463
|
-
websiteIndexDocument: "index.html" // <-- required for isWebsite
|
|
464
|
-
},
|
|
465
|
-
insertHttpSecurityHeaders: false,
|
|
466
|
-
cloudFrontDistributionProps: {
|
|
467
|
-
defaultBehavior: {
|
|
468
|
-
origin: new origins.HttpOrigin('example.com', {
|
|
469
|
-
originId: 'custom-http-origin-for-testing'
|
|
470
|
-
})
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
};
|
|
474
|
-
new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', props);
|
|
475
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
476
|
-
// Assert resources
|
|
477
|
-
template.hasResourceProperties('AWS::CloudFront::Distribution', {
|
|
478
|
-
DistributionConfig: {
|
|
479
|
-
Origins: [
|
|
480
|
-
{
|
|
481
|
-
DomainName: "example.com",
|
|
482
|
-
Id: "custom-http-origin-for-testing"
|
|
483
|
-
}
|
|
484
|
-
]
|
|
485
|
-
}
|
|
486
|
-
});
|
|
487
|
-
});
|
|
488
|
-
test('Test that we do not create an Access Log bucket for CF logs if one is provided', () => {
|
|
489
|
-
const stack = new cdk.Stack();
|
|
490
|
-
const cfS3AccessLogBucket = new s3.Bucket(stack, 'cf-s3-access-logs');
|
|
491
|
-
new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
|
|
492
|
-
cloudFrontLoggingBucketProps: {
|
|
493
|
-
serverAccessLogsBucket: cfS3AccessLogBucket
|
|
494
|
-
}
|
|
495
|
-
});
|
|
496
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
497
|
-
template.resourceCountIs("AWS::S3::Bucket", 4);
|
|
498
|
-
});
|
|
499
|
-
// =====================
|
|
500
|
-
// S3 Content Bucket Access Logs Bucket
|
|
501
|
-
// =====================
|
|
502
|
-
test('Providing loggingBucketProps and existingLoggingBucket is an error', () => {
|
|
503
|
-
const stack = new cdk.Stack();
|
|
504
|
-
const logBucket = new s3.Bucket(stack, 'log-bucket', {});
|
|
505
|
-
const app = () => {
|
|
506
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
507
|
-
bucketProps: {
|
|
508
|
-
serverAccessLogsBucket: logBucket,
|
|
509
|
-
},
|
|
510
|
-
loggingBucketProps: {
|
|
511
|
-
bucketName: 'anything'
|
|
512
|
-
}
|
|
513
|
-
});
|
|
514
|
-
};
|
|
515
|
-
expect(app).toThrowError(/Error - bothlog bucket props and an existing log bucket were provided.\n/);
|
|
516
|
-
});
|
|
517
|
-
test('Providing existingLoggingBucket and logS3AccessLogs=false is an error', () => {
|
|
518
|
-
const stack = new cdk.Stack();
|
|
519
|
-
const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
|
|
520
|
-
const app = () => {
|
|
521
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
522
|
-
bucketProps: {
|
|
523
|
-
serverAccessLogsBucket: logBucket,
|
|
524
|
-
},
|
|
525
|
-
logS3AccessLogs: false
|
|
526
|
-
});
|
|
527
|
-
};
|
|
528
|
-
expect(app).toThrowError(/Error - logS3AccessLogs is false, but a log bucket was provided in bucketProps.\n/);
|
|
529
|
-
});
|
|
530
|
-
test('Providing loggingBucketProps and logS3AccessLogs=false is an error', () => {
|
|
531
|
-
const stack = new cdk.Stack();
|
|
532
|
-
const app = () => {
|
|
533
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
534
|
-
loggingBucketProps: {
|
|
535
|
-
bucketName: 'anything'
|
|
536
|
-
},
|
|
537
|
-
logS3AccessLogs: false
|
|
538
|
-
});
|
|
539
|
-
};
|
|
540
|
-
// NOTE: This error is thrown by CheckS3Props(), not CheckConstructSpecificProps()
|
|
541
|
-
expect(app).toThrowError(/Error - If logS3AccessLogs is false, supplying loggingBucketProps or existingLoggingBucketObj is invalid.\n/);
|
|
542
|
-
});
|
|
543
|
-
// test('No new loggingBucket is created if existingLoggingBucket is supplied', () => {
|
|
544
|
-
test('loggingBucketProps is supplied is integrated into architecture correctly', () => {
|
|
545
|
-
const stack = new cdk.Stack();
|
|
546
|
-
const testName = "test-name";
|
|
547
|
-
const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
548
|
-
bucketProps: {
|
|
549
|
-
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
550
|
-
},
|
|
551
|
-
loggingBucketProps: {
|
|
552
|
-
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
553
|
-
autoDeleteObjects: true,
|
|
554
|
-
bucketName: testName
|
|
555
|
-
}
|
|
556
|
-
});
|
|
557
|
-
expect(construct.s3LoggingBucket).toBeDefined();
|
|
558
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
559
|
-
template.resourceCountIs("AWS::S3::Bucket", 4);
|
|
560
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
561
|
-
BucketName: testName
|
|
562
|
-
});
|
|
563
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
564
|
-
LoggingConfiguration: {
|
|
565
|
-
DestinationBucketName: {
|
|
566
|
-
Ref: "cloudfronts3S3LoggingBucket52EEB708"
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
});
|
|
570
|
-
});
|
|
571
|
-
test('bucketProps:serverAccessLogsBucket is supplied is integrated into architecture correctly', () => {
|
|
572
|
-
const testName = 'some-name';
|
|
573
|
-
const stack = new cdk.Stack();
|
|
574
|
-
const logBucket = new s3.Bucket(stack, 'test-log', {
|
|
575
|
-
bucketName: testName,
|
|
576
|
-
});
|
|
577
|
-
const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
578
|
-
bucketProps: {
|
|
579
|
-
serverAccessLogsBucket: logBucket,
|
|
580
|
-
},
|
|
581
|
-
});
|
|
582
|
-
expect(construct.s3LoggingBucket).toBeDefined();
|
|
583
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
584
|
-
template.resourceCountIs("AWS::S3::Bucket", 4);
|
|
585
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
586
|
-
LoggingConfiguration: {
|
|
587
|
-
DestinationBucketName: {
|
|
588
|
-
Ref: "testlogE88B4C6B"
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
});
|
|
592
|
-
});
|
|
593
|
-
// =====================
|
|
594
|
-
// CloudFront Log Bucket
|
|
595
|
-
// =====================
|
|
596
|
-
test('Providing cloudFrontLoggingBucketProps and a log bucket in cloudFrontDistrbutionProps is an error', () => {
|
|
597
|
-
const stack = new cdk.Stack();
|
|
598
|
-
const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
|
|
599
|
-
const app = () => {
|
|
600
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
601
|
-
cloudFrontDistributionProps: {
|
|
602
|
-
logBucket
|
|
603
|
-
},
|
|
604
|
-
cloudFrontLoggingBucketProps: {
|
|
605
|
-
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
606
|
-
autoDeleteObjects: true
|
|
607
|
-
}
|
|
608
|
-
});
|
|
609
|
-
};
|
|
610
|
-
expect(app).toThrowError();
|
|
611
|
-
});
|
|
612
|
-
test('cloudFrontLoggingBucketProps are used correctly', () => {
|
|
613
|
-
const stack = new cdk.Stack();
|
|
614
|
-
const testName = "test-name";
|
|
615
|
-
const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
616
|
-
cloudFrontLoggingBucketProps: {
|
|
617
|
-
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
618
|
-
autoDeleteObjects: true,
|
|
619
|
-
bucketName: testName
|
|
620
|
-
}
|
|
621
|
-
});
|
|
622
|
-
expect(construct.cloudFrontLoggingBucket).toBeDefined();
|
|
623
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
624
|
-
template.resourceCountIs("AWS::S3::Bucket", 4);
|
|
625
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
626
|
-
BucketName: testName
|
|
627
|
-
});
|
|
628
|
-
});
|
|
629
|
-
test('Logging disabled in CloudFront props is handled correctly', () => {
|
|
630
|
-
const stack = new cdk.Stack();
|
|
631
|
-
const construct = deploy(stack, { cloudFrontDistributionProps: { enableLogging: false } });
|
|
632
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
633
|
-
// Only the content bucket and it S3 Access Log bucket (no Cloudfront log bucket)
|
|
634
|
-
template.resourceCountIs("AWS::S3::Bucket", 2);
|
|
635
|
-
// No logging is configured
|
|
636
|
-
template.resourcePropertiesCountIs("AWS::CloudFront::Distribution", {
|
|
637
|
-
DistributionConfig: {
|
|
638
|
-
Logging: assertions_1.Match.anyValue()
|
|
639
|
-
}
|
|
640
|
-
}, 0);
|
|
641
|
-
expect(construct.cloudFrontLoggingBucket === undefined);
|
|
642
|
-
});
|
|
643
|
-
test('No new CloudFrontLoggingBucket is created if cloudFrontLoggingBucketProps:logBucket is supplied', () => {
|
|
644
|
-
const testName = 'random-value';
|
|
645
|
-
const stack = new cdk.Stack();
|
|
646
|
-
const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {
|
|
647
|
-
bucketName: testName
|
|
648
|
-
});
|
|
649
|
-
// const construct =
|
|
650
|
-
const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
651
|
-
cloudFrontDistributionProps: {
|
|
652
|
-
logBucket
|
|
653
|
-
},
|
|
654
|
-
});
|
|
655
|
-
expect(construct.cloudFrontLoggingBucket).toBeDefined();
|
|
656
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
657
|
-
// Content bucket, Content bucket S3 Access Log bucket, cloudfront log bucket
|
|
658
|
-
template.resourceCountIs("AWS::S3::Bucket", 3);
|
|
659
|
-
// Ensure our existing bucket has been used for cloudfront logging
|
|
660
|
-
template.hasResourceProperties("AWS::CloudFront::Distribution", {
|
|
661
|
-
DistributionConfig: {
|
|
662
|
-
Logging: {
|
|
663
|
-
Bucket: {
|
|
664
|
-
"Fn::GetAtt": [
|
|
665
|
-
"cloudfrontlogbucketDF7058FB",
|
|
666
|
-
"RegionalDomainName"
|
|
667
|
-
]
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
});
|
|
672
|
-
});
|
|
673
|
-
// =====================
|
|
674
|
-
// CloudFront Logs Bucket Access Log Bucket
|
|
675
|
-
// =====================
|
|
676
|
-
test('Providing cloudFrontLoggingBucketAccessLogBucketProps and cloudFrontLoggingBucketProps:serverAccessLogsBucket is an error', () => {
|
|
677
|
-
const stack = new cdk.Stack();
|
|
678
|
-
const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
|
|
679
|
-
const app = () => {
|
|
680
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
681
|
-
cloudFrontLoggingBucketProps: {
|
|
682
|
-
serverAccessLogsBucket: logBucket,
|
|
683
|
-
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
684
|
-
autoDeleteObjects: true
|
|
685
|
-
},
|
|
686
|
-
cloudFrontLoggingBucketAccessLogBucketProps: {
|
|
687
|
-
bucketName: 'specfic-name-is-inconsequential'
|
|
688
|
-
}
|
|
689
|
-
});
|
|
690
|
-
};
|
|
691
|
-
expect(app).toThrowError(/Error - an existing CloudFront log bucket S3 access log bucket and cloudFrontLoggingBucketAccessLogBucketProps were provided\n/);
|
|
692
|
-
});
|
|
693
|
-
test('Providing cloudFrontLoggingBucketAccessLogBucketProps and logCloudFrontAccessLog=false is an error', () => {
|
|
694
|
-
const stack = new cdk.Stack();
|
|
695
|
-
const app = () => {
|
|
696
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
697
|
-
logCloudFrontAccessLog: false,
|
|
698
|
-
cloudFrontLoggingBucketAccessLogBucketProps: {
|
|
699
|
-
bucketName: 'specfic-name-is-inconsequential'
|
|
700
|
-
}
|
|
701
|
-
});
|
|
702
|
-
};
|
|
703
|
-
expect(app).toThrowError(/Error - cloudFrontLoggingBucketAccessLogBucketProps were provided but logCloudFrontAccessLog was false\n/);
|
|
704
|
-
});
|
|
705
|
-
test('Providing logCloudFrontAccessLog=false and cloudFrontLoggingBucketProps:serverAccessLogsBucket is an error', () => {
|
|
706
|
-
const stack = new cdk.Stack();
|
|
707
|
-
const logBucket = new s3.Bucket(stack, 'cloudfront-log-bucket', {});
|
|
708
|
-
const app = () => {
|
|
709
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
710
|
-
cloudFrontLoggingBucketProps: {
|
|
711
|
-
serverAccessLogsBucket: logBucket,
|
|
712
|
-
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
713
|
-
autoDeleteObjects: true
|
|
714
|
-
},
|
|
715
|
-
logCloudFrontAccessLog: false,
|
|
716
|
-
});
|
|
717
|
-
};
|
|
718
|
-
expect(app).toThrowError(/Error - props.cloudFrontLoggingBucketProps.serverAccessLogsBucket was provided but logCloudFrontAccessLog was false\n/);
|
|
719
|
-
});
|
|
720
|
-
test('cloudFrontLoggingBucketAccessLogBucketProps are used correctly', () => {
|
|
721
|
-
const stack = new cdk.Stack();
|
|
722
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
723
|
-
cloudFrontLoggingBucketAccessLogBucketProps: {
|
|
724
|
-
websiteErrorDocument: 'placeholder',
|
|
725
|
-
websiteIndexDocument: 'placeholde-two'
|
|
726
|
-
}
|
|
727
|
-
});
|
|
728
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
729
|
-
// Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
|
|
730
|
-
template.resourceCountIs("AWS::S3::Bucket", 4);
|
|
731
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
732
|
-
WebsiteConfiguration: {
|
|
733
|
-
ErrorDocument: 'placeholder',
|
|
734
|
-
IndexDocument: 'placeholde-two'
|
|
735
|
-
}
|
|
736
|
-
});
|
|
737
|
-
});
|
|
738
|
-
test('If existing CloudFront Log bucket S3 Access Logging bucket is provided, it is used correctly', () => {
|
|
739
|
-
const stack = new cdk.Stack();
|
|
740
|
-
const testName = 'cf-log-s3-log';
|
|
741
|
-
const cfLogS3AccessLogBucket = new s3.Bucket(stack, 'cf-log-s3-access-log-bucket', {
|
|
742
|
-
bucketName: testName
|
|
743
|
-
});
|
|
744
|
-
new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
745
|
-
cloudFrontLoggingBucketProps: {
|
|
746
|
-
serverAccessLogsBucket: cfLogS3AccessLogBucket
|
|
747
|
-
}
|
|
748
|
-
});
|
|
749
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
750
|
-
// Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
|
|
751
|
-
template.resourceCountIs("AWS::S3::Bucket", 4);
|
|
752
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
753
|
-
BucketName: testName
|
|
754
|
-
});
|
|
755
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
756
|
-
LoggingConfiguration: {
|
|
757
|
-
DestinationBucketName: {
|
|
758
|
-
Ref: "cflogs3accesslogbucketDE374C27"
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
});
|
|
762
|
-
});
|
|
763
|
-
test('cloudFrontLoggingBucketAccessLogBucket property is set correctly', () => {
|
|
764
|
-
const stack = new cdk.Stack();
|
|
765
|
-
const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
766
|
-
cloudFrontLoggingBucketAccessLogBucketProps: {
|
|
767
|
-
websiteErrorDocument: 'placeholder',
|
|
768
|
-
websiteIndexDocument: 'placeholde-two'
|
|
769
|
-
}
|
|
770
|
-
});
|
|
771
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
772
|
-
// Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
|
|
773
|
-
template.resourceCountIs("AWS::S3::Bucket", 4);
|
|
774
|
-
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
775
|
-
WebsiteConfiguration: {
|
|
776
|
-
ErrorDocument: 'placeholder',
|
|
777
|
-
IndexDocument: 'placeholde-two'
|
|
778
|
-
}
|
|
779
|
-
});
|
|
780
|
-
expect(construct.cloudFrontLoggingBucketAccessLogBucket).toBeDefined();
|
|
781
|
-
expect(construct.cloudFrontLoggingBucketAccessLogBucket.bucketName).toBeDefined();
|
|
782
|
-
});
|
|
783
|
-
test('logCloudFrontAccessLog property is used correctly', () => {
|
|
784
|
-
const stack = new cdk.Stack();
|
|
785
|
-
const construct = new lib_1.CloudFrontToS3(stack, 'cloudfront-s3', {
|
|
786
|
-
logCloudFrontAccessLog: false
|
|
787
|
-
});
|
|
788
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
789
|
-
// Content Bucket, Content Bucket S3 Access Log Bucket, CloudFront Log Bucket, CloudFront Log Bucket S3 Access Log Bucket
|
|
790
|
-
template.resourceCountIs("AWS::S3::Bucket", 3);
|
|
791
|
-
expect(construct.cloudFrontLoggingBucket).toBeDefined();
|
|
792
|
-
expect(construct.cloudFrontLoggingBucketAccessLogBucket).not.toBeDefined();
|
|
793
|
-
});
|
|
794
|
-
test('additionalBehaviors have correct origin', () => {
|
|
795
|
-
const stack = new cdk.Stack();
|
|
796
|
-
const additionalBucket = defaults.CreateScrapBucket(stack, "scrapBucket", {
|
|
797
|
-
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
|
|
798
|
-
autoDeleteObjects: true,
|
|
799
|
-
});
|
|
800
|
-
const originAccessControl = new aws_cloudfront_1.CfnOriginAccessControl(stack, 'CloudFrontOac', {
|
|
801
|
-
originAccessControlConfig: {
|
|
802
|
-
name: defaults.generatePhysicalOacName('aws-cloudfront-s3-', [__filename]),
|
|
803
|
-
originAccessControlOriginType: 's3',
|
|
804
|
-
signingBehavior: 'always',
|
|
805
|
-
signingProtocol: 'sigv4',
|
|
806
|
-
description: 'Origin access control provisioned by aws-cloudfront-s3'
|
|
807
|
-
}
|
|
808
|
-
});
|
|
809
|
-
const additionalOrigin = new defaults.S3OacOrigin(additionalBucket, {
|
|
810
|
-
originAccessControl
|
|
811
|
-
});
|
|
812
|
-
new lib_1.CloudFrontToS3(stack, 'test-cloudfront-s3', {
|
|
813
|
-
cloudFrontDistributionProps: {
|
|
814
|
-
additionalBehaviors: {
|
|
815
|
-
'/assets/public/*': {
|
|
816
|
-
origin: additionalOrigin,
|
|
817
|
-
cachePolicy: aws_cloudfront_1.CachePolicy.CACHING_DISABLED,
|
|
818
|
-
},
|
|
819
|
-
'ngsw.json': {
|
|
820
|
-
cachePolicy: aws_cloudfront_1.CachePolicy.CACHING_DISABLED,
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
});
|
|
825
|
-
const template = assertions_1.Template.fromStack(stack);
|
|
826
|
-
template.hasResourceProperties("AWS::CloudFront::Distribution", {
|
|
827
|
-
DistributionConfig: {
|
|
828
|
-
CacheBehaviors: [
|
|
829
|
-
{
|
|
830
|
-
CachePolicyId: "4135ea2d-6df8-44a3-9df3-4b5a84be39ad",
|
|
831
|
-
Compress: true,
|
|
832
|
-
PathPattern: "/assets/public/*",
|
|
833
|
-
TargetOriginId: "testcloudfronts3CloudFrontDistributionOrigin21D78391C",
|
|
834
|
-
ViewerProtocolPolicy: "allow-all"
|
|
835
|
-
},
|
|
836
|
-
{
|
|
837
|
-
CachePolicyId: "4135ea2d-6df8-44a3-9df3-4b5a84be39ad",
|
|
838
|
-
Compress: true,
|
|
839
|
-
PathPattern: "ngsw.json",
|
|
840
|
-
TargetOriginId: "testcloudfronts3CloudFrontDistributionOrigin124051039",
|
|
841
|
-
ViewerProtocolPolicy: "allow-all"
|
|
842
|
-
}
|
|
843
|
-
],
|
|
844
|
-
}
|
|
845
|
-
});
|
|
846
|
-
});
|
|
847
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5jbG91ZGZyb250LXMzLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0ZXN0LmNsb3VkZnJvbnQtczMudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7O0dBV0c7O0FBRUgsdURBQXlEO0FBQ3pELHlDQUF5QztBQUN6QyxtQ0FBbUM7QUFDbkMsNkNBQTZEO0FBQzdELGdDQUE2RDtBQUM3RCwwREFBMEQ7QUFDMUQsMkRBQTJEO0FBQzNELGlEQUEwQztBQUMxQyw4REFBOEQ7QUFDOUQsK0RBQWlGO0FBRWpGLFNBQVMsTUFBTSxDQUFDLEtBQWdCLEVBQUUsS0FBMkI7SUFDM0QsT0FBTyxJQUFJLG9CQUFjLENBQUMsS0FBSyxFQUFFLG9CQUFvQixFQUFFO1FBQ3JELFdBQVcsRUFBRTtZQUNYLGFBQWEsRUFBRSxHQUFHLENBQUMsYUFBYSxDQUFDLE9BQU87U0FDekM7UUFDRCxHQUFHLEtBQUs7S0FDVCxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxDQUFDLDZDQUE2QyxFQUFFLEdBQUcsRUFBRTtJQUN2RCxNQUFNLEtBQUssR0FBRyxJQUFJLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM5QixNQUFNLFNBQVMsR0FBRyxJQUFJLG9CQUFjLENBQUMsS0FBSyxFQUFFLG9CQUFvQixFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRXRFLE1BQU0sQ0FBQyxTQUFTLENBQUMseUJBQXlCLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUMxRCxNQUFNLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDbkQsTUFBTSxDQUFDLFNBQVMsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3hELE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDekMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FB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RUFBRTtRQUNsRSxtQkFBbUI7S0FDcEIsQ0FBQyxDQUFDO0lBRUgsSUFBSSxvQkFBYyxDQUFDLEtBQUssRUFBRSxvQkFBb0IsRUFBRTtRQUM5QywyQkFBMkIsRUFBRTtZQUMzQixtQkFBbUIsRUFBRTtnQkFDbkIsa0JBQWtCLEVBQUU7b0JBQ2xCLE1BQU0sRUFBRSxnQkFBZ0I7b0JBQ3hCLFdBQVcsRUFBRSw0QkFBVyxDQUFDLGdCQUFnQjtpQkFDMUM7Z0JBQ0QsV0FBVyxFQUFFO29CQUNYLFdBQVcsRUFBRSw0QkFBVyxDQUFDLGdCQUFnQjtpQkFDMUM7YUFDRjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0MsUUFBUSxDQUFDLHFCQUFxQixDQUFDLCtCQUErQixFQUFFO1FBQzlELGtCQUFrQixFQUFFO1lBQ2xCLGNBQWMsRUFBRTtnQkFDZDtvQkFDRSxhQUFhLEVBQUUsc0NBQXNDO29CQUNyRCxRQUFRLEVBQUUsSUFBSTtvQkFDZCxXQUFXLEVBQUUsa0JBQWtCO29CQUMvQixjQUFjLEVBQUUsdURBQXVEO29CQUN2RSxvQkFBb0IsRUFBRSxXQUFXO2lCQUNsQztnQkFDRDtvQkFDRSxhQUFhLEVBQUUsc0NBQXNDO29CQUNyRCxRQUFRLEVBQUUsSUFBSTtvQkFDZCxXQUFXLEVBQUUsV0FBVztvQkFDeEIsY0FBYyxFQUFFLHVEQUF1RDtvQkFDdkUsb0JBQW9CLEVBQUUsV0FBVztpQkFDbEM7YUFDRjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKS4gWW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogIHdpdGggdGhlIExpY2Vuc2UuIEEgY29weSBvZiB0aGUgTGljZW5zZSBpcyBsb2NhdGVkIGF0XG4gKlxuICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiAgb3IgaW4gdGhlICdsaWNlbnNlJyBmaWxlIGFjY29tcGFueWluZyB0aGlzIGZpbGUuIFRoaXMgZmlsZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAnQVMgSVMnIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVNcbiAqICBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBleHByZXNzIG9yIGltcGxpZWQuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xuICogIGFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBNYXRjaCwgVGVtcGxhdGUgfSBmcm9tIFwiYXdzLWNkay1saWIvYXNzZXJ0aW9uc1wiO1xuaW1wb3J0ICogYXMgczMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCAqIGFzIGNkayBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IER1cmF0aW9uLCBSZW1vdmFsUG9saWN5LCBTdGFjayB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHsgQ2xvdWRGcm9udFRvUzMsIENsb3VkRnJvbnRUb1MzUHJvcHMgfSBmcm9tIFwiLi4vbGliXCI7XG5pbXBvcnQgKiBhcyBhY20gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNlcnRpZmljYXRlbWFuYWdlcic7XG5pbXBvcnQgKiBhcyBkZWZhdWx0cyBmcm9tICdAYXdzLXNvbHV0aW9ucy1jb25zdHJ1Y3RzL2NvcmUnO1xuaW1wb3J0IHsgS2V5IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1rbXNcIjtcbmltcG9ydCAqIGFzIG9yaWdpbnMgZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnQtb3JpZ2lucyc7XG5pbXBvcnQgeyBDYWNoZVBvbGljeSwgQ2ZuT3JpZ2luQWNjZXNzQ29udHJvbCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udFwiO1xuXG5mdW5jdGlvbiBkZXBsb3koc3RhY2s6IGNkay5TdGFjaywgcHJvcHM/OiBDbG91ZEZyb250VG9TM1Byb3BzKSB7XG4gIHJldHVybiBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCB7XG4gICAgYnVja2V0UHJvcHM6IHtcbiAgICAgIHJlbW92YWxQb2xpY3k6IGNkay5SZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgfSxcbiAgICAuLi5wcm9wc1xuICB9KTtcbn1cblxudGVzdCgnY29uc3RydWN0IGRlZmF1bHRzIHNldCBwcm9wZXJ0aWVzIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGNvbnN0cnVjdCA9IG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1zMycsIHt9KTtcblxuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRXZWJEaXN0cmlidXRpb24pLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuY2xvdWRGcm9udEZ1bmN0aW9uKS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRMb2dnaW5nQnVja2V0KS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LnMzQnVja2V0KS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoY29uc3RydWN0LnMzTG9nZ2luZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5zM0J1Y2tldEludGVyZmFjZSkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5vcmlnaW5BY2Nlc3NDb250cm9sKS50b0JlRGVmaW5lZCgpO1xufSk7XG5cbnRlc3QoJ2NoZWNrIHMzQnVja2V0IGRlZmF1bHQgZW5jcnlwdGlvbicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGRlcGxveShzdGFjayk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlMzOjpCdWNrZXQnLCB7XG4gICAgQnVja2V0RW5jcnlwdGlvbjoge1xuICAgICAgU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uOiBbe1xuICAgICAgICBTZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdDoge1xuICAgICAgICAgIFNTRUFsZ29yaXRobTogXCJBRVMyNTZcIlxuICAgICAgICB9XG4gICAgICB9XVxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdCgnY2hlY2sgczNCdWNrZXQgcHVibGljIGFjY2VzcyBibG9jayBjb25maWd1cmF0aW9uJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgZGVwbG95KHN0YWNrKTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6UzM6OkJ1Y2tldCcsIHtcbiAgICBQdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb246IHtcbiAgICAgIEJsb2NrUHVibGljQWNsczogdHJ1ZSxcbiAgICAgIEJsb2NrUHVibGljUG9saWN5OiB0cnVlLFxuICAgICAgSWdub3JlUHVibGljQWNsczogdHJ1ZSxcbiAgICAgIFJlc3RyaWN0UHVibGljQnVja2V0czogdHJ1ZVxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdCgndGVzdCBzM0J1Y2tldCBvdmVycmlkZSBwdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb24nLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IHByb3BzOiBDbG91ZEZyb250VG9TM1Byb3BzID0ge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICBibG9ja1B1YmxpY0FjY2Vzczoge1xuICAgICAgICBibG9ja1B1YmxpY0FjbHM6IGZhbHNlLFxuICAgICAgICBibG9ja1B1YmxpY1BvbGljeTogdHJ1ZSxcbiAgICAgICAgaWdub3JlUHVibGljQWNsczogZmFsc2UsXG4gICAgICAgIHJlc3RyaWN0UHVibGljQnVja2V0czogdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCBwcm9wcyk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIFB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvbjoge1xuICAgICAgQmxvY2tQdWJsaWNBY2xzOiBmYWxzZSxcbiAgICAgIEJsb2NrUHVibGljUG9saWN5OiB0cnVlLFxuICAgICAgSWdub3JlUHVibGljQWNsczogZmFsc2UsXG4gICAgICBSZXN0cmljdFB1YmxpY0J1Y2tldHM6IHRydWVcbiAgICB9LFxuICB9KTtcbn0pO1xuXG50ZXN0KCdjaGVjayBleGlzdGluZyBidWNrZXQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IGV4aXN0aW5nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ215LWJ1Y2tldCcsIHtcbiAgICBidWNrZXROYW1lOiAnbXktYnVja2V0J1xuICB9KTtcblxuICBjb25zdCBwcm9wczogQ2xvdWRGcm9udFRvUzNQcm9wcyA9IHtcbiAgICBleGlzdGluZ0J1Y2tldE9iajogZXhpc3RpbmdCdWNrZXRcbiAgfTtcblxuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCBwcm9wcyk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIEJ1Y2tldE5hbWU6IFwibXktYnVja2V0XCJcbiAgfSk7XG59KTtcblxudGVzdCgnY2hlY2sgZXhjZXB0aW9uIGZvciBNaXNzaW5nIGV4aXN0aW5nT2JqIGZyb20gcHJvcHMgZm9yIGRlcGxveSA9IGZhbHNlJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICB0cnkge1xuICAgIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1zMycsIHt9KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGV4cGVjdChlKS50b0JlSW5zdGFuY2VPZihFcnJvcik7XG4gIH1cbn0pO1xuXG50ZXN0KCdjaGVjayBwcm9wZXJ0aWVzJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBjb25zdHJ1Y3Q6IENsb3VkRnJvbnRUb1MzID0gZGVwbG95KHN0YWNrKTtcblxuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRXZWJEaXN0cmlidXRpb24pLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuczNCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG59KTtcblxudGVzdChcIkNvbmZpcm0gQ2hlY2tTM1Byb3BzIGlzIGNhbGxlZFwiLCAoKSA9PiB7XG4gIC8vIFN0YWNrXG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IHRlc3RCdWNrZXQgPSBuZXcgczMuQnVja2V0KHN0YWNrLCAndGVzdC1idWNrZXQnLCB7fSk7XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIC8vIEhlbHBlciBkZWNsYXJhdGlvblxuICAgIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgXCJiYWQtczMtYXJnc1wiLCB7XG4gICAgICBleGlzdGluZ0J1Y2tldE9iajogdGVzdEJ1Y2tldCxcbiAgICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWVxuICAgICAgfSxcbiAgICB9KTtcbiAgfTtcbiAgLy8gQXNzZXJ0aW9uXG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcignRXJyb3IgLSBFaXRoZXIgcHJvdmlkZSBidWNrZXRQcm9wcyBvciBleGlzdGluZ0J1Y2tldE9iaiwgYnV0IG5vdCBib3RoLlxcbicpO1xufSk7XG5cbnRlc3QoXCJUZXN0IGV4aXN0aW5nQnVja2V0T2JqXCIsICgpID0+IHtcbiAgLy8gU3RhY2tcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGNvbnN0cnVjdDogQ2xvdWRGcm9udFRvUzMgPSBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssIFwiZXhpc3RpbmdJQnVja2V0XCIsIHtcbiAgICBleGlzdGluZ0J1Y2tldE9iajogczMuQnVja2V0LmZyb21CdWNrZXROYW1lKHN0YWNrLCAnbXlidWNrZXQnLCAnbXlidWNrZXQnKVxuICB9KTtcbiAgLy8gQXNzZXJ0aW9uXG4gIGV4cGVjdChjb25zdHJ1Y3QuY2xvdWRGcm9udFdlYkRpc3RyaWJ1dGlvbikudG9CZURlZmluZWQoKTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICBPcmlnaW5zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBEb21haW5OYW1lOiB7XG4gICAgICAgICAgICBcIkZuOjpKb2luXCI6IFtcbiAgICAgICAgICAgICAgXCJcIixcbiAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIFwibXlidWNrZXQuczMuXCIsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgUmVmOiBcIkFXUzo6UmVnaW9uXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIFwiLlwiLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIFJlZjogXCJBV1M6OlVSTFN1ZmZpeFwiXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBdXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBJZDogXCJleGlzdGluZ0lCdWNrZXRDbG91ZEZyb250RGlzdHJpYnV0aW9uT3JpZ2luMUQ1ODQ5MTI1XCIsXG4gICAgICAgICAgT3JpZ2luQWNjZXNzQ29udHJvbElkOiB7IFwiRm46OkdldEF0dFwiOiBbXCJleGlzdGluZ0lCdWNrZXRDbG91ZEZyb250T2FjRUI0MkU5OEZcIiwgXCJJZFwiXSB9LFxuICAgICAgICAgIFMzT3JpZ2luQ29uZmlnOiB7fVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCd0ZXN0IGNsb3VkZnJvbnQgd2l0aCBjdXN0b20gZG9tYWluIG5hbWVzJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBjZXJ0aWZpY2F0ZSA9IGFjbS5DZXJ0aWZpY2F0ZS5mcm9tQ2VydGlmaWNhdGVBcm4oc3RhY2ssICdDZXJ0JywgJ2Fybjoke0F3cy5QQVJUSVRJT059OmFjbTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmNlcnRpZmljYXRlLzExMTEyMjIyLTMzMzMtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMicpO1xuXG4gIGNvbnN0IHByb3BzOiBDbG91ZEZyb250VG9TM1Byb3BzID0ge1xuICAgIGNsb3VkRnJvbnREaXN0cmlidXRpb25Qcm9wczoge1xuICAgICAgZG9tYWluTmFtZXM6IFsnbXlkb21haW5zJ10sXG4gICAgICBjZXJ0aWZpY2F0ZVxuICAgIH1cbiAgfTtcblxuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCBwcm9wcyk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICBBbGlhc2VzOiBbXG4gICAgICAgIFwibXlkb21haW5zXCJcbiAgICAgIF1cbiAgICB9XG4gIH0pO1xufSk7XG5cbnRlc3QoJ0Nsb3VkZnJvbnQgbG9nZ2luZyBidWNrZXQgd2l0aCBkZXN0cm95IHJlbW92YWwgcG9saWN5IGFuZCBhdXRvIGRlbGV0ZSBvYmplY3RzJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBjbG91ZGZyb250TG9nQnVja2V0TmFtZSA9ICdjZi1sb2ctYnVja2V0JztcbiAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWUsXG4gICAgICBidWNrZXROYW1lOiBjbG91ZGZyb250TG9nQnVja2V0TmFtZVxuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIE93bmVyc2hpcENvbnRyb2xzOiB7IFJ1bGVzOiBbeyBPYmplY3RPd25lcnNoaXA6IFwiT2JqZWN0V3JpdGVyXCIgfV0gfSxcbiAgICBCdWNrZXROYW1lOiBjbG91ZGZyb250TG9nQnVja2V0TmFtZSxcbiAgfSk7XG5cbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQ3VzdG9tOjpTM0F1dG9EZWxldGVPYmplY3RzXCIsIHtcbiAgICBTZXJ2aWNlVG9rZW46IHtcbiAgICAgIFwiRm46OkdldEF0dFwiOiBbXG4gICAgICAgIFwiQ3VzdG9tUzNBdXRvRGVsZXRlT2JqZWN0c0N1c3RvbVJlc291cmNlUHJvdmlkZXJIYW5kbGVyOUQ5MDE4NEZcIixcbiAgICAgICAgXCJBcm5cIlxuICAgICAgXVxuICAgIH0sXG4gICAgQnVja2V0TmFtZToge1xuICAgICAgUmVmOiBcImNsb3VkZnJvbnRzM0Nsb3VkZnJvbnRMb2dnaW5nQnVja2V0NUI4NDUxNDNcIlxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdCgnczMgYnVja2V0IHdpdGggb25lIGNvbnRlbnQgYnVja2V0IGFuZCBubyBhY2Nlc3MgbG9nZ2luZyBvZiBDT05URU5UIGJ1Y2tldCcsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBidWNrZXRQcm9wczoge1xuICAgICAgcmVtb3ZhbFBvbGljeTogY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICB9LFxuICAgIGxvZ1MzQWNjZXNzTG9nczogZmFsc2VcbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAvLyBDb250ZW50IGJ1Y2tldCtDbG91ZGZyb250IExvZ3MgYnVja2V0K1xuICAvLyBBY2Nlc3MgTG9nIGJ1Y2tldCBmb3IgQ2xvdWRmcm9udCBMb2dzIGJ1Y2tldCA9IDMgYnVja2V0c1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgMyk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuczNMb2dnaW5nQnVja2V0KS50b0VxdWFsKHVuZGVmaW5lZCk7XG59KTtcblxudGVzdCgnQ2xvdWRGcm9udCBvcmlnaW4gcGF0aCBwcmVzZW50IHdoZW4gcHJvdmlkZWQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtczMnLCB7XG4gICAgb3JpZ2luUGF0aDogJy90ZXN0UGF0aCdcbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOlxuICAgIHtcbiAgICAgIE9yaWdpbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIE9yaWdpblBhdGg6IFwiL3Rlc3RQYXRoXCIsXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9XG4gIH0pO1xufSk7XG5cbnRlc3QoJ0Nsb3VkRnJvbnQgb3JpZ2luIHBhdGggc2hvdWxkIG5vdCBiZSBwcmVzZW50IGlmIG5vdCBwcm92aWRlZCcsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHt9KTtcblxuICBkZWZhdWx0cy5leHBlY3ROb25leGlzdGVuY2Uoc3RhY2ssIFwiQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb25cIiwge1xuICAgIERpc3RyaWJ1dGlvbkNvbmZpZzpcbiAgICB7XG4gICAgICBPcmlnaW5zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBPcmlnaW5QYXRoOiBcIi90ZXN0UGF0aFwiLFxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCdUZXN0IHRoZSBkZXBsb3ltZW50IHdpdGggc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IgaW5zdGVhZCBvZiBIVFRQIHNlY3VyaXR5IGhlYWRlcnMnLCAoKSA9PiB7XG4gIC8vIEluaXRpYWwgc2V0dXBcbiAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgY29uc3QgY2xvdWRGcm9udFRvUzMgPSBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCB7XG4gICAgaW5zZXJ0SHR0cFNlY3VyaXR5SGVhZGVyczogZmFsc2UsXG4gICAgcmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHM6IHtcbiAgICAgIHNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yOiB7XG4gICAgICAgIHN0cmljdFRyYW5zcG9ydFNlY3VyaXR5OiB7XG4gICAgICAgICAgYWNjZXNzQ29udHJvbE1heEFnZTogRHVyYXRpb24uc2Vjb25kcyg2MzA3MiksXG4gICAgICAgICAgaW5jbHVkZVN1YmRvbWFpbnM6IHRydWUsXG4gICAgICAgICAgb3ZlcnJpZGU6IHRydWUsXG4gICAgICAgICAgcHJlbG9hZDogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBjb250ZW50U2VjdXJpdHlQb2xpY3k6IHtcbiAgICAgICAgICBjb250ZW50U2VjdXJpdHlQb2xpY3k6IFwidXBncmFkZS1pbnNlY3VyZS1yZXF1ZXN0czsgZGVmYXVsdC1zcmMgJ25vbmUnO1wiLFxuICAgICAgICAgIG92ZXJyaWRlOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICAvLyBBc3NlcnRpb25cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OlJlc3BvbnNlSGVhZGVyc1BvbGljeVwiLCB7XG4gICAgUmVzcG9uc2VIZWFkZXJzUG9saWN5Q29uZmlnOiB7XG4gICAgICBTZWN1cml0eUhlYWRlcnNDb25maWc6IHtcbiAgICAgICAgQ29udGVudFNlY3VyaXR5UG9saWN5OiB7XG4gICAgICAgICAgQ29udGVudFNlY3VyaXR5UG9saWN5OiBcInVwZ3JhZGUtaW5zZWN1cmUtcmVxdWVzdHM7IGRlZmF1bHQtc3JjICdub25lJztcIixcbiAgICAgICAgICBPdmVycmlkZTogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBTdHJpY3RUcmFuc3BvcnRTZWN1cml0eToge1xuICAgICAgICAgIEFjY2Vzc0NvbnRyb2xNYXhBZ2VTZWM6IDYzMDcyLFxuICAgICAgICAgIEluY2x1ZGVTdWJkb21haW5zOiB0cnVlLFxuICAgICAgICAgIE92ZXJyaWRlOiB0cnVlLFxuICAgICAgICAgIFByZWxvYWQ6IHRydWVcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSk7XG4gIGV4cGVjdChjbG91ZEZyb250VG9TMy5jbG91ZEZyb250RnVuY3Rpb24pLnRvRXF1YWwodW5kZWZpbmVkKTtcbn0pO1xuXG50ZXN0KFwidGhyb3cgZXhjZXB0aW9uIGlmIGluc2VydEh0dHBTZWN1cml0eUhlYWRlcnMgYW5kIHJlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzIGFyZSBwcm92aWRlZFwiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGV4cGVjdCgoKSA9PiB7XG4gICAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCBcInRlc3QtY2xvdWRmcm9udC1zM1wiLCB7XG4gICAgICBpbnNlcnRIdHRwU2VjdXJpdHlIZWFkZXJzOiB0cnVlLFxuICAgICAgcmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHM6IHtcbiAgICAgICAgc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3I6IHtcbiAgICAgICAgICBzdHJpY3RUcmFuc3BvcnRTZWN1cml0eToge1xuICAgICAgICAgICAgYWNjZXNzQ29udHJvbE1heEFnZTogRHVyYXRpb24uc2Vjb25kcyg2MzA3MiksXG4gICAgICAgICAgICBpbmNsdWRlU3ViZG9tYWluczogdHJ1ZSxcbiAgICAgICAgICAgIG92ZXJyaWRlOiBmYWxzZSxcbiAgICAgICAgICAgIHByZWxvYWQ6IHRydWVcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfSkudG9UaHJvd0Vycm9yKCk7XG59KTtcblxudGVzdChcIkNvbmZpcm0gQ2hlY2tDbG91ZEZyb250UHJvcHMgaXMgYmVpbmcgY2FsbGVkXCIsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgZXhwZWN0KCgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssIFwidGVzdC1jbG91ZGZyb250LWFwaWdhdGV3YXlcIiwge1xuICAgICAgaW5zZXJ0SHR0cFNlY3VyaXR5SGVhZGVyczogdHJ1ZSxcbiAgICAgIHJlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzOiB7XG4gICAgICAgIHNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yOiB7XG4gICAgICAgICAgc3RyaWN0VHJhbnNwb3J0U2VjdXJpdHk6IHtcbiAgICAgICAgICAgIGFjY2Vzc0NvbnRyb2xNYXhBZ2U6IER1cmF0aW9uLnNlY29uZHMoNjMwNzIpLFxuICAgICAgICAgICAgaW5jbHVkZVN1YmRvbWFpbnM6IHRydWUsXG4gICAgICAgICAgICBvdmVycmlkZTogZmFsc2UsXG4gICAgICAgICAgICBwcmVsb2FkOiB0cnVlXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pLnRvVGhyb3dFcnJvcigncmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHMuc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IgY2FuIG9ubHkgYmUgcGFzc2VkIGlmIGh0dHBTZWN1cml0eUhlYWRlcnMgaXMgc2V0IHRvIGBmYWxzZWAuJyk7XG59KTtcblxudGVzdChcIkN1c3RvbSByZXNvdXJjZSBpcyBwcm92aXNpb25lZCBpZiBlbmNyeXB0aW9uIGtleSBpcyBwcm92aWRlZCBhcyBidWNrZXRQcm9wXCIsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGVuY3J5cHRpb25LZXkgPSBuZXcgS2V5KHN0YWNrLCAnY21rS2V5Jywge1xuICAgIGVuYWJsZUtleVJvdGF0aW9uOiB0cnVlLFxuICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWVxuICB9KTtcbiAgZGVwbG95KHN0YWNrLCB7XG4gICAgYnVja2V0UHJvcHM6IHtcbiAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICBlbmNyeXB0aW9uOiBzMy5CdWNrZXRFbmNyeXB0aW9uLktNU1xuICAgIH1cbiAgfSk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgLy8gMiBGdW5jdGlvbnMgLSBvdXIgY3VzdG9tIHJlc291cmNlIGFuZCBhIGZ1bmN0aW9uIGNyZWF0ZWQgYnkgdGhlIENES1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIDIpO1xuXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgIERlc2NyaXB0aW9uOiBcIkN1c3RvbSByZXNvdXJjZSBmdW5jdGlvbiB0aGF0IHVwZGF0ZXMgYSBwcm92aWRlZCBrZXkgcG9saWN5IHRvIGFsbG93IENsb3VkRnJvbnQgYWNjZXNzLlwiLFxuICAgIFJvbGU6IHtcbiAgICAgIFwiRm46OkdldEF0dFwiOiBbXCJ0ZXN0Y2xvdWRmcm9udHMzTGFtYmRhRnVuY3Rpb25TZXJ2aWNlUm9sZTJBNDNFQTkyXCIsIFwiQXJuXCJdXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KFwiQ3VzdG9tIHJlc291cmNlIGlzIHByb3Zpc2lvbmVkIGlmIENNSyB3YXMgdXNlZCB0byBlbmNyeXB0IGFuIGV4aXN0aW5nIGJ1Y2tldFwiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gbmV3IEtleShzdGFjaywgJ2Nta0tleScsIHtcbiAgICBlbmFibGVLZXlSb3RhdGlvbjogdHJ1ZSxcbiAgICByZW1vdmFsUG9saWN5OiBSZW1vdmFsUG9saWN5LkRFU1RST1lcbiAgfSk7XG4gIGNvbnN0IGV4aXN0aW5nQnVja2V0T2JqID0gZGVmYXVsdHMuYnVpbGRTM0J1Y2tldChzdGFjaywge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICBlbmNyeXB0aW9uOiBzMy5CdWNrZXRFbmNyeXB0aW9uLktNUyxcbiAgICAgIGVuY3J5cHRpb25LZXlcbiAgICB9XG4gIH0sICdleGlzdGluZy1zMy1idWNrZXQtZW5jcnlwdGVkLXdpdGgtY21rJykuYnVja2V0O1xuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCB7XG4gICAgZXhpc3RpbmdCdWNrZXRPYmpcbiAgfSk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgLy8gMiBGdW5jdGlvbnMgLSBvdXIgY3VzdG9tIHJlc291cmNlIGFuZCBhIGZ1bmN0aW9uIGNyZWF0ZWQgYnkgdGhlIENES1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIDIpO1xuXG4gIC8vIGVuc3VyZSB0aGF0IG91ciBGdW5jdGlvbiBoYXMgdGhlIGNvcnJlY3Qgcm9sZSBhdHRhY2hlZFxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICBEZXNjcmlwdGlvbjogXCJDdXN0b20gcmVzb3VyY2UgZnVuY3Rpb24gdGhhdCB1cGRhdGVzIGEgcHJvdmlkZWQga2V5IHBvbGljeSB0byBhbGxvdyBDbG91ZEZyb250IGFjY2Vzcy5cIixcbiAgICBSb2xlOiB7XG4gICAgICBcIkZuOjpHZXRBdHRcIjogW1widGVzdGNsb3VkZnJvbnRzM0xhbWJkYUZ1bmN0aW9uU2VydmljZVJvbGUyQTQzRUE5MlwiLCBcIkFyblwiXVxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdChcIkN1c3RvbSByZXNvdXJjZSBpcyBub3QgcHJvdmlzaW9uZWQgaWYgZW5jcnlwdGlvbiBrZXkgaXMgbm90IHByb3ZpZGVkIGFzIGJ1Y2tldFByb3BcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgZGVwbG95KHN0YWNrKTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIDApO1xufSk7XG5cbnRlc3QoXCJDdXN0b20gcmVzb3VyY2UgaXMgbm90IHByb3Zpc2lvbmVkIGlmIENNSyB3YXMgbm90IHVzZWQgdG8gZW5jcnlwdCBhbiBleGlzdGluZyBidWNrZXRcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgZXhpc3RpbmdCdWNrZXRPYmogPSBkZWZhdWx0cy5idWlsZFMzQnVja2V0KHN0YWNrLCB7fSwgJ2V4aXN0aW5nLXMzLWJ1Y2tldC1lbmNyeXB0ZWQtd2l0aC1jbWsnKS5idWNrZXQ7XG4gIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1zMycsIHtcbiAgICBleGlzdGluZ0J1Y2tldE9ialxuICB9KTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIDApO1xufSk7XG5cbnRlc3QoXCJIdHRwT3JpZ2luIGlzIHByb3Zpc2lvbmVkIGlmIGEgc3RhdGljIHdlYnNpdGUgYnVja2V0IGlzIHVzZWRcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgYmxvY2tQdWJsaWNBY2Nlc3MgPSBmYWxzZTtcbiAgY29uc3QgcHJvcHM6IENsb3VkRnJvbnRUb1MzUHJvcHMgPSB7XG4gICAgYnVja2V0UHJvcHM6IHtcbiAgICAgIGVuZm9yY2VTU0w6IGZhbHNlLFxuICAgICAgcHVibGljUmVhZEFjY2VzczogdHJ1ZSwgLy8gPC0tIHJlcXVpcmVkIGZvciBpc1dlYnNpdGVcbiAgICAgIGJsb2NrUHVibGljQWNjZXNzOiB7XG4gICAgICAgIGJsb2NrUHVibGljQWNsczogYmxvY2tQdWJsaWNBY2Nlc3MsXG4gICAgICAgIHJlc3RyaWN0UHVibGljQnVja2V0czogYmxvY2tQdWJsaWNBY2Nlc3MsXG4gICAgICAgIGJsb2NrUHVibGljUG9saWN5OiBibG9ja1B1YmxpY0FjY2VzcyxcbiAgICAgICAgaWdub3JlUHVibGljQWNsczogYmxvY2tQdWJsaWNBY2Nlc3NcbiAgICAgIH0sXG4gICAgICB3ZWJzaXRlSW5kZXhEb2N1bWVudDogXCJpbmRleC5odG1sXCIgLy8gPC0tIHJlcXVpcmVkIGZvciBpc1dlYnNpdGVcbiAgICB9LFxuICAgIGluc2VydEh0dHBTZWN1cml0eUhlYWRlcnM6IGZhbHNlXG4gIH07XG4gIGNvbnN0IGNvbnN0cnVjdCA9IG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1zMycsIHByb3BzKTtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAvLyBBc3NlcnQgcmVzb3VyY2VzXG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcygnQVdTOjpDbG91ZEZyb250OjpPcmlnaW5BY2Nlc3NDb250cm9sJywgMCk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb24nLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICBPcmlnaW5zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBDdXN0b21PcmlnaW5Db25maWc6IHtcbiAgICAgICAgICAgIE9yaWdpblByb3RvY29sUG9saWN5OiBcImh0dHAtb25seVwiXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OkNsb3VkRnJvbnQ6Ok9yaWdpbkFjY2Vzc0lkZW50aXR5JywgMCk7XG4gIC8vIEFzc2VydCBwYXR0ZXJuIHByb3BlcnRpZXMgKG91dHB1dCBwcm9wcylcbiAgZXhwZWN0KGNvbnN0cnVjdC5vcmlnaW5BY2Nlc3NDb250cm9sKS50b0JlKHVuZGVmaW5lZCk7XG59KTtcblxudGVzdChcIk9BQyBpcyBwcm92aXNpb25lZCBpbiBhbGwgb3RoZXIgY2FzZXNcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LXMzJywge30pO1xuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIC8vIEFzc2VydCByZXNvdXJjZXNcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OkNsb3VkRnJvbnQ6Ok9yaWdpbkFjY2Vzc0NvbnRyb2wnLCAxKTtcbiAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OkNsb3VkRnJvbnQ6Ok9yaWdpbkFjY2Vzc0lkZW50aXR5JywgMCk7XG4gIC8vIEFzc2VydCBwYXR0ZXJuIHByb3BlcnRpZXMgKG91dHB1dCBwcm9wcylcbiAgZXhwZWN0KGNvbnN0cnVjdC5vcmlnaW5BY2Nlc3NDb250cm9sKS5ub3QudG9CZSh1bmRlZmluZWQpO1xufSk7XG5cbnRlc3QoXCJJZiBhIGN1c3RvbWVyIHByb3ZpZGVzIHRoZWlyIG93biBodHRwT3JpZ2luLCBvciBvdGhlciBvcmlnaW4gdHlwZSwgdXNlIHRoYXQgb25lXCIsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGJsb2NrUHVibGljQWNjZXNzID0gZmFsc2U7XG4gIGNvbnN0IHByb3BzOiBDbG91ZEZyb250VG9TM1Byb3BzID0ge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICBlbmZvcmNlU1NMOiBmYWxzZSxcbiAgICAgIHB1YmxpY1JlYWRBY2Nlc3M6IHRydWUsIC8vIDwtLSByZXF1aXJlZCBmb3IgaXNXZWJzaXRlXG4gICAgICBibG9ja1B1YmxpY0FjY2Vzczoge1xuICAgICAgICBibG9ja1B1YmxpY0FjbHM6IGJsb2NrUHVibGljQWNjZXNzLFxuICAgICAgICByZXN0cmljdFB1YmxpY0J1Y2tldHM6IGJsb2NrUHVibGljQWNjZXNzLFxuICAgICAgICBibG9ja1B1YmxpY1BvbGljeTogYmxvY2tQdWJsaWNBY2Nlc3MsXG4gICAgICAgIGlnbm9yZVB1YmxpY0FjbHM6IGJsb2NrUHVibGljQWNjZXNzXG4gICAgICB9LFxuICAgICAgd2Vic2l0ZUluZGV4RG9jdW1lbnQ6IFwiaW5kZXguaHRtbFwiIC8vIDwtLSByZXF1aXJlZCBmb3IgaXNXZWJzaXRlXG4gICAgfSxcbiAgICBpbnNlcnRIdHRwU2VjdXJpdHlIZWFkZXJzOiBmYWxzZSxcbiAgICBjbG91ZEZyb250RGlzdHJpYnV0aW9uUHJvcHM6IHtcbiAgICAgIGRlZmF1bHRCZWhhdmlvcjoge1xuICAgICAgICBvcmlnaW46IG5ldyBvcmlnaW5zLkh0dHBPcmlnaW4oJ2V4YW1wbGUuY29tJywge1xuICAgICAgICAgIG9yaWdpbklkOiAnY3VzdG9tLWh0dHAtb3JpZ2luLWZvci10ZXN0aW5nJ1xuICAgICAgICB9KVxuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAndGVzdC1jbG91ZGZyb250LXMzJywgcHJvcHMpO1xuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIC8vIEFzc2VydCByZXNvdXJjZXNcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvbicsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIE9yaWdpbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIERvbWFpbk5hbWU6IFwiZXhhbXBsZS5jb21cIixcbiAgICAgICAgICBJZDogXCJjdXN0b20taHR0cC1vcmlnaW4tZm9yLXRlc3RpbmdcIlxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCdUZXN0IHRoYXQgd2UgZG8gbm90IGNyZWF0ZSBhbiBBY2Nlc3MgTG9nIGJ1Y2tldCBmb3IgQ0YgbG9ncyBpZiBvbmUgaXMgcHJvdmlkZWQnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBjZlMzQWNjZXNzTG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2NmLXMzLWFjY2Vzcy1sb2dzJyk7XG4gIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ3Rlc3QtY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICBzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0OiBjZlMzQWNjZXNzTG9nQnVja2V0XG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCA0KTtcblxufSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PVxuLy8gUzMgQ29udGVudCBCdWNrZXQgQWNjZXNzIExvZ3MgQnVja2V0XG4vLyA9PT09PT09PT09PT09PT09PT09PT1cbnRlc3QoJ1Byb3ZpZGluZyBsb2dnaW5nQnVja2V0UHJvcHMgYW5kIGV4aXN0aW5nTG9nZ2luZ0J1Y2tldCBpcyBhbiBlcnJvcicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGxvZ0J1Y2tldCA9IG5ldyBzMy5CdWNrZXQoc3RhY2ssICdsb2ctYnVja2V0Jywge30pO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgICAgYnVja2V0UHJvcHM6IHtcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc0J1Y2tldDogbG9nQnVja2V0LFxuICAgICAgfSxcbiAgICAgIGxvZ2dpbmdCdWNrZXRQcm9wczoge1xuICAgICAgICBidWNrZXROYW1lOiAnYW55dGhpbmcnXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcigvRXJyb3IgLSBib3RobG9nIGJ1Y2tldCBwcm9wcyBhbmQgYW4gZXhpc3RpbmcgbG9nIGJ1Y2tldCB3ZXJlIHByb3ZpZGVkLlxcbi8pO1xufSk7XG5cbnRlc3QoJ1Byb3ZpZGluZyBleGlzdGluZ0xvZ2dpbmdCdWNrZXQgYW5kIGxvZ1MzQWNjZXNzTG9ncz1mYWxzZSBpcyBhbiBlcnJvcicsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGxvZ0J1Y2tldCA9IG5ldyBzMy5CdWNrZXQoc3RhY2ssICdjbG91ZGZyb250LWxvZy1idWNrZXQnLCB7fSk7XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIG5ldyBDbG91ZEZyb250VG9TMyhzdGFjaywgJ2Nsb3VkZnJvbnQtczMnLCB7XG4gICAgICBidWNrZXRQcm9wczoge1xuICAgICAgICBzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0OiBsb2dCdWNrZXQsXG4gICAgICB9LFxuICAgICAgbG9nUzNBY2Nlc3NMb2dzOiBmYWxzZVxuICAgIH0pO1xuICB9O1xuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoL0Vycm9yIC0gbG9nUzNBY2Nlc3NMb2dzIGlzIGZhbHNlLCBidXQgYSBsb2cgYnVja2V0IHdhcyBwcm92aWRlZCBpbiBidWNrZXRQcm9wcy5cXG4vKTtcbn0pO1xuXG50ZXN0KCdQcm92aWRpbmcgbG9nZ2luZ0J1Y2tldFByb3BzIGFuZCBsb2dTM0FjY2Vzc0xvZ3M9ZmFsc2UgaXMgYW4gZXJyb3InLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgICAgbG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICAgIGJ1Y2tldE5hbWU6ICdhbnl0aGluZydcbiAgICAgIH0sXG4gICAgICBsb2dTM0FjY2Vzc0xvZ3M6IGZhbHNlXG4gICAgfSk7XG4gIH07XG4gIC8vIE5PVEU6IFRoaXMgZXJyb3IgaXMgdGhyb3duIGJ5IENoZWNrUzNQcm9wcygpLCBub3QgQ2hlY2tDb25zdHJ1Y3RTcGVjaWZpY1Byb3BzKClcbiAgZXhwZWN0KGFwcCkudG9UaHJvd0Vycm9yKC9FcnJvciAtIElmIGxvZ1MzQWNjZXNzTG9ncyBpcyBmYWxzZSwgc3VwcGx5aW5nIGxvZ2dpbmdCdWNrZXRQcm9wcyBvciBleGlzdGluZ0xvZ2dpbmdCdWNrZXRPYmogaXMgaW52YWxpZC5cXG4vKTtcbn0pO1xuXG4vLyB0ZXN0KCdObyBuZXcgbG9nZ2luZ0J1Y2tldCBpcyBjcmVhdGVkIGlmIGV4aXN0aW5nTG9nZ2luZ0J1Y2tldCBpcyBzdXBwbGllZCcsICgpID0+IHtcbnRlc3QoJ2xvZ2dpbmdCdWNrZXRQcm9wcyBpcyBzdXBwbGllZCBpcyBpbnRlZ3JhdGVkIGludG8gYXJjaGl0ZWN0dXJlIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgdGVzdE5hbWUgPSBcInRlc3QtbmFtZVwiO1xuICBjb25zdCBjb25zdHJ1Y3QgPSBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgIH0sXG4gICAgbG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWUsXG4gICAgICBidWNrZXROYW1lOiB0ZXN0TmFtZVxuICAgIH1cbiAgfSk7XG5cbiAgZXhwZWN0KGNvbnN0cnVjdC5zM0xvZ2dpbmdCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG5cbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpTMzo6QnVja2V0XCIsIHtcbiAgICBCdWNrZXROYW1lOiB0ZXN0TmFtZVxuICB9KTtcblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIExvZ2dpbmdDb25maWd1cmF0aW9uOiB7XG4gICAgICBEZXN0aW5hdGlvbkJ1Y2tldE5hbWU6IHtcbiAgICAgICAgUmVmOiBcImNsb3VkZnJvbnRzM1MzTG9nZ2luZ0J1Y2tldDUyRUVCNzA4XCJcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xufSk7XG50ZXN0KCdidWNrZXRQcm9wczpzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0IGlzIHN1cHBsaWVkIGlzIGludGVncmF0ZWQgaW50byBhcmNoaXRlY3R1cmUgY29ycmVjdGx5JywgKCkgPT4ge1xuICBjb25zdCB0ZXN0TmFtZSA9ICdzb21lLW5hbWUnO1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgbG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ3Rlc3QtbG9nJywge1xuICAgIGJ1Y2tldE5hbWU6IHRlc3ROYW1lLFxuICB9KTtcblxuICBjb25zdCBjb25zdHJ1Y3QgPSBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgIGJ1Y2tldFByb3BzOiB7XG4gICAgICBzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0OiBsb2dCdWNrZXQsXG4gICAgfSxcbiAgfSk7XG5cbiAgZXhwZWN0KGNvbnN0cnVjdC5zM0xvZ2dpbmdCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgTG9nZ2luZ0NvbmZpZ3VyYXRpb246IHtcbiAgICAgIERlc3RpbmF0aW9uQnVja2V0TmFtZToge1xuICAgICAgICBSZWY6IFwidGVzdGxvZ0U4OEI0QzZCXCJcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xufSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PVxuLy8gQ2xvdWRGcm9udCBMb2cgQnVja2V0XG4vLyA9PT09PT09PT09PT09PT09PT09PT1cbnRlc3QoJ1Byb3ZpZGluZyBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzIGFuZCBhIGxvZyBidWNrZXQgaW4gY2xvdWRGcm9udERpc3RyYnV0aW9uUHJvcHMgaXMgYW4gZXJyb3InLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBsb2dCdWNrZXQgPSBuZXcgczMuQnVja2V0KHN0YWNrLCAnY2xvdWRmcm9udC1sb2ctYnVja2V0Jywge30pO1xuXG4gIGNvbnN0IGFwcCA9ICgpID0+IHtcbiAgICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgICAgY2xvdWRGcm9udERpc3RyaWJ1dGlvblByb3BzOiB7XG4gICAgICAgIGxvZ0J1Y2tldFxuICAgICAgfSxcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgcmVtb3ZhbFBvbGljeTogY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoKTtcbn0pO1xudGVzdCgnY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wcyBhcmUgdXNlZCBjb3JyZWN0bHknLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuXG4gIGNvbnN0IHRlc3ROYW1lID0gXCJ0ZXN0LW5hbWVcIjtcbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOiB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWUsXG4gICAgICBidWNrZXROYW1lOiB0ZXN0TmFtZVxuICAgIH1cbiAgfSk7XG5cbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCA0KTtcblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIEJ1Y2tldE5hbWU6IHRlc3ROYW1lXG4gIH0pO1xuXG59KTtcbnRlc3QoJ0xvZ2dpbmcgZGlzYWJsZWQgaW4gQ2xvdWRGcm9udCBwcm9wcyBpcyBoYW5kbGVkIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgY29uc3RydWN0ID0gZGVwbG95KHN0YWNrLCB7IGNsb3VkRnJvbnREaXN0cmlidXRpb25Qcm9wczogeyBlbmFibGVMb2dnaW5nOiBmYWxzZSB9IH0pO1xuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgLy8gT25seSB0aGUgY29udGVudCBidWNrZXQgYW5kIGl0IFMzIEFjY2VzcyBMb2cgYnVja2V0IChubyBDbG91ZGZyb250IGxvZyBidWNrZXQpXG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCAyKTtcblxuICAvLyBObyBsb2dnaW5nIGlzIGNvbmZpZ3VyZWRcbiAgdGVtcGxhdGUucmVzb3VyY2VQcm9wZXJ0aWVzQ291bnRJcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIExvZ2dpbmc6IE1hdGNoLmFueVZhbHVlKClcbiAgICB9XG4gIH0sIDApO1xuICBleHBlY3QoY29uc3RydWN0LmNsb3VkRnJvbnRMb2dnaW5nQnVja2V0ID09PSB1bmRlZmluZWQpO1xufSk7XG50ZXN0KCdObyBuZXcgQ2xvdWRGcm9udExvZ2dpbmdCdWNrZXQgaXMgY3JlYXRlZCBpZiBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzOmxvZ0J1Y2tldCBpcyBzdXBwbGllZCcsICgpID0+IHtcbiAgY29uc3QgdGVzdE5hbWUgPSAncmFuZG9tLXZhbHVlJztcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGxvZ0J1Y2tldCA9IG5ldyBzMy5CdWNrZXQoc3RhY2ssICdjbG91ZGZyb250LWxvZy1idWNrZXQnLCB7XG4gICAgYnVja2V0TmFtZTogdGVzdE5hbWVcbiAgfSk7XG5cbiAgLy8gY29uc3QgY29uc3RydWN0ID1cbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250RGlzdHJpYnV0aW9uUHJvcHM6IHtcbiAgICAgIGxvZ0J1Y2tldFxuICAgIH0sXG4gIH0pO1xuXG4gIGV4cGVjdChjb25zdHJ1Y3QuY2xvdWRGcm9udExvZ2dpbmdCdWNrZXQpLnRvQmVEZWZpbmVkKCk7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBDb250ZW50IGJ1Y2tldCwgQ29udGVudCBidWNrZXQgUzMgQWNjZXNzIExvZyBidWNrZXQsIGNsb3VkZnJvbnQgbG9nIGJ1Y2tldFxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgMyk7XG5cbiAgLy8gRW5zdXJlIG91ciBleGlzdGluZyBidWNrZXQgaGFzIGJlZW4gdXNlZCBmb3IgY2xvdWRmcm9udCBsb2dnaW5nXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIExvZ2dpbmc6IHtcbiAgICAgICAgQnVja2V0OiB7XG4gICAgICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcbiAgICAgICAgICAgIFwiY2xvdWRmcm9udGxvZ2J1Y2tldERGNzA1OEZCXCIsXG4gICAgICAgICAgICBcIlJlZ2lvbmFsRG9tYWluTmFtZVwiXG4gICAgICAgICAgXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxufSk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PVxuLy8gQ2xvdWRGcm9udCBMb2dzIEJ1Y2tldCBBY2Nlc3MgTG9nIEJ1Y2tldFxuLy8gPT09PT09PT09PT09PT09PT09PT09XG50ZXN0KCdQcm92aWRpbmcgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wcyBhbmQgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wczpzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0IGlzIGFuIGVycm9yJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgbG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2Nsb3VkZnJvbnQtbG9nLWJ1Y2tldCcsIHt9KTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc0J1Y2tldDogbG9nQnVja2V0LFxuICAgICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZVxuICAgICAgfSxcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0QWNjZXNzTG9nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgYnVja2V0TmFtZTogJ3NwZWNmaWMtbmFtZS1pcy1pbmNvbnNlcXVlbnRpYWwnXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgZXhwZWN0KGFwcCkudG9UaHJvd0Vycm9yKFxuICAgIC9FcnJvciAtIGFuIGV4aXN0aW5nIENsb3VkRnJvbnQgbG9nIGJ1Y2tldCBTMyBhY2Nlc3MgbG9nIGJ1Y2tldCBhbmQgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wcyB3ZXJlIHByb3ZpZGVkXFxuLyk7XG59KTtcbnRlc3QoJ1Byb3ZpZGluZyBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzIGFuZCBsb2dDbG91ZEZyb250QWNjZXNzTG9nPWZhbHNlIGlzIGFuIGVycm9yJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICAgIGxvZ0Nsb3VkRnJvbnRBY2Nlc3NMb2c6IGZhbHNlLFxuICAgICAgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wczoge1xuICAgICAgICBidWNrZXROYW1lOiAnc3BlY2ZpYy1uYW1lLWlzLWluY29uc2VxdWVudGlhbCdcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoL0Vycm9yIC0gY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wcyB3ZXJlIHByb3ZpZGVkIGJ1dCBsb2dDbG91ZEZyb250QWNjZXNzTG9nIHdhcyBmYWxzZVxcbi8pO1xufSk7XG50ZXN0KCdQcm92aWRpbmcgbG9nQ2xvdWRGcm9udEFjY2Vzc0xvZz1mYWxzZSBhbmQgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wczpzZXJ2ZXJBY2Nlc3NMb2dzQnVja2V0IGlzIGFuIGVycm9yJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgY29uc3QgbG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2Nsb3VkZnJvbnQtbG9nLWJ1Y2tldCcsIHt9KTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc0J1Y2tldDogbG9nQnVja2V0LFxuICAgICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZVxuICAgICAgfSxcbiAgICAgIGxvZ0Nsb3VkRnJvbnRBY2Nlc3NMb2c6IGZhbHNlLFxuICAgIH0pO1xuICB9O1xuXG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcigvRXJyb3IgLSBwcm9wcy5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldFByb3BzLnNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQgd2FzIHByb3ZpZGVkIGJ1dCBsb2dDbG91ZEZyb250QWNjZXNzTG9nIHdhcyBmYWxzZVxcbi8pO1xufSk7XG50ZXN0KCdjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzIGFyZSB1c2VkIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzOiB7XG4gICAgICB3ZWJzaXRlRXJyb3JEb2N1bWVudDogJ3BsYWNlaG9sZGVyJyxcbiAgICAgIHdlYnNpdGVJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgLy8gQ29udGVudCBCdWNrZXQsIENvbnRlbnQgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0LCBDbG91ZEZyb250IExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCBTMyBBY2Nlc3MgTG9nIEJ1Y2tldFxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgV2Vic2l0ZUNvbmZpZ3VyYXRpb246IHtcbiAgICAgIEVycm9yRG9jdW1lbnQ6ICdwbGFjZWhvbGRlcicsXG4gICAgICBJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcblxufSk7XG50ZXN0KCdJZiBleGlzdGluZyBDbG91ZEZyb250IExvZyBidWNrZXQgUzMgQWNjZXNzIExvZ2dpbmcgYnVja2V0IGlzIHByb3ZpZGVkLCBpdCBpcyB1c2VkIGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IHRlc3ROYW1lID0gJ2NmLWxvZy1zMy1sb2cnO1xuICBjb25zdCBjZkxvZ1MzQWNjZXNzTG9nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldChzdGFjaywgJ2NmLWxvZy1zMy1hY2Nlc3MtbG9nLWJ1Y2tldCcsIHtcbiAgICBidWNrZXROYW1lOiB0ZXN0TmFtZVxuICB9KTtcblxuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM6IHtcbiAgICAgIHNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQ6IGNmTG9nUzNBY2Nlc3NMb2dCdWNrZXRcbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBDb250ZW50IEJ1Y2tldCwgQ29udGVudCBCdWNrZXQgUzMgQWNjZXNzIExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCwgQ2xvdWRGcm9udCBMb2cgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCA0KTtcblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwge1xuICAgIEJ1Y2tldE5hbWU6IHRlc3ROYW1lXG4gIH0pO1xuXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgTG9nZ2luZ0NvbmZpZ3VyYXRpb246IHtcbiAgICAgIERlc3RpbmF0aW9uQnVja2V0TmFtZToge1xuICAgICAgICBSZWY6IFwiY2Zsb2dzM2FjY2Vzc2xvZ2J1Y2tldERFMzc0QzI3XCJcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG59KTtcblxudGVzdCgnY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXQgcHJvcGVydHkgaXMgc2V0IGNvcnJlY3RseScsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG5cbiAgY29uc3QgY29uc3RydWN0ID0gbmV3IENsb3VkRnJvbnRUb1MzKHN0YWNrLCAnY2xvdWRmcm9udC1zMycsIHtcbiAgICBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldFByb3BzOiB7XG4gICAgICB3ZWJzaXRlRXJyb3JEb2N1bWVudDogJ3BsYWNlaG9sZGVyJyxcbiAgICAgIHdlYnNpdGVJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcblxuICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgLy8gQ29udGVudCBCdWNrZXQsIENvbnRlbnQgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0LCBDbG91ZEZyb250IExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCBTMyBBY2Nlc3MgTG9nIEJ1Y2tldFxuICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgV2Vic2l0ZUNvbmZpZ3VyYXRpb246IHtcbiAgICAgIEVycm9yRG9jdW1lbnQ6ICdwbGFjZWhvbGRlcicsXG4gICAgICBJbmRleERvY3VtZW50OiAncGxhY2Vob2xkZS10d28nXG4gICAgfVxuICB9KTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCEuYnVja2V0TmFtZSkudG9CZURlZmluZWQoKTtcbn0pO1xuXG50ZXN0KCdsb2dDbG91ZEZyb250QWNjZXNzTG9nIHByb3BlcnR5IGlzIHVzZWQgY29ycmVjdGx5JywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBjb25zdHJ1Y3QgPSBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICdjbG91ZGZyb250LXMzJywge1xuICAgIGxvZ0Nsb3VkRnJvbnRBY2Nlc3NMb2c6IGZhbHNlXG4gIH0pO1xuXG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBDb250ZW50IEJ1Y2tldCwgQ29udGVudCBCdWNrZXQgUzMgQWNjZXNzIExvZyBCdWNrZXQsIENsb3VkRnJvbnQgTG9nIEJ1Y2tldCwgQ2xvdWRGcm9udCBMb2cgQnVja2V0IFMzIEFjY2VzcyBMb2cgQnVja2V0XG4gIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCAzKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGNvbnN0cnVjdC5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCkubm90LnRvQmVEZWZpbmVkKCk7XG59KTtcblxudGVzdCgnYWRkaXRpb25hbEJlaGF2aW9ycyBoYXZlIGNvcnJlY3Qgb3JpZ2luJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcblxuICBjb25zdCBhZGRpdGlvbmFsQnVja2V0ID0gZGVmYXVsdHMuQ3JlYXRlU2NyYXBCdWNrZXQoc3RhY2ssIFwic2NyYXBCdWNrZXRcIiwge1xuICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZSxcbiAgfSk7XG5cbiAgY29uc3Qgb3JpZ2luQWNjZXNzQ29udHJvbCA9IG5ldyBDZm5PcmlnaW5BY2Nlc3NDb250cm9sKHN0YWNrLCAnQ2xvdWRGcm9udE9hYycsIHtcbiAgICBvcmlnaW5BY2Nlc3NDb250cm9sQ29uZmlnOiB7XG4gICAgICBuYW1lOiBkZWZhdWx0cy5nZW5lcmF0ZVBoeXNpY2FsT2FjTmFtZSgnYXdzLWNsb3VkZnJvbnQtczMtJywgW19fZmlsZW5hbWVdKSxcbiAgICAgIG9yaWdpbkFjY2Vzc0NvbnRyb2xPcmlnaW5UeXBlOiAnczMnLFxuICAgICAgc2lnbmluZ0JlaGF2aW9yOiAnYWx3YXlzJyxcbiAgICAgIHNpZ25pbmdQcm90b2NvbDogJ3NpZ3Y0JyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnT3JpZ2luIGFjY2VzcyBjb250cm9sIHByb3Zpc2lvbmVkIGJ5IGF3cy1jbG91ZGZyb250LXMzJ1xuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgYWRkaXRpb25hbE9yaWdpbiA9IG5ldyBkZWZhdWx0cy5TM09hY09yaWdpbihhZGRpdGlvbmFsQnVja2V0LCB7XG4gICAgb3JpZ2luQWNjZXNzQ29udHJvbFxuICB9KTtcblxuICBuZXcgQ2xvdWRGcm9udFRvUzMoc3RhY2ssICd0ZXN0LWNsb3VkZnJvbnQtczMnLCB7XG4gICAgY2xvdWRGcm9udERpc3RyaWJ1dGlvblByb3BzOiB7XG4gICAgICBhZGRpdGlvbmFsQmVoYXZpb3JzOiB7XG4gICAgICAgICcvYXNzZXRzL3B1YmxpYy8qJzoge1xuICAgICAgICAgIG9yaWdpbjogYWRkaXRpb25hbE9yaWdpbixcbiAgICAgICAgICBjYWNoZVBvbGljeTogQ2FjaGVQb2xpY3kuQ0FDSElOR19ESVNBQkxFRCxcbiAgICAgICAgfSxcbiAgICAgICAgJ25nc3cuanNvbic6IHtcbiAgICAgICAgICBjYWNoZVBvbGljeTogQ2FjaGVQb2xpY3kuQ0FDSElOR19ESVNBQkxFRCxcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICBDYWNoZUJlaGF2aW9yczogW1xuICAgICAgICB7XG4gICAgICAgICAgQ2FjaGVQb2xpY3lJZDogXCI0MTM1ZWEyZC02ZGY4LTQ0YTMtOWRmMy00YjVhODRiZTM5YWRcIixcbiAgICAgICAgICBDb21wcmVzczogdHJ1ZSxcbiAgICAgICAgICBQYXRoUGF0dGVybjogXCIvYXNzZXRzL3B1YmxpYy8qXCIsXG4gICAgICAgICAgVGFyZ2V0T3JpZ2luSWQ6IFwidGVzdGNsb3VkZnJvbnRzM0Nsb3VkRnJvbnREaXN0cmlidXRpb25PcmlnaW4yMUQ3ODM5MUNcIixcbiAgICAgICAgICBWaWV3ZXJQcm90b2NvbFBvbGljeTogXCJhbGxvdy1hbGxcIlxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgQ2FjaGVQb2xpY3lJZDogXCI0MTM1ZWEyZC02ZGY4LTQ0YTMtOWRmMy00YjVhODRiZTM5YWRcIixcbiAgICAgICAgICBDb21wcmVzczogdHJ1ZSxcbiAgICAgICAgICBQYXRoUGF0dGVybjogXCJuZ3N3Lmpzb25cIixcbiAgICAgICAgICBUYXJnZXRPcmlnaW5JZDogXCJ0ZXN0Y2xvdWRmcm9udHMzQ2xvdWRGcm9udERpc3RyaWJ1dGlvbk9yaWdpbjEyNDA1MTAzOVwiLFxuICAgICAgICAgIFZpZXdlclByb3RvY29sUG9saWN5OiBcImFsbG93LWFsbFwiXG4gICAgICAgIH1cbiAgICAgIF0sXG4gICAgfVxuICB9KTtcbn0pO1xuIl19
|