@aws/pdk
Version:
All documentation is located at: https://aws.github.io/aws-pdk
228 lines • 38.4 kB
JavaScript
"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