UNPKG

@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
"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==