UNPKG

@aws/pdk

Version:

All documentation is located at: https://aws.github.io/aws-pdk

228 lines 38.4 kB
"use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.StaticWebsiteOrigin = exports.StaticWebsite = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); /*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ const monorepo_1 = require("../monorepo"); const pdk_nag_1 = require("../pdk-nag"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const aws_cloudfront_1 = require("aws-cdk-lib/aws-cloudfront"); const aws_cloudfront_origins_1 = require("aws-cdk-lib/aws-cloudfront-origins"); const aws_s3_1 = require("aws-cdk-lib/aws-s3"); const aws_s3_deployment_1 = require("aws-cdk-lib/aws-s3-deployment"); const cdk_nag_1 = require("cdk-nag"); const constructs_1 = require("constructs"); const cloudfront_web_acl_1 = require("./cloudfront-web-acl"); const lazy_token_renderer_1 = require("./lazy-token-renderer"); const DEFAULT_RUNTIME_CONFIG_FILENAME = "runtime-config.json"; /** * Deploys a Static Website using by default a private S3 bucket as an origin and Cloudfront as the entrypoint. * * This construct configures a webAcl containing rules that are generally applicable to web applications. This * provides protection against exploitation of a wide range of vulnerabilities, including some of the high risk * and commonly occurring vulnerabilities described in OWASP publications such as OWASP Top 10. * */ class StaticWebsite extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); this.validateProps = (props) => { this.validateEncryptionSettings(props); props.runtimeOptions && this.validateRuntimeConfig(props.runtimeOptions); props.websiteBucket && this.validateBucketConfig(props.websiteBucket); }; this.validateRuntimeConfig = (config) => { if (!config) { throw new Error("validateRuntimeConfig only accepts non-null RuntimeOptions."); } if (config.jsonFileName && !config.jsonFileName.endsWith(".json")) { throw new Error("RuntimeOptions.jsonFileName must be a json file."); } }; this.validateBucketConfig = (bucket) => { if (bucket.isWebsite) { throw new Error("Website buckets cannot be configured as websites as this will break Cloudfront hosting!"); } }; this.validateEncryptionSettings = ({ defaultWebsiteBucketEncryption, defaultWebsiteBucketEncryptionKey, }) => { if (defaultWebsiteBucketEncryptionKey && defaultWebsiteBucketEncryption !== aws_s3_1.BucketEncryption.KMS) { throw new Error("Bucket encryption should be set to KMS if providing a defaultWebsiteBucketEncryptionKey."); } if (defaultWebsiteBucketEncryption && defaultWebsiteBucketEncryption !== aws_s3_1.BucketEncryption.KMS && defaultWebsiteBucketEncryption !== aws_s3_1.BucketEncryption.S3_MANAGED) { throw new Error("Only KMS and S3_MANAGED encryption are supported on the default bucket."); } }; this.suppressCDKNagViolations = (props) => { const stack = aws_cdk_lib_1.Stack.of(this); !props.distributionProps?.certificate && [ "AwsSolutions-CFR4", "AwsPrototyping-CloudFrontDistributionHttpsViewerNoOutdatedSSL", ].forEach((RuleId) => { cdk_nag_1.NagSuppressions.addResourceSuppressions(this.cloudFrontDistribution, [ { id: RuleId, reason: "Certificate is not mandatory therefore the Cloudfront certificate will be used.", }, ]); }); ["AwsSolutions-L1", "AwsPrototyping-LambdaLatestVersion"].forEach((RuleId) => { cdk_nag_1.NagSuppressions.addResourceSuppressions(this, [ { id: RuleId, reason: "Latest runtime cannot be configured. CDK will need to upgrade the BucketDeployment construct accordingly.", }, ], true); }); ["AwsSolutions-IAM5", "AwsPrototyping-IAMNoWildcardPermissions"].forEach((RuleId) => { cdk_nag_1.NagSuppressions.addResourceSuppressions(this, [ { id: RuleId, reason: "All Policies have been scoped to a Bucket. Given Buckets can contain arbitrary content, wildcard resources with bucket scope are required.", appliesTo: [ { regex: "/^Action::s3:.*$/g", }, { regex: `/^Resource::.*$/g`, }, ], }, ], true); }); ["AwsSolutions-IAM4", "AwsPrototyping-IAMNoManagedPolicies"].forEach((RuleId) => { cdk_nag_1.NagSuppressions.addResourceSuppressions(this, [ { id: RuleId, reason: "Buckets can contain arbitrary content, therefore wildcard resources under a bucket are required.", appliesTo: [ { regex: `/^Policy::arn:${pdk_nag_1.PDKNag.getStackPartitionRegex(stack)}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole$/g`, }, ], }, ], true); }); ["AwsSolutions-S1", "AwsPrototyping-S3BucketLoggingEnabled"].forEach((RuleId) => { cdk_nag_1.NagSuppressions.addResourceSuppressions(this, [ { id: RuleId, reason: "Access Log buckets should not have s3 bucket logging", }, ], true); }); }; (0, monorepo_1.addMetric)(scope, "static-website"); this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true); this.validateProps(props); const accessLogsBucket = new aws_s3_1.Bucket(this, "AccessLogsBucket", { versioned: false, enforceSSL: true, autoDeleteObjects: true, removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY, encryption: aws_s3_1.BucketEncryption.S3_MANAGED, objectOwnership: aws_s3_1.ObjectOwnership.OBJECT_WRITER, publicReadAccess: false, blockPublicAccess: aws_s3_1.BlockPublicAccess.BLOCK_ALL, }); // S3 Bucket to hold website files this.websiteBucket = props.websiteBucket ?? new aws_s3_1.Bucket(this, "WebsiteBucket", { versioned: true, enforceSSL: true, autoDeleteObjects: true, removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY, encryption: props.defaultWebsiteBucketEncryption ?? aws_s3_1.BucketEncryption.S3_MANAGED, objectOwnership: aws_s3_1.ObjectOwnership.BUCKET_OWNER_ENFORCED, encryptionKey: props.defaultWebsiteBucketEncryptionKey, publicReadAccess: false, blockPublicAccess: aws_s3_1.BlockPublicAccess.BLOCK_ALL, serverAccessLogsPrefix: "website-access-logs", serverAccessLogsBucket: accessLogsBucket, }); // Web ACL const { distributionProps } = props; const webAclArn = distributionProps?.webAclId ?? (props.webAclProps?.disable ? undefined : new cloudfront_web_acl_1.CloudfrontWebAcl(this, "WebsiteAcl", props.webAclProps) .webAclArn); // Cloudfront Distribution const logBucket = props.distributionProps?.logBucket || new aws_s3_1.Bucket(this, "DistributionLogBucket", { enforceSSL: true, autoDeleteObjects: true, removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY, encryption: props.defaultWebsiteBucketEncryption ?? aws_s3_1.BucketEncryption.S3_MANAGED, objectOwnership: aws_s3_1.ObjectOwnership.BUCKET_OWNER_PREFERRED, encryptionKey: props.defaultWebsiteBucketEncryptionKey, publicReadAccess: false, blockPublicAccess: aws_s3_1.BlockPublicAccess.BLOCK_ALL, serverAccessLogsPrefix: "distribution-access-logs", serverAccessLogsBucket: accessLogsBucket, }); const defaultRootObject = distributionProps?.defaultRootObject ?? "index.html"; this.cloudFrontDistribution = new aws_cloudfront_1.Distribution(this, "CloudfrontDistribution", { ...distributionProps, webAclId: webAclArn, enableLogging: true, logBucket: logBucket, defaultBehavior: { ...distributionProps?.defaultBehavior, origin: aws_cloudfront_origins_1.S3BucketOrigin.withOriginAccessControl(this.websiteBucket), viewerProtocolPolicy: aws_cloudfront_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS, }, defaultRootObject, // We need to redirect "key not found errors" to index.html for single page apps errorResponses: distributionProps?.errorResponses ?? [403, 404].map((httpStatus) => ({ httpStatus, responseHttpStatus: 200, responsePagePath: `/${defaultRootObject}`, })), }); // Deploy Website this.bucketDeployment = new aws_s3_deployment_1.BucketDeployment(this, "WebsiteDeployment", { memoryLimit: 2048, ...props.bucketDeploymentProps, sources: [ aws_s3_deployment_1.Source.asset(props.websiteContentPath), ...(props.runtimeOptions ? [ aws_s3_deployment_1.Source.jsonData(props.runtimeOptions?.jsonFileName || DEFAULT_RUNTIME_CONFIG_FILENAME, (0, lazy_token_renderer_1.lazilyRender)(this, props.runtimeOptions.jsonPayload)), ] : []), ], destinationBucket: this.websiteBucket, // Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket. distribution: this.cloudFrontDistribution, }); new aws_cdk_lib_1.CfnOutput(this, "DistributionDomainName", { value: this.cloudFrontDistribution.domainName, }); this.suppressCDKNagViolations(props); } } exports.StaticWebsite = StaticWebsite; _a = JSII_RTTI_SYMBOL_1; StaticWebsite[_a] = { fqn: "@aws/pdk.static_website.StaticWebsite", version: "0.26.14" }; /** * If passing in distributionProps, the default behaviour.origin is a required parameter. An instance of this class can be passed in * to make the compiler happy. */ class StaticWebsiteOrigin { bind(_scope, _options) { throw new Error("This should never be called"); } } exports.StaticWebsiteOrigin = StaticWebsiteOrigin; _b = JSII_RTTI_SYMBOL_1; StaticWebsiteOrigin[_b] = { fqn: "@aws/pdk.static_website.StaticWebsiteOrigin", version: "0.26.14" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljLXdlYnNpdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzdGF0aWMtd2Vic2l0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBO3NDQUNzQztBQUN0Qyw0Q0FBMEM7QUFDMUMsMENBQXNDO0FBQ3RDLDZDQUE4RDtBQUM5RCwrREFNb0M7QUFDcEMsK0VBQW9FO0FBRXBFLCtDQU00QjtBQUM1QixxRUFBeUU7QUFDekUscUNBQTBDO0FBQzFDLDJDQUF1QztBQUV2Qyw2REFBK0U7QUFFL0UsK0RBQXFEO0FBRXJELE1BQU0sK0JBQStCLEdBQUcscUJBQXFCLENBQUM7QUEyRjlEOzs7Ozs7O0dBT0c7QUFDSCxNQUFhLGFBQWMsU0FBUSxzQkFBUztJQUsxQyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXlCO1FBQ2pFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUF5SFgsa0JBQWEsR0FBRyxDQUFDLEtBQXlCLEVBQUUsRUFBRTtZQUNwRCxJQUFJLENBQUMsMEJBQTBCLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdkMsS0FBSyxDQUFDLGNBQWMsSUFBSSxJQUFJLENBQUMscUJBQXFCLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ3pFLEtBQUssQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN4RSxDQUFDLENBQUM7UUFFTSwwQkFBcUIsR0FBRyxDQUFDLE1BQXNCLEVBQUUsRUFBRTtZQUN6RCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ1osTUFBTSxJQUFJLEtBQUssQ0FDYiw2REFBNkQsQ0FDOUQsQ0FBQztZQUNKLENBQUM7WUFFRCxJQUFJLE1BQU0sQ0FBQyxZQUFZLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNsRSxNQUFNLElBQUksS0FB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Q0FDckQ7cUJBQ0Y7b0JBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQzthQUNSO1lBQ0QsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLGFBQWE7WUFDckMsa0hBQWtIO1lBQ2xILFlBQVksRUFBRSxJQUFJLENBQUMsc0JBQXNCO1NBQzFDLENBQUMsQ0FBQztRQUVILElBQUksdUJBQVMsQ0FBQyxJQUFJLEVBQUUsd0JBQXdCLEVBQUU7WUFDNUMsS0FBSyxFQUFFLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVO1NBQzlDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN2QyxDQUFDOztBQTdISCxzQ0ErUUM7OztBQUVEOzs7R0FHRztBQUNILE1BQWEsbUJBQW1CO0lBQzlCLElBQUksQ0FBQyxNQUFpQixFQUFFLFFBQTJCO1FBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQztJQUNqRCxDQUFDOztBQUhILGtEQUlDIiwic291cmNlc0NvbnRlbnQiOlsiLyohIENvcHlyaWdodCBbQW1hem9uLmNvbV0oaHR0cDovL2FtYXpvbi5jb20vKSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wICovXG5pbXBvcnQgeyBhZGRNZXRyaWMgfSBmcm9tIFwiQGF3cy9tb25vcmVwb1wiO1xuaW1wb3J0IHsgUERLTmFnIH0gZnJvbSBcIkBhd3MvcGRrLW5hZ1wiO1xuaW1wb3J0IHsgQ2ZuT3V0cHV0LCBSZW1vdmFsUG9saWN5LCBTdGFjayB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHtcbiAgRGlzdHJpYnV0aW9uLFxuICBJT3JpZ2luLFxuICBPcmlnaW5CaW5kQ29uZmlnLFxuICBPcmlnaW5CaW5kT3B0aW9ucyxcbiAgVmlld2VyUHJvdG9jb2xQb2xpY3ksXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udFwiO1xuaW1wb3J0IHsgUzNCdWNrZXRPcmlnaW4gfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnQtb3JpZ2luc1wiO1xuaW1wb3J0IHsgS2V5IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1rbXNcIjtcbmltcG9ydCB7XG4gIEJsb2NrUHVibGljQWNjZXNzLFxuICBCdWNrZXQsXG4gIEJ1Y2tldEVuY3J5cHRpb24sXG4gIElCdWNrZXQsXG4gIE9iamVjdE93bmVyc2hpcCxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1zM1wiO1xuaW1wb3J0IHsgQnVja2V0RGVwbG95bWVudCwgU291cmNlIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1zMy1kZXBsb3ltZW50XCI7XG5pbXBvcnQgeyBOYWdTdXBwcmVzc2lvbnMgfSBmcm9tIFwiY2RrLW5hZ1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IEJ1Y2tldERlcGxveW1lbnRQcm9wcyB9IGZyb20gXCIuL2J1Y2tldC1kZXBsb3ltZW50LXByb3BzXCI7XG5pbXBvcnQgeyBDbG91ZGZyb250V2ViQWNsLCBDbG91ZEZyb250V2ViQWNsUHJvcHMgfSBmcm9tIFwiLi9jbG91ZGZyb250LXdlYi1hY2xcIjtcbmltcG9ydCB7IERpc3RyaWJ1dGlvblByb3BzIH0gZnJvbSBcIi4vZGlzdHJpYnV0aW9uLXByb3BzXCI7XG5pbXBvcnQgeyBsYXppbHlSZW5kZXIgfSBmcm9tIFwiLi9sYXp5LXRva2VuLXJlbmRlcmVyXCI7XG5cbmNvbnN0IERFRkFVTFRfUlVOVElNRV9DT05GSUdfRklMRU5BTUUgPSBcInJ1bnRpbWUtY29uZmlnLmpzb25cIjtcblxuLyoqXG4gKiBEeW5hbWljIGNvbmZpZ3VyYXRpb24gd2hpY2ggZ2V0cyByZXNvbHZlZCBvbmx5IGR1cmluZyBkZXBsb3ltZW50LlxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogLy8gV2lsbCBzdG9yZSBhIEpTT04gZmlsZSBjYWxsZWQgcnVudGltZS1jb25maWcuanNvbiBpbiB0aGUgcm9vdCBvZiB0aGUgU3RhdGljV2Vic2l0ZSBTMyBidWNrZXQgY29udGFpbmluZyBhbnlcbiAqIC8vIGFuZCBhbGwgcmVzb2x2ZWQgdmFsdWVzLlxuICogY29uc3QgcnVudGltZUNvbmZpZyA9IHtqc29uUGF5bG9hZDoge2J1Y2tldEFybjogczNCdWNrZXQuYnVja2V0QXJufX07XG4gKiBuZXcgU3RhdGljV2Vic2l0ZShzY29wZSwgJ1N0YXRpY1dlYnNpdGUnLCB7d2Vic2l0ZUNvbnRlbnRQYXRoOiAncGF0aC90by93ZWJzaXRlJywgcnVudGltZUNvbmZpZ30pO1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFJ1bnRpbWVPcHRpb25zIHtcbiAgLyoqXG4gICAqIEZpbGUgbmFtZSB0byBzdG9yZSBydW50aW1lIGNvbmZpZ3VyYXRpb24gKGpzb25QYXlsb2FkKS5cbiAgICpcbiAgICogTXVzdCBmb2xsb3cgcGF0dGVybjogJyouanNvbidcbiAgICpcbiAgICogQGRlZmF1bHQgXCJydW50aW1lLWNvbmZpZy5qc29uXCJcbiAgICovXG4gIHJlYWRvbmx5IGpzb25GaWxlTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogQXJiaXRyYXJ5IEpTT04gcGF5bG9hZCBjb250YWluaW5nIHJ1bnRpbWUgdmFsdWVzIHRvIGRlcGxveS4gVHlwaWNhbGx5IHRoaXMgY29udGFpbnMgcmVzb3VyY2VBcm5zLCBldGMgd2hpY2hcbiAgICogYXJlIG9ubHkga25vd24gYXQgZGVwbG95IHRpbWUuXG4gICAqXG4gICAqIEBleGFtcGxlIHsgdXNlclBvb2xJZDogc29tZS51c2VyUG9vbC51c2VyUG9vbElkLCBzb21lUmVzb3VyY2VBcm46IHNvbWUucmVzb3VyY2UuQXJuIH1cbiAgICovXG4gIHJlYWRvbmx5IGpzb25QYXlsb2FkOiBhbnk7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgY29uZmlndXJpbmcgdGhlIFN0YXRpY1dlYnNpdGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RhdGljV2Vic2l0ZVByb3BzIHtcbiAgLyoqXG4gICAqIFBhdGggdG8gdGhlIGRpcmVjdG9yeSBjb250YWluaW5nIHRoZSBzdGF0aWMgd2Vic2l0ZSBmaWxlcyBhbmQgYXNzZXRzLiBUaGlzIGRpcmVjdG9yeSBtdXN0IGNvbnRhaW4gYW4gaW5kZXguaHRtbCBmaWxlLlxuICAgKi9cbiAgcmVhZG9ubHkgd2Vic2l0ZUNvbnRlbnRQYXRoOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIER5bmFtaWMgY29uZmlndXJhdGlvbiB3aGljaCBnZXRzIHJlc29sdmVkIG9ubHkgZHVyaW5nIGRlcGxveW1lbnQuXG4gICAqL1xuICByZWFkb25seSBydW50aW1lT3B0aW9ucz86IFJ1bnRpbWVPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBCdWNrZXQgZW5jcnlwdGlvbiB0byB1c2UgZm9yIHRoZSBkZWZhdWx0IGJ1Y2tldC5cbiAgICpcbiAgICogU3VwcG9ydGVkIG9wdGlvbnMgYXJlIEtNUyBvciBTM01BTkFHRUQuXG4gICAqXG4gICAqIE5vdGU6IElmIHBsYW5uaW5nIHRvIHVzZSBLTVMsIGVuc3VyZSB5b3UgYXNzb2NpYXRlIGEgTGFtYmRhIEVkZ2UgZnVuY3Rpb24gdG8gc2lnbiByZXF1ZXN0cyB0byBTMyBhcyBPQUkgZG9lcyBub3QgY3VycmVudGx5IHN1cHBvcnQgS01TIGVuY3J5cHRpb24uIFJlZmVyIHRvIHtAbGluayBodHRwczovL2F3cy5hbWF6b24uY29tL2Jsb2dzL25ldHdvcmtpbmctYW5kLWNvbnRlbnQtZGVsaXZlcnkvc2VydmluZy1zc2Uta21zLWVuY3J5cHRlZC1jb250ZW50LWZyb20tczMtdXNpbmctY2xvdWRmcm9udC99XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gXCJTM01BTkFHRURcIlxuICAgKi9cbiAgcmVhZG9ubHkgZGVmYXVsdFdlYnNpdGVCdWNrZXRFbmNyeXB0aW9uPzogQnVja2V0RW5jcnlwdGlvbjtcblxuICAvKipcbiAgICogQSBwcmVkZWZpbmVkIEtNUyBjdXN0b21lciBlbmNyeXB0aW9uIGtleSB0byB1c2UgZm9yIHRoZSBkZWZhdWx0IGJ1Y2tldCB0aGF0IGdldHMgY3JlYXRlZC5cbiAgICpcbiAgICogTm90ZTogVGhpcyBpcyBvbmx5IHVzZWQgaWYgdGhlIHdlYnNpdGVCdWNrZXQgaXMgbGVmdCB1bmRlZmluZWQsIG90aGVyd2lzZSBhbGwgc2V0dGluZ3MgZnJvbSB0aGUgcHJvdmlkZWQgd2Vic2l0ZUJ1Y2tldCB3aWxsIGJlIHVzZWQuXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0V2Vic2l0ZUJ1Y2tldEVuY3J5cHRpb25LZXk/OiBLZXk7XG5cbiAgLyoqXG4gICAqIFByZWRlZmluZWQgYnVja2V0IHRvIGRlcGxveSB0aGUgd2Vic2l0ZSBpbnRvLlxuICAgKi9cbiAgcmVhZG9ubHkgd2Vic2l0ZUJ1Y2tldD86IElCdWNrZXQ7XG5cbiAgLyoqXG4gICAqIEN1c3RvbSBkaXN0cmlidXRpb24gcHJvcGVydGllcy5cbiAgICpcbiAgICogTm90ZTogZGVmYXVsdEJlaGF2aW91ci5vcmlnaW4gaXMgYSByZXF1aXJlZCBwYXJhbWV0ZXIsIGhvd2V2ZXIgaXQgd2lsbCBub3QgYmUgdXNlZCBhcyB0aGlzIGNvbnN0cnVjdCB3aWxsIHdpcmUgaXQgb24geW91ciBiZWhhbGYuXG4gICAqIFlvdSB3aWxsIG5lZWQgdG8gcGFzcyBpbiBhbiBpbnN0YW5jZSBvZiBTdGF0aWNXZWJzaXRlT3JpZ2luIChOb09wKSB0byBrZWVwIHRoZSBjb21waWxlciBoYXBweS5cbiAgICovXG4gIHJlYWRvbmx5IGRpc3RyaWJ1dGlvblByb3BzPzogRGlzdHJpYnV0aW9uUHJvcHM7XG5cbiAgLyoqXG4gICAqIEN1c3RvbSBidWNrZXQgZGVwbG95bWVudCBwcm9wZXJ0aWVzLlxuICAgKlxuICAgKiBgYGBcbiAgICovXG4gIHJlYWRvbmx5IGJ1Y2tldERlcGxveW1lbnRQcm9wcz86IEJ1Y2tldERlcGxveW1lbnRQcm9wcztcblxuICAvKipcbiAgICogTGltaXRlZCBjb25maWd1cmF0aW9uIHNldHRpbmdzIGZvciB0aGUgZ2VuZXJhdGVkIHdlYkFjbC4gRm9yIG1vcmUgYWR2YW5jZWQgc2V0dGluZ3MsIGNyZWF0ZSB5b3VyIG93biBBQ0wgYW5kIHBhc3MgaW4gdGhlIHdlYkFjbElkIGFzIGEgcGFyYW0gdG8gZGlzdHJpYnV0aW9uUHJvcHMuXG4gICAqXG4gICAqIE5vdGU6IElmIHBhc3MgaW4geW91ciBvd24gQUNMLCBtYWtlIHN1cmUgdGhlIFNDT1BFIGlzIENMT1VERlJPTlQgYW5kIGl0IGlzIGNyZWF0ZWQgaW4gdXMtZWFzdC0xLlxuICAgKi9cbiAgcmVhZG9ubHkgd2ViQWNsUHJvcHM/OiBDbG91ZEZyb250V2ViQWNsUHJvcHM7XG59XG5cbi8qKlxuICogRGVwbG95cyBhIFN0YXRpYyBXZWJzaXRlIHVzaW5nIGJ5IGRlZmF1bHQgYSBwcml2YXRlIFMzIGJ1Y2tldCBhcyBhbiBvcmlnaW4gYW5kIENsb3VkZnJvbnQgYXMgdGhlIGVudHJ5cG9pbnQuXG4gKlxuICogVGhpcyBjb25zdHJ1Y3QgY29uZmlndXJlcyBhIHdlYkFjbCBjb250YWluaW5nIHJ1bGVzIHRoYXQgYXJlIGdlbmVyYWxseSBhcHBsaWNhYmxlIHRvIHdlYiBhcHBsaWNhdGlvbnMuIFRoaXNcbiAqIHByb3ZpZGVzIHByb3RlY3Rpb24gYWdhaW5zdCBleHBsb2l0YXRpb24gb2YgYSB3aWRlIHJhbmdlIG9mIHZ1bG5lcmFiaWxpdGllcywgaW5jbHVkaW5nIHNvbWUgb2YgdGhlIGhpZ2ggcmlza1xuICogYW5kIGNvbW1vbmx5IG9jY3VycmluZyB2dWxuZXJhYmlsaXRpZXMgZGVzY3JpYmVkIGluIE9XQVNQIHB1YmxpY2F0aW9ucyBzdWNoIGFzIE9XQVNQIFRvcCAxMC5cbiAqXG4gKi9cbmV4cG9ydCBjbGFzcyBTdGF0aWNXZWJzaXRlIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcHVibGljIHJlYWRvbmx5IHdlYnNpdGVCdWNrZXQ6IElCdWNrZXQ7XG4gIHB1YmxpYyByZWFkb25seSBjbG91ZEZyb250RGlzdHJpYnV0aW9uOiBEaXN0cmlidXRpb247XG4gIHB1YmxpYyByZWFkb25seSBidWNrZXREZXBsb3ltZW50OiBCdWNrZXREZXBsb3ltZW50O1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBTdGF0aWNXZWJzaXRlUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgYWRkTWV0cmljKHNjb3BlLCBcInN0YXRpYy13ZWJzaXRlXCIpO1xuXG4gICAgdGhpcy5ub2RlLnNldENvbnRleHQoXG4gICAgICBcIkBhd3MtY2RrL2F3cy1zMzpzZXJ2ZXJBY2Nlc3NMb2dzVXNlQnVja2V0UG9saWN5XCIsXG4gICAgICB0cnVlXG4gICAgKTtcblxuICAgIHRoaXMudmFsaWRhdGVQcm9wcyhwcm9wcyk7XG5cbiAgICBjb25zdCBhY2Nlc3NMb2dzQnVja2V0ID0gbmV3IEJ1Y2tldCh0aGlzLCBcIkFjY2Vzc0xvZ3NCdWNrZXRcIiwge1xuICAgICAgdmVyc2lvbmVkOiBmYWxzZSxcbiAgICAgIGVuZm9yY2VTU0w6IHRydWUsXG4gICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZSxcbiAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgIGVuY3J5cHRpb246IEJ1Y2tldEVuY3J5cHRpb24uUzNfTUFOQUdFRCxcbiAgICAgIG9iamVjdE93bmVyc2hpcDogT2JqZWN0T3duZXJzaGlwLk9CSkVDVF9XUklURVIsXG4gICAgICBwdWJsaWNSZWFkQWNjZXNzOiBmYWxzZSxcbiAgICAgIGJsb2NrUHVibGljQWNjZXNzOiBCbG9ja1B1YmxpY0FjY2Vzcy5CTE9DS19BTEwsXG4gICAgfSk7XG5cbiAgICAvLyBTMyBCdWNrZXQgdG8gaG9sZCB3ZWJzaXRlIGZpbGVzXG4gICAgdGhpcy53ZWJzaXRlQnVja2V0ID1cbiAgICAgIHByb3BzLndlYnNpdGVCdWNrZXQgPz9cbiAgICAgIG5ldyBCdWNrZXQodGhpcywgXCJXZWJzaXRlQnVja2V0XCIsIHtcbiAgICAgICAgdmVyc2lvbmVkOiB0cnVlLFxuICAgICAgICBlbmZvcmNlU1NMOiB0cnVlLFxuICAgICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZSxcbiAgICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICBlbmNyeXB0aW9uOlxuICAgICAgICAgIHByb3BzLmRlZmF1bHRXZWJzaXRlQnVja2V0RW5jcnlwdGlvbiA/PyBCdWNrZXRFbmNyeXB0aW9uLlMzX01BTkFHRUQsXG4gICAgICAgIG9iamVjdE93bmVyc2hpcDogT2JqZWN0T3duZXJzaGlwLkJVQ0tFVF9PV05FUl9FTkZPUkNFRCxcbiAgICAgICAgZW5jcnlwdGlvbktleTogcHJvcHMuZGVmYXVsdFdlYnNpdGVCdWNrZXRFbmNyeXB0aW9uS2V5LFxuICAgICAgICBwdWJsaWNSZWFkQWNjZXNzOiBmYWxzZSxcbiAgICAgICAgYmxvY2tQdWJsaWNBY2Nlc3M6IEJsb2NrUHVibGljQWNjZXNzLkJMT0NLX0FMTCxcbiAgICAgICAgc2VydmVyQWNjZXNzTG9nc1ByZWZpeDogXCJ3ZWJzaXRlLWFjY2Vzcy1sb2dzXCIsXG4gICAgICAgIHNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQ6IGFjY2Vzc0xvZ3NCdWNrZXQsXG4gICAgICB9KTtcblxuICAgIC8vIFdlYiBBQ0xcbiAgICBjb25zdCB7IGRpc3RyaWJ1dGlvblByb3BzIH0gPSBwcm9wcztcbiAgICBjb25zdCB3ZWJBY2xBcm4gPVxuICAgICAgZGlzdHJpYnV0aW9uUHJvcHM/LndlYkFjbElkID8/XG4gICAgICAocHJvcHMud2ViQWNsUHJvcHM/LmRpc2FibGVcbiAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgOiBuZXcgQ2xvdWRmcm9udFdlYkFjbCh0aGlzLCBcIldlYnNpdGVBY2xcIiwgcHJvcHMud2ViQWNsUHJvcHMpXG4gICAgICAgICAgICAud2ViQWNsQXJuKTtcblxuICAgIC8vIENsb3VkZnJvbnQgRGlzdHJpYnV0aW9uXG4gICAgY29uc3QgbG9nQnVja2V0ID1cbiAgICAgIHByb3BzLmRpc3RyaWJ1dGlvblByb3BzPy5sb2dCdWNrZXQgfHxcbiAgICAgIG5ldyBCdWNrZXQodGhpcywgXCJEaXN0cmlidXRpb25Mb2dCdWNrZXRcIiwge1xuICAgICAgICBlbmZvcmNlU1NMOiB0cnVlLFxuICAgICAgICBhdXRvRGVsZXRlT2JqZWN0czogdHJ1ZSxcbiAgICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICBlbmNyeXB0aW9uOlxuICAgICAgICAgIHByb3BzLmRlZmF1bHRXZWJzaXRlQnVja2V0RW5jcnlwdGlvbiA/PyBCdWNrZXRFbmNyeXB0aW9uLlMzX01BTkFHRUQsXG4gICAgICAgIG9iamVjdE93bmVyc2hpcDogT2JqZWN0T3duZXJzaGlwLkJVQ0tFVF9PV05FUl9QUkVGRVJSRUQsXG4gICAgICAgIGVuY3J5cHRpb25LZXk6IHByb3BzLmRlZmF1bHRXZWJzaXRlQnVja2V0RW5jcnlwdGlvbktleSxcbiAgICAgICAgcHVibGljUmVhZEFjY2VzczogZmFsc2UsXG4gICAgICAgIGJsb2NrUHVibGljQWNjZXNzOiBCbG9ja1B1YmxpY0FjY2Vzcy5CTE9DS19BTEwsXG4gICAgICAgIHNlcnZlckFjY2Vzc0xvZ3NQcmVmaXg6IFwiZGlzdHJpYnV0aW9uLWFjY2Vzcy1sb2dzXCIsXG4gICAgICAgIHNlcnZlckFjY2Vzc0xvZ3NCdWNrZXQ6IGFjY2Vzc0xvZ3NCdWNrZXQsXG4gICAgICB9KTtcblxuICAgIGNvbnN0IGRlZmF1bHRSb290T2JqZWN0ID1cbiAgICAgIGRpc3RyaWJ1dGlvblByb3BzPy5kZWZhdWx0Um9vdE9iamVjdCA/PyBcImluZGV4Lmh0bWxcIjtcbiAgICB0aGlzLmNsb3VkRnJvbnREaXN0cmlidXRpb24gPSBuZXcgRGlzdHJpYnV0aW9uKFxuICAgICAgdGhpcyxcbiAgICAgIFwiQ2xvdWRmcm9udERpc3RyaWJ1dGlvblwiLFxuICAgICAge1xuICAgICAgICAuLi5kaXN0cmlidXRpb25Qcm9wcyxcbiAgICAgICAgd2ViQWNsSWQ6IHdlYkFjbEFybixcbiAgICAgICAgZW5hYmxlTG9nZ2luZzogdHJ1ZSxcbiAgICAgICAgbG9nQnVja2V0OiBsb2dCdWNrZXQsXG4gICAgICAgIGRlZmF1bHRCZWhhdmlvcjoge1xuICAgICAgICAgIC4uLmRpc3RyaWJ1dGlvblByb3BzPy5kZWZhdWx0QmVoYXZpb3IsXG4gICAgICAgICAgb3JpZ2luOiBTM0J1Y2tldE9yaWdpbi53aXRoT3JpZ2luQWNjZXNzQ29udHJvbCh0aGlzLndlYnNpdGVCdWNrZXQpLFxuICAgICAgICAgIHZpZXdlclByb3RvY29sUG9saWN5OiBWaWV3ZXJQcm90b2NvbFBvbGljeS5SRURJUkVDVF9UT19IVFRQUyxcbiAgICAgICAgfSxcbiAgICAgICAgZGVmYXVsdFJvb3RPYmplY3QsXG4gICAgICAgIC8vIFdlIG5lZWQgdG8gcmVkaXJlY3QgXCJrZXkgbm90IGZvdW5kIGVycm9yc1wiIHRvIGluZGV4Lmh0bWwgZm9yIHNpbmdsZSBwYWdlIGFwcHNcbiAgICAgICAgZXJyb3JSZXNwb25zZXM6XG4gICAgICAgICAgZGlzdHJpYnV0aW9uUHJvcHM/LmVycm9yUmVzcG9uc2VzID8/XG4gICAgICAgICAgWzQwMywgNDA0XS5tYXAoKGh0dHBTdGF0dXMpID0+ICh7XG4gICAgICAgICAgICBodHRwU3RhdHVzLFxuICAgICAgICAgICAgcmVzcG9uc2VIdHRwU3RhdHVzOiAyMDAsXG4gICAgICAgICAgICByZXNwb25zZVBhZ2VQYXRoOiBgLyR7ZGVmYXVsdFJvb3RPYmplY3R9YCxcbiAgICAgICAgICB9KSksXG4gICAgICB9XG4gICAgKTtcblxuICAgIC8vIERlcGxveSBXZWJzaXRlXG4gICAgdGhpcy5idWNrZXREZXBsb3ltZW50ID0gbmV3IEJ1Y2tldERlcGxveW1lbnQodGhpcywgXCJXZWJzaXRlRGVwbG95bWVudFwiLCB7XG4gICAgICBtZW1vcnlMaW1pdDogMjA0OCxcbiAgICAgIC4uLnByb3BzLmJ1Y2tldERlcGxveW1lbnRQcm9wcyxcbiAgICAgIHNvdXJjZXM6IFtcbiAgICAgICAgU291cmNlLmFzc2V0KHByb3BzLndlYnNpdGVDb250ZW50UGF0aCksXG4gICAgICAgIC4uLihwcm9wcy5ydW50aW1lT3B0aW9uc1xuICAgICAgICAgID8gW1xuICAgICAgICAgICAgICBTb3VyY2UuanNvbkRhdGEoXG4gICAgICAgICAgICAgICAgcHJvcHMucnVudGltZU9wdGlvbnM/Lmpzb25GaWxlTmFtZSB8fFxuICAgICAgICAgICAgICAgICAgREVGQVVMVF9SVU5USU1FX0NPTkZJR19GSUxFTkFNRSxcbiAgICAgICAgICAgICAgICBsYXppbHlSZW5kZXIodGhpcywgcHJvcHMucnVudGltZU9wdGlvbnMuanNvblBheWxvYWQpXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICBdXG4gICAgICAgICAgOiBbXSksXG4gICAgICBdLFxuICAgICAgZGVzdGluYXRpb25CdWNrZXQ6IHRoaXMud2Vic2l0ZUJ1Y2tldCxcbiAgICAgIC8vIEZpbGVzIGluIHRoZSBkaXN0cmlidXRpb24ncyBlZGdlIGNhY2hlcyB3aWxsIGJlIGludmFsaWRhdGVkIGFmdGVyIGZpbGVzIGFyZSB1cGxvYWRlZCB0byB0aGUgZGVzdGluYXRpb24gYnVja2V0LlxuICAgICAgZGlzdHJpYnV0aW9uOiB0aGlzLmNsb3VkRnJvbnREaXN0cmlidXRpb24sXG4gICAgfSk7XG5cbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsIFwiRGlzdHJpYnV0aW9uRG9tYWluTmFtZVwiLCB7XG4gICAgICB2YWx1ZTogdGhpcy5jbG91ZEZyb250RGlzdHJpYnV0aW9uLmRvbWFpbk5hbWUsXG4gICAgfSk7XG5cbiAgICB0aGlzLnN1cHByZXNzQ0RLTmFnVmlvbGF0aW9ucyhwcm9wcyk7XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlUHJvcHMgPSAocHJvcHM6IFN0YXRpY1dlYnNpdGVQcm9wcykgPT4ge1xuICAgIHRoaXMudmFsaWRhdGVFbmNyeXB0aW9uU2V0dGluZ3MocHJvcHMpO1xuICAgIHByb3BzLnJ1bnRpbWVPcHRpb25zICYmIHRoaXMudmFsaWRhdGVSdW50aW1lQ29uZmlnKHByb3BzLnJ1bnRpbWVPcHRpb25zKTtcbiAgICBwcm9wcy53ZWJzaXRlQnVja2V0ICYmIHRoaXMudmFsaWRhdGVCdWNrZXRDb25maWcocHJvcHMud2Vic2l0ZUJ1Y2tldCk7XG4gIH07XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZVJ1bnRpbWVDb25maWcgPSAoY29uZmlnOiBSdW50aW1lT3B0aW9ucykgPT4ge1xuICAgIGlmICghY29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwidmFsaWRhdGVSdW50aW1lQ29uZmlnIG9ubHkgYWNjZXB0cyBub24tbnVsbCBSdW50aW1lT3B0aW9ucy5cIlxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLmpzb25GaWxlTmFtZSAmJiAhY29uZmlnLmpzb25GaWxlTmFtZS5lbmRzV2l0aChcIi5qc29uXCIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSdW50aW1lT3B0aW9ucy5qc29uRmlsZU5hbWUgbXVzdCBiZSBhIGpzb24gZmlsZS5cIik7XG4gICAgfVxuICB9O1xuXG4gIHByaXZhdGUgdmFsaWRhdGVCdWNrZXRDb25maWcgPSAoYnVja2V0OiBJQnVja2V0KSA9PiB7XG4gICAgaWYgKGJ1Y2tldC5pc1dlYnNpdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJXZWJzaXRlIGJ1Y2tldHMgY2Fubm90IGJlIGNvbmZpZ3VyZWQgYXMgd2Vic2l0ZXMgYXMgdGhpcyB3aWxsIGJyZWFrIENsb3VkZnJvbnQgaG9zdGluZyFcIlxuICAgICAgKTtcbiAgICB9XG4gIH07XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZUVuY3J5cHRpb25TZXR0aW5ncyA9ICh7XG4gICAgZGVmYXVsdFdlYnNpdGVCdWNrZXRFbmNyeXB0aW9uLFxuICAgIGRlZmF1bHRXZWJzaXRlQnVja2V0RW5jcnlwdGlvbktleSxcbiAgfTogU3RhdGljV2Vic2l0ZVByb3BzKSA9PiB7XG4gICAgaWYgKFxuICAgICAgZGVmYXVsdFdlYnNpdGVCdWNrZXRFbmNyeXB0aW9uS2V5ICYmXG4gICAgICBkZWZhdWx0V2Vic2l0ZUJ1Y2tldEVuY3J5cHRpb24gIT09IEJ1Y2tldEVuY3J5cHRpb24uS01TXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiQnVja2V0IGVuY3J5cHRpb24gc2hvdWxkIGJlIHNldCB0byBLTVMgaWYgcHJvdmlkaW5nIGEgZGVmYXVsdFdlYnNpdGVCdWNrZXRFbmNyeXB0aW9uS2V5LlwiXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIGRlZmF1bHRXZWJzaXRlQnVja2V0RW5jcnlwdGlvbiAmJlxuICAgICAgZGVmYXVsdFdlYnNpdGVCdWNrZXRFbmNyeXB0aW9uICE9PSBCdWNrZXRFbmNyeXB0aW9uLktNUyAmJlxuICAgICAgZGVmYXVsdFdlYnNpdGVCdWNrZXRFbmNyeXB0aW9uICE9PSBCdWNrZXRFbmNyeXB0aW9uLlMzX01BTkFHRURcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJPbmx5IEtNUyBhbmQgUzNfTUFOQUdFRCBlbmNyeXB0aW9uIGFyZSBzdXBwb3J0ZWQgb24gdGhlIGRlZmF1bHQgYnVja2V0LlwiXG4gICAgICApO1xuICAgIH1cbiAgfTtcblxuICBwcml2YXRlIHN1cHByZXNzQ0RLTmFnVmlvbGF0aW9ucyA9IChwcm9wczogU3RhdGljV2Vic2l0ZVByb3BzKSA9PiB7XG4gICAgY29uc3Qgc3RhY2sgPSBTdGFjay5vZih0aGlzKTtcbiAgICAhcHJvcHMuZGlzdHJpYnV0aW9uUHJvcHM/LmNlcnRpZmljYXRlICYmXG4gICAgICBbXG4gICAgICAgIFwiQXdzU29sdXRpb25zLUNGUjRcIixcbiAgICAgICAgXCJBd3NQcm90b3R5cGluZy1DbG91ZEZyb250RGlzdHJpYnV0aW9uSHR0cHNWaWV3ZXJOb091dGRhdGVkU1NMXCIsXG4gICAgICBdLmZvckVhY2goKFJ1bGVJZCkgPT4ge1xuICAgICAgICBOYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnModGhpcy5jbG91ZEZyb250RGlzdHJpYnV0aW9uLCBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgaWQ6IFJ1bGVJZCxcbiAgICAgICAgICAgIHJlYXNvbjpcbiAgICAgICAgICAgICAgXCJDZXJ0aWZpY2F0ZSBpcyBub3QgbWFuZGF0b3J5IHRoZXJlZm9yZSB0aGUgQ2xvdWRmcm9udCBjZXJ0aWZpY2F0ZSB3aWxsIGJlIHVzZWQuXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG4gICAgICB9KTtcblxuICAgIFtcIkF3c1NvbHV0aW9ucy1MMVwiLCBcIkF3c1Byb3RvdHlwaW5nLUxhbWJkYUxhdGVzdFZlcnNpb25cIl0uZm9yRWFjaChcbiAgICAgIChSdWxlSWQpID0+IHtcbiAgICAgICAgTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zKFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBpZDogUnVsZUlkLFxuICAgICAgICAgICAgICByZWFzb246XG4gICAgICAgICAgICAgICAgXCJMYXRlc3QgcnVudGltZSBjYW5ub3QgYmUgY29uZmlndXJlZC4gQ0RLIHdpbGwgbmVlZCB0byB1cGdyYWRlIHRoZSBCdWNrZXREZXBsb3ltZW50IGNvbnN0cnVjdCBhY2NvcmRpbmdseS5cIixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICB0cnVlXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgKTtcblxuICAgIFtcIkF3c1NvbHV0aW9ucy1JQU01XCIsIFwiQXdzUHJvdG90eXBpbmctSUFNTm9XaWxkY2FyZFBlcm1pc3Npb25zXCJdLmZvckVhY2goXG4gICAgICAoUnVsZUlkKSA9PiB7XG4gICAgICAgIE5hZ1N1cHByZXNzaW9ucy5hZGRSZXNvdXJjZVN1cHByZXNzaW9ucyhcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgaWQ6IFJ1bGVJZCxcbiAgICAgICAgICAgICAgcmVhc29uOlxuICAgICAgICAgICAgICAgIFwiQWxsIFBvbGljaWVzIGhhdmUgYmVlbiBzY29wZWQgdG8gYSBCdWNrZXQuIEdpdmVuIEJ1Y2tldHMgY2FuIGNvbnRhaW4gYXJiaXRyYXJ5IGNvbnRlbnQsIHdpbGRjYXJkIHJlc291cmNlcyB3aXRoIGJ1Y2tldCBzY29wZSBhcmUgcmVxdWlyZWQuXCIsXG4gICAgICAgICAgICAgIGFwcGxpZXNUbzogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIHJlZ2V4OiBcIi9eQWN0aW9uOjpzMzouKiQvZ1wiLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcmVnZXg6IGAvXlJlc291cmNlOjouKiQvZ2AsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICB0cnVlXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgKTtcblxuICAgIFtcIkF3c1NvbHV0aW9ucy1JQU00XCIsIFwiQXdzUHJvdG90eXBpbmctSUFNTm9NYW5hZ2VkUG9saWNpZXNcIl0uZm9yRWFjaChcbiAgICAgIChSdWxlSWQpID0+IHtcbiAgICAgICAgTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zKFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBpZDogUnVsZUlkLFxuICAgICAgICAgICAgICByZWFzb246XG4gICAgICAgICAgICAgICAgXCJCdWNrZXRzIGNhbiBjb250YWluIGFyYml0cmFyeSBjb250ZW50LCB0aGVyZWZvcmUgd2lsZGNhcmQgcmVzb3VyY2VzIHVuZGVyIGEgYnVja2V0IGFyZSByZXF1aXJlZC5cIixcbiAgICAgICAgICAgICAgYXBwbGllc1RvOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcmVnZXg6IGAvXlBvbGljeTo6YXJuOiR7UERLTmFnLmdldFN0YWNrUGFydGl0aW9uUmVnZXgoXG4gICAgICAgICAgICAgICAgICAgIHN0YWNrXG4gICAgICAgICAgICAgICAgICApfTppYW06OmF3czpwb2xpY3kvc2VydmljZS1yb2xlL0FXU0xhbWJkYUJhc2ljRXhlY3V0aW9uUm9sZSQvZ2AsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICB0cnVlXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgKTtcblxuICAgIFtcIkF3c1NvbHV0aW9ucy1TMVwiLCBcIkF3c1Byb3RvdHlwaW5nLVMzQnVja2V0TG9nZ2luZ0VuYWJsZWRcIl0uZm9yRWFjaChcbiAgICAgIChSdWxlSWQpID0+IHtcbiAgICAgICAgTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zKFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBpZDogUnVsZUlkLFxuICAgICAgICAgICAgICByZWFzb246IFwiQWNjZXNzIExvZyBidWNrZXRzIHNob3VsZCBub3QgaGF2ZSBzMyBidWNrZXQgbG9nZ2luZ1wiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICApO1xuICB9O1xufVxuXG4vKipcbiAqIElmIHBhc3NpbmcgaW4gZGlzdHJpYnV0aW9uUHJvcHMsIHRoZSBkZWZhdWx0IGJlaGF2aW91ci5vcmlnaW4gaXMgYSByZXF1aXJlZCBwYXJhbWV0ZXIuIEFuIGluc3RhbmNlIG9mIHRoaXMgY2xhc3MgY2FuIGJlIHBhc3NlZCBpblxuICogdG8gbWFrZSB0aGUgY29tcGlsZXIgaGFwcHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdGF0aWNXZWJzaXRlT3JpZ2luIGltcGxlbWVudHMgSU9yaWdpbiB7XG4gIGJpbmQoX3Njb3BlOiBDb25zdHJ1Y3QsIF9vcHRpb25zOiBPcmlnaW5CaW5kT3B0aW9ucyk6IE9yaWdpbkJpbmRDb25maWcge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlRoaXMgc2hvdWxkIG5ldmVyIGJlIGNhbGxlZFwiKTtcbiAgfVxufVxuIl19