@aws/cloudfront-hosting-toolkit
Version:
CloudFront Hosting Toolkit offers the convenience of a managed frontend hosting service while retaining full control over the hosting and deployment infrastructure to make it your own.
231 lines (225 loc) • 33.7 kB
JavaScript
"use strict";
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.HostingInfrastructure = void 0;
const aws_cdk_lib_1 = require("aws-cdk-lib");
const cdk_nag_1 = require("cdk-nag");
const constructs_1 = require("constructs");
const helper_1 = require("../bin/cli/utils/helper");
const constants_1 = require("../bin/cli/shared/constants");
class HostingInfrastructure extends constructs_1.Construct {
constructor(scope, id, params) {
super(scope, id);
let s3Logs;
/*
//TODO add condition to activate logs
s3Logs = new s3.Bucket(this, "LogsBucket", {
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
objectOwnership: s3.ObjectOwnership.OBJECT_WRITER,
enforceSSL: true,
});
addCfnSuppressRules(s3Logs, [
{
id: "W35",
reason: "It is a log bucket, not need to have access logging enabled.",
},
]);
addCfnSuppressRules(s3Logs, [
{
id: "W51",
reason: "It is a log bucket, not need for a bucket policy.",
},
]);
*/
this.hostingBucket = new aws_cdk_lib_1.aws_s3.Bucket(this, "HostingBucket", {
versioned: false,
...(s3Logs ? { serverAccessLogsBucket: s3Logs } : {}),
enforceSSL: true,
encryption: aws_cdk_lib_1.aws_s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: new aws_cdk_lib_1.aws_s3.BlockPublicAccess({
blockPublicPolicy: true,
blockPublicAcls: true,
ignorePublicAcls: true,
restrictPublicBuckets: true,
}),
});
const s3origin = aws_cdk_lib_1.aws_cloudfront_origins.S3BucketOrigin.withOriginAccessControl(this.hostingBucket);
const myResponseHeadersPolicy = new aws_cdk_lib_1.aws_cloudfront.ResponseHeadersPolicy(this, "ResponseHeadersPolicy", {
responseHeadersPolicyName: "ResponseHeadersPolicy" + aws_cdk_lib_1.Stack.of(this).stackName + "-" + aws_cdk_lib_1.Stack.of(this).region,
comment: "ResponseHeadersPolicy" + aws_cdk_lib_1.Stack.of(this).stackName + "-" + aws_cdk_lib_1.Stack.of(this).region,
securityHeadersBehavior: {
contentTypeOptions: { override: true },
frameOptions: {
frameOption: aws_cdk_lib_1.aws_cloudfront.HeadersFrameOption.DENY,
override: true,
},
referrerPolicy: {
referrerPolicy: aws_cdk_lib_1.aws_cloudfront.HeadersReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
override: false,
},
strictTransportSecurity: {
accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(31536000),
includeSubdomains: true,
override: true,
},
xssProtection: { protection: true, modeBlock: true, override: true },
},
removeHeaders: ['age', 'date'],
});
const defaultCachePolicy = new aws_cdk_lib_1.aws_cloudfront.CachePolicy(this, "DefaultCachePolicy", {
cachePolicyName: "CachePolicy" + aws_cdk_lib_1.Stack.of(this).stackName + "-" + aws_cdk_lib_1.Stack.of(this).region,
comment: "Default policy - " + aws_cdk_lib_1.Stack.of(this).stackName + "-" + aws_cdk_lib_1.Stack.of(this).region,
defaultTtl: aws_cdk_lib_1.Duration.days(365),
minTtl: aws_cdk_lib_1.Duration.days(365),
maxTtl: aws_cdk_lib_1.Duration.days(365),
cookieBehavior: aws_cdk_lib_1.aws_cloudfront.CacheCookieBehavior.none(),
headerBehavior: aws_cdk_lib_1.aws_cloudfront.CacheHeaderBehavior.none(),
queryStringBehavior: aws_cdk_lib_1.aws_cloudfront.CacheQueryStringBehavior.none(),
enableAcceptEncodingGzip: true,
enableAcceptEncodingBrotli: true,
});
const imgCachePolicy = new aws_cdk_lib_1.aws_cloudfront.CachePolicy(this, "ImagesCachePolicy", {
cachePolicyName: "ImagesCachePolicy" + aws_cdk_lib_1.Stack.of(this).stackName + "-" + aws_cdk_lib_1.Stack.of(this).region,
comment: "Images cache policy - " + aws_cdk_lib_1.Stack.of(this).stackName + "-" + aws_cdk_lib_1.Stack.of(this).region,
defaultTtl: aws_cdk_lib_1.Duration.days(365),
minTtl: aws_cdk_lib_1.Duration.days(365),
maxTtl: aws_cdk_lib_1.Duration.days(365),
cookieBehavior: aws_cdk_lib_1.aws_cloudfront.CacheCookieBehavior.none(),
headerBehavior: aws_cdk_lib_1.aws_cloudfront.CacheHeaderBehavior.none(),
queryStringBehavior: aws_cdk_lib_1.aws_cloudfront.CacheQueryStringBehavior.none(),
});
const staticAssetsCachePolicy = new aws_cdk_lib_1.aws_cloudfront.CachePolicy(this, "staticAssetsCachePolicy", {
cachePolicyName: "StaticAssetsCachePolicy" + aws_cdk_lib_1.Stack.of(this).stackName + "-" + aws_cdk_lib_1.Stack.of(this).region,
comment: "Static assets cache policy - " + aws_cdk_lib_1.Stack.of(this).stackName + "-" + aws_cdk_lib_1.Stack.of(this).region,
defaultTtl: aws_cdk_lib_1.Duration.days(365),
minTtl: aws_cdk_lib_1.Duration.days(365),
maxTtl: aws_cdk_lib_1.Duration.days(365),
cookieBehavior: aws_cdk_lib_1.aws_cloudfront.CacheCookieBehavior.none(),
headerBehavior: aws_cdk_lib_1.aws_cloudfront.CacheHeaderBehavior.none(),
queryStringBehavior: aws_cdk_lib_1.aws_cloudfront.CacheQueryStringBehavior.none(),
});
const defaultBehavior = {
origin: s3origin,
responseHeadersPolicy: myResponseHeadersPolicy,
cachePolicy: defaultCachePolicy,
allowedMethods: aws_cdk_lib_1.aws_cloudfront.AllowedMethods.ALLOW_GET_HEAD,
viewerProtocolPolicy: aws_cdk_lib_1.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
functionAssociations: [
{
function: params.changeUri,
eventType: aws_cdk_lib_1.aws_cloudfront.FunctionEventType.VIEWER_REQUEST,
},
],
};
const imgBehaviour = {
origin: s3origin,
responseHeadersPolicy: myResponseHeadersPolicy,
cachePolicy: imgCachePolicy,
allowedMethods: aws_cdk_lib_1.aws_cloudfront.AllowedMethods.ALLOW_GET_HEAD,
viewerProtocolPolicy: aws_cdk_lib_1.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
functionAssociations: [
{
function: params.changeUri,
eventType: aws_cdk_lib_1.aws_cloudfront.FunctionEventType.VIEWER_REQUEST,
},
],
};
const staticAssetsBehaviour = {
origin: s3origin,
compress: true,
responseHeadersPolicy: myResponseHeadersPolicy,
cachePolicy: staticAssetsCachePolicy,
allowedMethods: aws_cdk_lib_1.aws_cloudfront.AllowedMethods.ALLOW_GET_HEAD,
viewerProtocolPolicy: aws_cdk_lib_1.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
functionAssociations: [
{
function: params.changeUri,
eventType: aws_cdk_lib_1.aws_cloudfront.FunctionEventType.VIEWER_REQUEST,
},
],
};
let cfLogs;
/*
//TODO add condition to activate logs
cfLogs = new s3.Bucket(this, "CloudfrontLogsBucket", {
objectOwnership: s3.ObjectOwnership.OBJECT_WRITER,
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
enforceSSL: true,
});
NagSuppressions.addResourceSuppressions(cfLogs, [
{
id: "AwsSolutions-S1",
reason: "It is a log bucket, not need to have access logging enabled.",
},
]);
addCfnSuppressRules(cfLogs, [
{
id: "W35",
reason: "It is a log bucket, not need to have access logging enabled.",
},
]);
addCfnSuppressRules(cfLogs, [
{
id: "W51",
reason: "It is a log bucket, not need for a bucket policy.",
},
]);*/
this.distribution = new aws_cdk_lib_1.aws_cloudfront.Distribution(this, "Distribution", {
comment: "Static hosting - " + aws_cdk_lib_1.Stack.of(this).stackName,
defaultRootObject: "index.html",
httpVersion: aws_cdk_lib_1.aws_cloudfront.HttpVersion.HTTP2_AND_3,
...(cfLogs ? { enableLogging: true } : {}),
...(cfLogs ? { logBucket: cfLogs } : {}),
...(cfLogs ? { logFilePrefix: "distribution-access-logs/" } : {}),
minimumProtocolVersion: aws_cdk_lib_1.aws_cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021,
defaultBehavior: defaultBehavior,
additionalBehaviors: {
"*.jpg": imgBehaviour,
"*.jpeg": imgBehaviour,
"*.png": imgBehaviour,
"*.gif": imgBehaviour,
"*.bmp": imgBehaviour,
"*.tiff": imgBehaviour,
"*.ico": imgBehaviour,
"*.js": staticAssetsBehaviour,
"*.css": staticAssetsBehaviour,
"*.html": staticAssetsBehaviour,
},
...(params.hostingConfiguration.domainName && params.certificateArn
? {
domainNames: (0, helper_1.getDomainNames)(params.hostingConfiguration.domainName),
certificate: aws_cdk_lib_1.aws_certificatemanager.Certificate.fromCertificateArn(this, "Certificate", params.certificateArn),
}
: {}),
});
cdk_nag_1.NagSuppressions.addResourceSuppressions(this.distribution, [
{
id: "AwsSolutions-CFR4",
reason: "A certificate with min TLS 1.2 is selected if the user has a custom domain",
},
]);
new aws_cdk_lib_1.CfnOutput(this, "DomainName", {
value: "https://" + this.distribution.domainName,
});
const stackName = (0, helper_1.calculateMainStackName)(params.hostingConfiguration);
new aws_cdk_lib_1.aws_ssm.StringParameter(this, 'SSMConnectionRegion', {
parameterName: '/' + stackName + '/' + constants_1.SSM_DOMAIN_STR,
stringValue: this.distribution.domainName,
});
}
}
exports.HostingInfrastructure = HostingInfrastructure;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9zdGluZ19pbmZyYXN0cnVjdHVyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImhvc3RpbmdfaW5mcmFzdHJ1Y3R1cmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHOzs7QUFFSCw2Q0FXcUI7QUFJckIscUNBQTBDO0FBRTFDLDJDQUF1QztBQUN2QyxvREFBaUY7QUFHakYsMkRBQTZEO0FBVzdELE1BQWEscUJBQXNCLFNBQVEsc0JBQVM7SUFPbEQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxNQUFvQjtRQUM1RCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLElBQUksTUFBTSxDQUFDO1FBQ1g7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztVQXFCRTtRQUNGLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxvQkFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsZUFBZSxFQUFFO1lBQ3hELFNBQVMsRUFBRSxLQUFLO1lBQ2hCLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNyRCxVQUFVLEVBQUUsSUFBSTtZQUNoQixVQUFVLEVBQUUsb0JBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVO1lBQzFDLGlCQUFpQixFQUFFLElBQUksb0JBQUUsQ0FBQyxpQkFBaUIsQ0FBQztnQkFDMUMsaUJBQWlCLEVBQUUsSUFBSTtnQkFDdkIsZUFBZSxFQUFFLElBQUk7Z0JBQ3JCLGdCQUFnQixFQUFFLElBQUk7Z0JBQ3RCLHFCQUFxQixFQUFFLElBQUk7YUFDNUIsQ0FBQztTQUNILENBQUMsQ0FBQztRQUdILE1BQU0sUUFBUSxHQUFHLG9DQUFPLENBQUMsY0FBYyxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUVwRixNQUFNLHVCQUF1QixHQUFHLElBQUksNEJBQVUs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LE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLElBQUksTUFBTSxDQUFDLGNBQWM7Z0JBQ2pFLENBQUMsQ0FBQztvQkFDRSxXQUFXLEVBQUUsSUFBQSx1QkFBYyxFQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLENBQUM7b0JBQ25FLFdBQVcsRUFBRSxvQ0FBRyxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FDN0MsSUFBSSxFQUNKLGFBQWEsRUFDYixNQUFNLENBQUMsY0FBYyxDQUN0QjtpQkFDRjtnQkFDSCxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQ1IsQ0FBQyxDQUFDO1FBRUgseUJBQWUsQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3pEO2dCQUNFLEVBQUUsRUFBRSxtQkFBbUI7Z0JBQ3ZCLE1BQU0sRUFDSiw0RUFBNEU7YUFDL0U7U0FDRixDQUFDLENBQUM7UUFJSCxJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLFlBQVksRUFBRTtZQUNoQyxLQUFLLEVBQUUsVUFBVSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVTtTQUNqRCxDQUFDLENBQUM7UUFFSCxNQUFNLFNBQVMsR0FBRyxJQUFBLCtCQUFzQixFQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBR3RFLElBQUkscUJBQUcsQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLHFCQUFxQixFQUFFO1lBQ25ELGFBQWEsRUFBRSxHQUFHLEdBQUcsU0FBUyxHQUFHLEdBQUcsR0FBRywwQkFBYztZQUNyRCxXQUFXLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVO1NBQzFDLENBQUMsQ0FBQztJQUdMLENBQUM7Q0FDRjtBQTFQRCxzREEwUEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAgXG4gIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIikuXG4gIFlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gIFxuICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gIFxuICBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgQXdzLFxuICBEdXJhdGlvbixcbiAgQXJuRm9ybWF0LFxuICBhd3NfY2xvdWRmcm9udCBhcyBjbG91ZGZyb250LFxuICBhd3NfczMgYXMgczMsXG4gIGF3c19jbG91ZGZyb250X29yaWdpbnMgYXMgb3JpZ2lucyxcbiAgYXdzX2NlcnRpZmljYXRlbWFuYWdlciBhcyBhY20sXG4gIGF3c19zc20gYXMgc3NtLFxuICBDZm5PdXRwdXQsXG4gIFN0YWNrLFxufSBmcm9tIFwiYXdzLWNkay1saWJcIjtcblxuaW1wb3J0IHsgQ2ZuRGlzdHJpYnV0aW9uIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZGZyb250XCI7XG5pbXBvcnQgeyBDZm5CdWNrZXRQb2xpY3ksIElCdWNrZXQgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXMzXCI7XG5pbXBvcnQgeyBOYWdTdXBwcmVzc2lvbnMgfSBmcm9tIFwiY2RrLW5hZ1wiO1xuXG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHsgY2FsY3VsYXRlTWFpblN0YWNrTmFtZSwgZ2V0RG9tYWluTmFtZXMgfSBmcm9tIFwiLi4vYmluL2NsaS91dGlscy9oZWxwZXJcIjtcbmltcG9ydCB7IGFkZENmblN1cHByZXNzUnVsZXMgfSBmcm9tIFwiLi9jZm5fbmFnL2Nmbl9uYWdfdXRpbHNcIjtcbmltcG9ydCB7IEhvc3RpbmdDb25maWd1cmF0aW9uIH0gZnJvbSBcIi4uL2Jpbi9jbGkvc2hhcmVkL3R5cGVzXCI7XG5pbXBvcnQgeyBTU01fRE9NQUlOX1NUUiB9IGZyb20gXCIuLi9iaW4vY2xpL3NoYXJlZC9jb25zdGFudHNcIjtcbmltcG9ydCB7IHRydW5jYXRlU3RyaW5nIH0gZnJvbSBcIi4vdXRpbGl0eVwiO1xuXG5pbnRlcmZhY2UgSUNvbmZpZ1Byb3BzIHtcbiAgY2hhbmdlVXJpOiBjbG91ZGZyb250LkZ1bmN0aW9uO1xuICBjZXJ0aWZpY2F0ZUFybj86IHN0cmluZztcbiAgaG9zdGluZ0NvbmZpZ3VyYXRpb246IEhvc3RpbmdDb25maWd1cmF0aW9uO1xufVxuXG5cblxuZXhwb3J0IGNsYXNzIEhvc3RpbmdJbmZyYXN0cnVjdHVyZSBleHRlbmRzIENvbnN0cnVjdCB7XG4gIFxuICBwdWJsaWMgcmVhZG9ubHkgaG9zdGluZ0J1Y2tldDogSUJ1Y2tldDtcbiAgcHVibGljIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbjogY2xvdWRmcm9udC5EaXN0cmlidXRpb247XG5cblxuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHBhcmFtczogSUNvbmZpZ1Byb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGxldCBzM0xvZ3M7XG4gICAgLypcbiAgICAvL1RPRE8gYWRkIGNvbmRpdGlvbiB0byBhY3RpdmF0ZSBsb2dzXG4gICAgczNMb2dzID0gbmV3IHMzLkJ1Y2tldCh0aGlzLCBcIkxvZ3NCdWNrZXRcIiwge1xuICAgICAgZW5jcnlwdGlvbjogczMuQnVja2V0RW5jcnlwdGlvbi5TM19NQU5BR0VELFxuICAgICAgYmxvY2tQdWJsaWNBY2Nlc3M6IHMzLkJsb2NrUHVibGljQWNjZXNzLkJMT0NLX0FMTCxcbiAgICAgIG9iamVjdE93bmVyc2hpcDogczMuT2JqZWN0T3duZXJzaGlwLk9CSkVDVF9XUklURVIsXG4gICAgICBlbmZvcmNlU1NMOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgYWRkQ2ZuU3VwcHJlc3NSdWxlcyhzM0xvZ3MsIFtcbiAgICAgIHtcbiAgICAgICAgaWQ6IFwiVzM1XCIsXG4gICAgICAgIHJlYXNvbjogXCJJdCBpcyBhIGxvZyBidWNrZXQsIG5vdCBuZWVkIHRvIGhhdmUgYWNjZXNzIGxvZ2dpbmcgZW5hYmxlZC5cIixcbiAgICAgIH0sXG4gICAgXSk7XG4gICAgYWRkQ2ZuU3VwcHJlc3NSdWxlcyhzM0xvZ3MsIFtcbiAgICAgIHtcbiAgICAgICAgaWQ6IFwiVzUxXCIsXG4gICAgICAgIHJlYXNvbjogXCJJdCBpcyBhIGxvZyBidWNrZXQsIG5vdCBuZWVkIGZvciBhIGJ1Y2tldCBwb2xpY3kuXCIsXG4gICAgICB9LFxuICAgIF0pO1xuICAgICovXG4gICAgdGhpcy5ob3N0aW5nQnVja2V0ID0gbmV3IHMzLkJ1Y2tldCh0aGlzLCBcIkhvc3RpbmdCdWNrZXRcIiwge1xuICAgICAgdmVyc2lvbmVkOiBmYWxzZSxcbiAgICAgIC4uLihzM0xvZ3MgPyB7IHNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQ6IHMzTG9ncyB9IDoge30pLFxuICAgICAgZW5mb3JjZVNTTDogdHJ1ZSxcbiAgICAgIGVuY3J5cHRpb246IHMzLkJ1Y2tldEVuY3J5cHRpb24uUzNfTUFOQUdFRCxcbiAgICAgIGJsb2NrUHVibGljQWNjZXNzOiBuZXcgczMuQmxvY2tQdWJsaWNBY2Nlc3Moe1xuICAgICAgICBibG9ja1B1YmxpY1BvbGljeTogdHJ1ZSxcbiAgICAgICAgYmxvY2tQdWJsaWNBY2xzOiB0cnVlLFxuICAgICAgICBpZ25vcmVQdWJsaWNBY2xzOiB0cnVlLFxuICAgICAgICByZXN0cmljdFB1YmxpY0J1Y2tldHM6IHRydWUsXG4gICAgICB9KSxcbiAgICB9KTtcblxuXG4gICAgY29uc3QgczNvcmlnaW4gPSBvcmlnaW5zLlMzQnVja2V0T3JpZ2luLndpdGhPcmlnaW5BY2Nlc3NDb250cm9sKHRoaXMuaG9zdGluZ0J1Y2tldCk7XG5cbiAgICBjb25zdCBteVJlc3BvbnNlSGVhZGVyc1BvbGljeSA9IG5ldyBjbG91ZGZyb250LlJlc3BvbnNlSGVhZGVyc1BvbGljeShcbiAgICAgIHRoaXMsXG4gICAgICBcIlJlc3BvbnNlSGVhZGVyc1BvbGljeVwiLFxuICAgICAge1xuICAgICAgICByZXNwb25zZUhlYWRlcnNQb2xpY3lOYW1lOiBcIlJlc3BvbnNlSGVhZGVyc1BvbGljeVwiICsgU3RhY2sub2YodGhpcykuc3RhY2tOYW1lICsgXCItXCIgKyBTdGFjay5vZih0aGlzKS5yZWdpb24sXG4gICAgICAgIGNvbW1lbnQ6IFwiUmVzcG9uc2VIZWFkZXJzUG9saWN5XCIgKyBTdGFjay5vZih0aGlzKS5zdGFja05hbWUgKyBcIi1cIiArIFN0YWNrLm9mKHRoaXMpLnJlZ2lvbixcbiAgICAgICAgc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3I6IHtcbiAgICAgICAgICBjb250ZW50VHlwZU9wdGlvbnM6IHsgb3ZlcnJpZGU6IHRydWUgfSxcbiAgICAgICAgICBmcmFtZU9wdGlvbnM6IHtcbiAgICAgICAgICAgIGZyYW1lT3B0aW9uOiBjbG91ZGZyb250LkhlYWRlcnNGcmFtZU9wdGlvbi5ERU5ZLFxuICAgICAgICAgICAgb3ZlcnJpZGU6IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgICByZWZlcnJlclBvbGljeToge1xuICAgICAgICAgICAgcmVmZXJyZXJQb2xpY3k6XG4gICAgICAgICAgICAgIGNsb3VkZnJvbnQuSGVhZGVyc1JlZmVycmVyUG9saWN5LlNUUklDVF9PUklHSU5fV0hFTl9DUk9TU19PUklHSU4sXG4gICAgICAgICAgICBvdmVycmlkZTogZmFsc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBzdHJpY3RUcmFuc3BvcnRTZWN1cml0eToge1xuICAgICAgICAgICAgYWNjZXNzQ29udHJvbE1heEFnZTogRHVyYXRpb24uc2Vjb25kcygzMTUzNjAwMCksXG4gICAgICAgICAgICBpbmNsdWRlU3ViZG9tYWluczogdHJ1ZSxcbiAgICAgICAgICAgIG92ZXJyaWRlOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgeHNzUHJvdGVjdGlvbjogeyBwcm90ZWN0aW9uOiB0cnVlLCBtb2RlQmxvY2s6IHRydWUsIG92ZXJyaWRlOiB0cnVlIH0sXG4gICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHJlbW92ZUhlYWRlcnM6IFsnYWdlJyAsICdkYXRlJ10sXG4gICAgICB9XG4gICAgKTtcblxuICAgIGNvbnN0IGRlZmF1bHRDYWNoZVBvbGljeSA9IG5ldyBjbG91ZGZyb250LkNhY2hlUG9saWN5KFxuICAgICAgdGhpcyxcbiAgICAgIFwiRGVmYXVsdENhY2hlUG9saWN5XCIsXG4gICAgICB7XG4gICAgICAgIGNhY2hlUG9saWN5TmFtZTogXCJDYWNoZVBvbGljeVwiICsgU3RhY2sub2YodGhpcykuc3RhY2tOYW1lICsgXCItXCIgKyBTdGFjay5vZih0aGlzKS5yZWdpb24sXG4gICAgICAgIGNvbW1lbnQ6IFwiRGVmYXVsdCBwb2xpY3kgLSBcIiArIFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZSArIFwiLVwiICsgU3RhY2sub2YodGhpcykucmVnaW9uLFxuICAgICAgICBkZWZhdWx0VHRsOiBEdXJhdGlvbi5kYXlzKDM2NSksXG4gICAgICAgIG1pblR0bDogRHVyYXRpb24uZGF5cygzNjUpLFxuICAgICAgICBtYXhUdGw6IER1cmF0aW9uLmRheXMoMzY1KSxcbiAgICAgICAgY29va2llQmVoYXZpb3I6IGNsb3VkZnJvbnQuQ2FjaGVDb29raWVCZWhhdmlvci5ub25lKCksXG4gICAgICAgIGhlYWRlckJlaGF2aW9yOiBjbG91ZGZyb250LkNhY2hlSGVhZGVyQmVoYXZpb3Iubm9uZSgpLFxuICAgICAgICBxdWVyeVN0cmluZ0JlaGF2aW9yOiBjbG91ZGZyb250LkNhY2hlUXVlcnlTdHJpbmdCZWhhdmlvci5ub25lKCksXG4gICAgICAgIGVuYWJsZUFjY2VwdEVuY29kaW5nR3ppcDogdHJ1ZSxcbiAgICAgICAgZW5hYmxlQWNjZXB0RW5jb2RpbmdCcm90bGk6IHRydWUsXG4gICAgICB9XG4gICAgKTtcblxuICAgIGNvbnN0IGltZ0NhY2hlUG9saWN5ID0gbmV3IGNsb3VkZnJvbnQuQ2FjaGVQb2xpY3kodGhpcywgXCJJbWFnZXNDYWNoZVBvbGljeVwiLCB7XG4gICAgICBjYWNoZVBvbGljeU5hbWU6IFwiSW1hZ2VzQ2FjaGVQb2xpY3lcIiArIFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZSArIFwiLVwiICsgU3RhY2sub2YodGhpcykucmVnaW9uLFxuICAgICAgY29tbWVudDogXCJJbWFnZXMgY2FjaGUgcG9saWN5IC0gXCIgKyBTdGFjay5vZih0aGlzKS5zdGFja05hbWUgKyBcIi1cIiArIFN0YWNrLm9mKHRoaXMpLnJlZ2lvbixcbiAgICAgIGRlZmF1bHRUdGw6IER1cmF0aW9uLmRheXMoMzY1KSxcbiAgICAgIG1pblR0bDogRHVyYXRpb24uZGF5cygzNjUpLFxuICAgICAgbWF4VHRsOiBEdXJhdGlvbi5kYXlzKDM2NSksXG4gICAgICBjb29raWVCZWhhdmlvcjogY2xvdWRmcm9udC5DYWNoZUNvb2tpZUJlaGF2aW9yLm5vbmUoKSxcbiAgICAgIGhlYWRlckJlaGF2aW9yOiBjbG91ZGZyb250LkNhY2hlSGVhZGVyQmVoYXZpb3Iubm9uZSgpLFxuICAgICAgcXVlcnlTdHJpbmdCZWhhdmlvcjogY2xvdWRmcm9udC5DYWNoZVF1ZXJ5U3RyaW5nQmVoYXZpb3Iubm9uZSgpLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgc3RhdGljQXNzZXRzQ2FjaGVQb2xpY3kgPSBuZXcgY2xvdWRmcm9udC5DYWNoZVBvbGljeSh0aGlzLCBcInN0YXRpY0Fzc2V0c0NhY2hlUG9saWN5XCIsIHtcbiAgICAgIGNhY2hlUG9saWN5TmFtZTogXCJTdGF0aWNBc3NldHNDYWNoZVBvbGljeVwiICsgU3RhY2sub2YodGhpcykuc3RhY2tOYW1lICsgXCItXCIgKyBTdGFjay5vZih0aGlzKS5yZWdpb24sXG4gICAgICBjb21tZW50OiBcIlN0YXRpYyBhc3NldHMgY2FjaGUgcG9saWN5IC0gXCIgKyBTdGFjay5vZih0aGlzKS5zdGFja05hbWUgKyBcIi1cIiArIFN0YWNrLm9mKHRoaXMpLnJlZ2lvbixcbiAgICAgIGRlZmF1bHRUdGw6IER1cmF0aW9uLmRheXMoMzY1KSxcbiAgICAgIG1pblR0bDogRHVyYXRpb24uZGF5cygzNjUpLFxuICAgICAgbWF4VHRsOiBEdXJhdGlvbi5kYXlzKDM2NSksXG4gICAgICBjb29raWVCZWhhdmlvcjogY2xvdWRmcm9udC5DYWNoZUNvb2tpZUJlaGF2aW9yLm5vbmUoKSxcbiAgICAgIGhlYWRlckJlaGF2aW9yOiBjbG91ZGZyb250LkNhY2hlSGVhZGVyQmVoYXZpb3Iubm9uZSgpLFxuICAgICAgcXVlcnlTdHJpbmdCZWhhdmlvcjogY2xvdWRmcm9udC5DYWNoZVF1ZXJ5U3RyaW5nQmVoYXZpb3Iubm9uZSgpLFxuICAgIH0pO1xuXG4gICAgY29uc3QgZGVmYXVsdEJlaGF2aW9yOiBjbG91ZGZyb250LkJlaGF2aW9yT3B0aW9ucyA9IHtcbiAgICAgIG9yaWdpbjogczNvcmlnaW4sXG4gICAgICByZXNwb25zZUhlYWRlcnNQb2xpY3k6IG15UmVzcG9uc2VIZWFkZXJzUG9saWN5LFxuICAgICAgY2FjaGVQb2xpY3k6IGRlZmF1bHRDYWNoZVBvbGljeSxcbiAgICAgIGFsbG93ZWRNZXRob2RzOiBjbG91ZGZyb250LkFsbG93ZWRNZXRob2RzLkFMTE9XX0dFVF9IRUFELFxuICAgICAgdmlld2VyUHJvdG9jb2xQb2xpY3k6IGNsb3VkZnJvbnQuVmlld2VyUHJvdG9jb2xQb2xpY3kuUkVESVJFQ1RfVE9fSFRUUFMsXG4gICAgICBmdW5jdGlvbkFzc29jaWF0aW9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgZnVuY3Rpb246IHBhcmFtcy5jaGFuZ2VVcmksXG4gICAgICAgICAgZXZlbnRUeXBlOiBjbG91ZGZyb250LkZ1bmN0aW9uRXZlbnRUeXBlLlZJRVdFUl9SRVFVRVNULFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuXG4gICAgY29uc3QgaW1nQmVoYXZpb3VyOiBjbG91ZGZyb250LkJlaGF2aW9yT3B0aW9ucyA9IHtcbiAgICAgIG9yaWdpbjogczNvcmlnaW4sXG4gICAgICByZXNwb25zZUhlYWRlcnNQb2xpY3k6IG15UmVzcG9uc2VIZWFkZXJzUG9saWN5LFxuICAgICAgY2FjaGVQb2xpY3k6IGltZ0NhY2hlUG9saWN5LFxuICAgICAgYWxsb3dlZE1ldGhvZHM6IGNsb3VkZnJvbnQuQWxsb3dlZE1ldGhvZHMuQUxMT1dfR0VUX0hFQUQsXG4gICAgICB2aWV3ZXJQcm90b2NvbFBvbGljeTogY2xvdWRmcm9udC5WaWV3ZXJQcm90b2NvbFBvbGljeS5SRURJUkVDVF9UT19IVFRQUyxcbiAgICAgIGZ1bmN0aW9uQXNzb2NpYXRpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBmdW5jdGlvbjogcGFyYW1zLmNoYW5nZVVyaSxcbiAgICAgICAgICBldmVudFR5cGU6IGNsb3VkZnJvbnQuRnVuY3Rpb25FdmVudFR5cGUuVklFV0VSX1JFUVVFU1QsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG5cbiAgICBjb25zdCBzdGF0aWNBc3NldHNCZWhhdmlvdXI6IGNsb3VkZnJvbnQuQmVoYXZpb3JPcHRpb25zID0ge1xuICAgICAgb3JpZ2luOiBzM29yaWdpbixcbiAgICAgIGNvbXByZXNzOiB0cnVlLFxuICAgICAgcmVzcG9uc2VIZWFkZXJzUG9saWN5OiBteVJlc3BvbnNlSGVhZGVyc1BvbGljeSxcbiAgICAgIGNhY2hlUG9saWN5OiBzdGF0aWNBc3NldHNDYWNoZVBvbGljeSxcbiAgICAgIGFsbG93ZWRNZXRob2RzOiBjbG91ZGZyb250LkFsbG93ZWRNZXRob2RzLkFMTE9XX0dFVF9IRUFELFxuICAgICAgdmlld2VyUHJvdG9jb2xQb2xpY3k6IGNsb3VkZnJvbnQuVmlld2VyUHJvdG9jb2xQb2xpY3kuUkVESVJFQ1RfVE9fSFRUUFMsXG4gICAgICBmdW5jdGlvbkFzc29jaWF0aW9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgZnVuY3Rpb246IHBhcmFtcy5jaGFuZ2VVcmksXG4gICAgICAgICAgZXZlbnRUeXBlOiBjbG91ZGZyb250LkZ1bmN0aW9uRXZlbnRUeXBlLlZJRVdFUl9SRVFVRVNULFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuXG5cbiAgICBsZXQgY2ZMb2dzO1xuICAgIC8qXG4gICAgLy9UT0RPIGFkZCBjb25kaXRpb24gdG8gYWN0aXZhdGUgbG9nc1xuICAgIGNmTG9ncyA9IG5ldyBzMy5CdWNrZXQodGhpcywgXCJDbG91ZGZyb250TG9nc0J1Y2tldFwiLCB7XG4gICAgICBvYmplY3RPd25lcnNoaXA6IHMzLk9iamVjdE93bmVyc2hpcC5PQkpFQ1RfV1JJVEVSLFxuICAgICAgZW5jcnlwdGlvbjogczMuQnVja2V0RW5jcnlwdGlvbi5TM19NQU5BR0VELFxuICAgICAgYmxvY2tQdWJsaWNBY2Nlc3M6IHMzLkJsb2NrUHVibGljQWNjZXNzLkJMT0NLX0FMTCxcbiAgICAgIGVuZm9yY2VTU0w6IHRydWUsXG4gICAgfSk7XG5cbiAgICBOYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnMoY2ZMb2dzLCBbXG4gICAgICB7XG4gICAgICAgIGlkOiBcIkF3c1NvbHV0aW9ucy1TMVwiLFxuICAgICAgICByZWFzb246IFwiSXQgaXMgYSBsb2cgYnVja2V0LCBub3QgbmVlZCB0byBoYXZlIGFjY2VzcyBsb2dnaW5nIGVuYWJsZWQuXCIsXG4gICAgICB9LFxuICAgIF0pO1xuXG4gICAgYWRkQ2ZuU3VwcHJlc3NSdWxlcyhjZkxvZ3MsIFtcbiAgICAgIHtcbiAgICAgICAgaWQ6IFwiVzM1XCIsXG4gICAgICAgIHJlYXNvbjogXCJJdCBpcyBhIGxvZyBidWNrZXQsIG5vdCBuZWVkIHRvIGhhdmUgYWNjZXNzIGxvZ2dpbmcgZW5hYmxlZC5cIixcbiAgICAgIH0sXG4gICAgXSk7XG4gICAgYWRkQ2ZuU3VwcHJlc3NSdWxlcyhjZkxvZ3MsIFtcbiAgICAgIHtcbiAgICAgICAgaWQ6IFwiVzUxXCIsXG4gICAgICAgIHJlYXNvbjogXCJJdCBpcyBhIGxvZyBidWNrZXQsIG5vdCBuZWVkIGZvciBhIGJ1Y2tldCBwb2xpY3kuXCIsXG4gICAgICB9LFxuICAgIF0pOyovXG5cblxuXG4gICAgdGhpcy5kaXN0cmlidXRpb24gPSBuZXcgY2xvdWRmcm9udC5EaXN0cmlidXRpb24odGhpcywgXCJEaXN0cmlidXRpb25cIiwge1xuICAgICAgY29tbWVudDogXCJTdGF0aWMgaG9zdGluZyAtIFwiICsgU3RhY2sub2YodGhpcykuc3RhY2tOYW1lLFxuICAgICAgZGVmYXVsdFJvb3RPYmplY3Q6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgaHR0cFZlcnNpb246IGNsb3VkZnJvbnQuSHR0cFZlcnNpb24uSFRUUDJfQU5EXzMsXG4gICAgICAuLi4oY2ZMb2dzID8geyBlbmFibGVMb2dnaW5nOiB0cnVlIH0gOiB7fSksXG4gICAgICAuLi4oY2ZMb2dzID8geyBsb2dCdWNrZXQ6IGNmTG9ncyB9IDoge30pLFxuICAgICAgLi4uKGNmTG9ncyA/IHsgbG9nRmlsZVByZWZpeDogXCJkaXN0cmlidXRpb24tYWNjZXNzLWxvZ3MvXCIgfSA6IHt9KSxcbiAgICAgIG1pbmltdW1Qcm90b2NvbFZlcnNpb246IGNsb3VkZnJvbnQuU2VjdXJpdHlQb2xpY3lQcm90b2NvbC5UTFNfVjFfMl8yMDIxLFxuICAgICAgZGVmYXVsdEJlaGF2aW9yOiBkZWZhdWx0QmVoYXZpb3IsXG4gICAgICBhZGRpdGlvbmFsQmVoYXZpb3JzOiB7XG4gICAgICAgIFwiKi5qcGdcIjogaW1nQmVoYXZpb3VyLFxuICAgICAgICBcIiouanBlZ1wiOiBpbWdCZWhhdmlvdXIsXG4gICAgICAgIFwiKi5wbmdcIjogaW1nQmVoYXZpb3VyLFxuICAgICAgICBcIiouZ2lmXCI6IGltZ0JlaGF2aW91cixcbiAgICAgICAgXCIqLmJtcFwiOiBpbWdCZWhhdmlvdXIsXG4gICAgICAgIFwiKi50aWZmXCI6IGltZ0JlaGF2aW91cixcbiAgICAgICAgXCIqLmljb1wiOiBpbWdCZWhhdmlvdXIsXG4gICAgICAgIFwiKi5qc1wiOiBzdGF0aWNBc3NldHNCZWhhdmlvdXIsXG4gICAgICAgIFwiKi5jc3NcIjogc3RhdGljQXNzZXRzQmVoYXZpb3VyLFxuICAgICAgICBcIiouaHRtbFwiOiBzdGF0aWNBc3NldHNCZWhhdmlvdXIsXG4gICAgICB9LFxuICAgICAgLi4uKHBhcmFtcy5ob3N0aW5nQ29uZmlndXJhdGlvbi5kb21haW5OYW1lICYmIHBhcmFtcy5jZXJ0aWZpY2F0ZUFyblxuICAgICAgICA/IHtcbiAgICAgICAgICAgIGRvbWFpbk5hbWVzOiBnZXREb21haW5OYW1lcyhwYXJhbXMuaG9zdGluZ0NvbmZpZ3VyYXRpb24uZG9tYWluTmFtZSksXG4gICAgICAgICAgICBjZXJ0aWZpY2F0ZTogYWNtLkNlcnRpZmljYXRlLmZyb21DZXJ0aWZpY2F0ZUFybihcbiAgICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICAgICAgXCJDZXJ0aWZpY2F0ZVwiLFxuICAgICAgICAgICAgICBwYXJhbXMuY2VydGlmaWNhdGVBcm5cbiAgICAgICAgICAgICksXG4gICAgICAgICAgfVxuICAgICAgICA6IHt9KSxcbiAgICB9KTtcblxuICAgIE5hZ1N1cHByZXNzaW9ucy5hZGRSZXNvdXJjZVN1cHByZXNzaW9ucyh0aGlzLmRpc3RyaWJ1dGlvbiwgW1xuICAgICAge1xuICAgICAgICBpZDogXCJBd3NTb2x1dGlvbnMtQ0ZSNFwiLFxuICAgICAgICByZWFzb246XG4gICAgICAgICAgXCJBIGNlcnRpZmljYXRlIHdpdGggbWluIFRMUyAxLjIgaXMgc2VsZWN0ZWQgaWYgdGhlIHVzZXIgaGFzIGEgY3VzdG9tIGRvbWFpblwiLFxuICAgICAgfSxcbiAgICBdKTtcblxuXG5cbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsIFwiRG9tYWluTmFtZVwiLCB7XG4gICAgICB2YWx1ZTogXCJodHRwczovL1wiICsgdGhpcy5kaXN0cmlidXRpb24uZG9tYWluTmFtZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHN0YWNrTmFtZSA9IGNhbGN1bGF0ZU1haW5TdGFja05hbWUocGFyYW1zLmhvc3RpbmdDb25maWd1cmF0aW9uKTtcblxuXG4gICAgbmV3IHNzbS5TdHJpbmdQYXJhbWV0ZXIodGhpcywgJ1NTTUNvbm5lY3Rpb25SZWdpb24nLCB7XG4gICAgICBwYXJhbWV0ZXJOYW1lOiAnLycgKyBzdGFja05hbWUgKyAnLycgKyBTU01fRE9NQUlOX1NUUiwgXG4gICAgICBzdHJpbmdWYWx1ZTogdGhpcy5kaXN0cmlidXRpb24uZG9tYWluTmFtZSxcbiAgICB9KTtcblxuXG4gIH1cbn1cbiJdfQ==