@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.
210 lines (207 loc) • 27.6 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.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeploymentWorkflowStepFunction = void 0;
const aws_cdk_lib_1 = require("aws-cdk-lib");
const constructs_1 = require("constructs");
const path = __importStar(require("path"));
const aws_stepfunctions_1 = require("aws-cdk-lib/aws-stepfunctions");
const cfn_nag_utils_1 = require("./cfn_nag/cfn_nag_utils");
const cdk_nag_1 = require("cdk-nag");
const aws_logs_1 = require("aws-cdk-lib/aws-logs");
class DeploymentWorkflowStepFunction extends constructs_1.Construct {
constructor(scope, id, params) {
super(scope, id);
const basicLambdaRole = new aws_cdk_lib_1.aws_iam.Role(this, "BasicLambdaRole", {
assumedBy: new aws_cdk_lib_1.aws_iam.ServicePrincipal("lambda.amazonaws.com"),
});
const awsSdkLayer = new aws_cdk_lib_1.aws_lambda.LayerVersion(this, "AwsSdkLayer", {
compatibleRuntimes: [aws_cdk_lib_1.aws_lambda.Runtime.NODEJS_20_X],
code: aws_cdk_lib_1.aws_lambda.Code.fromAsset(path.join(__dirname, "../lambda/layers/aws_sdk")),
description: "AWS SDK lib including client-cloudfront-keyvaluestore",
});
const updateKvs = new aws_cdk_lib_1.aws_lambda.Function(this, "UpdateKvsFunction", {
runtime: aws_cdk_lib_1.aws_lambda.Runtime.NODEJS_20_X,
code: aws_cdk_lib_1.aws_lambda.Code.fromAsset(path.join(__dirname, "../lambda/update_kvs")),
handler: "index.handler",
memorySize: 512,
timeout: aws_cdk_lib_1.Duration.minutes(10),
logRetention: aws_cdk_lib_1.aws_logs.RetentionDays.ONE_WEEK,
tracing: aws_cdk_lib_1.aws_lambda.Tracing.ACTIVE,
layers: [awsSdkLayer],
environment: {
KVS_ARN: params.kvsArn,
},
role: basicLambdaRole,
});
updateKvs.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW,
actions: [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
],
resources: ["arn:aws:logs:*:*:*"],
}));
updateKvs.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW,
actions: [
"cloudfront-keyvaluestore:DescribeKeyValueStore",
"cloudfront-keyvaluestore:PutKey",
],
resources: [params.kvsArn],
}));
(0, cfn_nag_utils_1.addCfnSuppressRules)(updateKvs, [
{
id: "W58",
reason: "Lambda has CloudWatch permissions by using service role AWSLambdaBasicExecutionRole",
},
]);
(0, cfn_nag_utils_1.addCfnSuppressRules)(updateKvs, [
{
id: "W89",
reason: "We don t have any VPC in the stack, we only use serverless services",
},
]);
(0, cfn_nag_utils_1.addCfnSuppressRules)(updateKvs, [
{
id: "W92",
reason: "No need for ReservedConcurrentExecutions, some are used only for the demo website, and others are not used in a concurrent mode.",
},
]);
const deleteOldDeployments = new aws_cdk_lib_1.aws_lambda.Function(this, "DeleteOldDeployments", {
runtime: aws_cdk_lib_1.aws_lambda.Runtime.NODEJS_18_X,
code: aws_cdk_lib_1.aws_lambda.Code.fromAsset(path.join(__dirname, "../lambda/delete_old_deployments")),
timeout: aws_cdk_lib_1.Duration.seconds(300),
handler: "index.handler",
environment: {
BUCKET_NAME: params.hostingBucket.bucketName,
},
logRetention: aws_cdk_lib_1.aws_logs.RetentionDays.ONE_WEEK,
role: basicLambdaRole,
});
deleteOldDeployments.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW,
actions: [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
],
resources: ["arn:aws:logs:*:*:*"],
}));
(0, cfn_nag_utils_1.addCfnSuppressRules)(deleteOldDeployments, [
{
id: "W58",
reason: "Lambda has CloudWatch permissions by using service role AWSLambdaBasicExecutionRole",
},
]);
(0, cfn_nag_utils_1.addCfnSuppressRules)(deleteOldDeployments, [
{
id: "W89",
reason: "We don t have any VPC in the stack, we only use serverless services",
},
]);
(0, cfn_nag_utils_1.addCfnSuppressRules)(deleteOldDeployments, [
{
id: "W92",
reason: "No need for ReservedConcurrentExecutions, some are used only for the demo website, and others are not used in a concurrent mode.",
},
]);
params.hostingBucket.grantReadWrite(deleteOldDeployments);
cdk_nag_1.NagSuppressions.addResourceSuppressions(basicLambdaRole, [
{
id: "AwsSolutions-IAM5",
reason: "Permissions to get objects and delete them is required",
},
], true);
const successState = new aws_cdk_lib_1.aws_stepfunctions.Pass(this, "SuccessState");
const updateCloudFrontFunctionJob = new aws_cdk_lib_1.aws_stepfunctions_tasks.LambdaInvoke(this, "Update KeyValueStore", {
lambdaFunction: updateKvs,
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
});
const deleteOldDeploymentsJob = new aws_cdk_lib_1.aws_stepfunctions_tasks.LambdaInvoke(this, "Purge previous deployments from S3", {
lambdaFunction: deleteOldDeployments,
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
});
const communDefinition = updateCloudFrontFunctionJob
.next(deleteOldDeploymentsJob);
var stepFunctionDefinition;
if (params.ssmCommitIdParam) {
const getCommitId = new aws_cdk_lib_1.aws_stepfunctions_tasks.CallAwsService(this, "Get CommitID from Parameter Store", {
service: "ssm",
action: "getParameter",
parameters: {
Name: params.ssmCommitIdParam.parameterName,
},
iamResources: [params.ssmCommitIdParam.parameterArn],
iamAction: "ssm:getParameter",
resultSelector: {
commitId: aws_cdk_lib_1.aws_stepfunctions.JsonPath.stringAt("$.Parameter.Value"),
},
});
const ssmHasValue = new aws_cdk_lib_1.aws_stepfunctions.Choice(this, "SSM Param is SET ?")
.when(aws_cdk_lib_1.aws_stepfunctions.Condition.stringEquals("$.commitId", "init"), successState)
.otherwise(communDefinition);
stepFunctionDefinition = getCommitId.next(ssmHasValue);
}
else {
stepFunctionDefinition = communDefinition;
}
const sfnLog = new aws_logs_1.LogGroup(this, "sfnLog", {
logGroupName: "/aws/vendedlogs/states/" + aws_cdk_lib_1.Stack.of(this).stackName,
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
retention: aws_logs_1.RetentionDays.ONE_WEEK,
});
this.stepFunction = new aws_cdk_lib_1.aws_stepfunctions.StateMachine(this, "StaticHostingSF", {
definitionBody: aws_cdk_lib_1.aws_stepfunctions.DefinitionBody.fromChainable(stepFunctionDefinition),
tracingEnabled: true,
logs: {
destination: sfnLog,
includeExecutionData: true,
level: aws_stepfunctions_1.LogLevel.ALL,
},
});
cdk_nag_1.NagSuppressions.addResourceSuppressions(this.stepFunction, [
{
id: "AwsSolutions-IAM5",
reason: "Required permissions for this Step Function",
},
], true);
}
}
exports.DeploymentWorkflowStepFunction = DeploymentWorkflowStepFunction;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95bWVudF93b3JrZmxvd19zZi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImRlcGxveW1lbnRfd29ya2Zsb3dfc2YudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVILDZDQVlxQjtBQUVyQiwyQ0FBdUM7QUFDdkMsMkNBQTZCO0FBQzdCLHFFQUErRTtBQUUvRSwyREFBOEQ7QUFDOUQscUNBQTBDO0FBQzFDLG1EQUErRDtBQWMvRCxNQUFhLDhCQUErQixTQUFRLHNCQUFTO0lBRzNELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsTUFBbUI7UUFDM0QsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUdqQixNQUFNLGVBQWUsR0FBRyxJQUFJLHFCQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxpQkFBaUIsRUFBRTtZQUM1RCxTQUFTLEVBQUUsSUFBSSxxQkFBRyxDQUFDLGdCQUFnQixDQUFDLHNCQUFzQixDQUFDO1NBQzVELENBQUMsQ0FBQztRQUVILE1BQU0sV0FBVyxHQUFHLElBQUksd0JBQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRTtZQUMvRCxrQkFBa0IsRUFBRSxDQUFDLHdCQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQztZQUNoRCxJQUFJLEVBQUUsd0JBQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLDBCQUEwQixDQUFDLENBQUM7WUFDN0UsV0FBVyxFQUFFLHVEQUF1RDtTQUNyRSxDQUFDLENBQUM7UUFFSCxNQUFNLFNBQVMsR0FBRyxJQUFJLHdCQUFNLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxtQkFBbUIsRUFBRTtZQUMvRCxPQUFPLEVBQUUsd0JBQU0sQ0FBQyxPQUFPLENBQUMsV0FBVztZQUNuQyxJQUFJLEVBQUUsd0JBQU0s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QUUsaUJBQWlCLEVBQUU7WUFDaEUsY0FBYyxFQUFHLCtCQUFHLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyxzQkFBc0IsQ0FBQztZQUN6RSxjQUFjLEVBQUUsSUFBSTtZQUNwQixJQUFJLEVBQUU7Z0JBQ0osV0FBVyxFQUFFLE1BQU07Z0JBQ25CLG9CQUFvQixFQUFFLElBQUk7Z0JBQzFCLEtBQUssRUFBRSw0QkFBUSxDQUFDLEdBQUc7YUFDcEI7U0FDRixDQUFDLENBQUM7UUFFSCx5QkFBZSxDQUFDLHVCQUF1QixDQUNyQyxJQUFJLENBQUMsWUFBWSxFQUNqQjtZQUNFO2dCQUNFLEVBQUUsRUFBRSxtQkFBbUI7Z0JBQ3ZCLE1BQU0sRUFBRSw2Q0FBNkM7YUFDdEQ7U0FDRixFQUNELElBQUksQ0FDTCxDQUFDO0lBQ0osQ0FBQztDQUNGO0FBak9ELHdFQWlPQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICBcbiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKS5cbiAgWW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgXG4gICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgXG4gIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBBd3MsXG4gIER1cmF0aW9uLFxuICBhd3NfaWFtIGFzIGlhbSxcbiAgYXdzX2Nsb3VkZnJvbnQgYXMgY2xvdWRmcm9udCxcbiAgYXdzX3N0ZXBmdW5jdGlvbnMgYXMgc2ZuLFxuICBhd3NfbGFtYmRhIGFzIGxhbWJkYSxcbiAgYXdzX3N0ZXBmdW5jdGlvbnNfdGFza3MgYXMgdGFza3MsXG4gIGF3c19sb2dzIGFzIGxvZ3MsXG4gIGF3c19zc20gYXMgc3NtLFxuICBSZW1vdmFsUG9saWN5LFxuICBTdGFjayxcbn0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5cbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBJQ2hhaW5hYmxlLCBKc29uUGF0aCwgTG9nTGV2ZWwgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnNcIjtcbmltcG9ydCB7IElCdWNrZXQgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXMzXCI7XG5pbXBvcnQgeyBhZGRDZm5TdXBwcmVzc1J1bGVzIH0gZnJvbSBcIi4vY2ZuX25hZy9jZm5fbmFnX3V0aWxzXCI7XG5pbXBvcnQgeyBOYWdTdXBwcmVzc2lvbnMgfSBmcm9tIFwiY2RrLW5hZ1wiO1xuaW1wb3J0IHsgTG9nR3JvdXAsIFJldGVudGlvbkRheXMgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxvZ3NcIjtcbmltcG9ydCB7IE5vZGVqc0Z1bmN0aW9uIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1sYW1iZGEtbm9kZWpzXCI7XG5pbXBvcnQgeyBMYXllclZlcnNpb24sIFJ1bnRpbWUsIFRyYWNpbmcgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcblxuXG5pbnRlcmZhY2UgSVBhcmFtUHJvcHMge1xuICBjaGFuZ2VVcmk6IGNsb3VkZnJvbnQuRnVuY3Rpb247XG4gIGt2c0Fybjogc3RyaW5nLFxuICBob3N0aW5nQnVja2V0OiBJQnVja2V0O1xuICBzc21Db21taXRJZFBhcmFtPzogc3NtLlN0cmluZ1BhcmFtZXRlcjtcbiAgc3NtUzNLZXlQYXJhbT86IHNzbS5TdHJpbmdQYXJhbWV0ZXI7XG59XG5cblxuZXhwb3J0IGNsYXNzIERlcGxveW1lbnRXb3JrZmxvd1N0ZXBGdW5jdGlvbiBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSBzdGVwRnVuY3Rpb246IHNmbi5JU3RhdGVNYWNoaW5lO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHBhcmFtczogSVBhcmFtUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICBcbiAgICBjb25zdCBiYXNpY0xhbWJkYVJvbGUgPSBuZXcgaWFtLlJvbGUodGhpcywgXCJCYXNpY0xhbWJkYVJvbGVcIiwge1xuICAgICAgYXNzdW1lZEJ5OiBuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoXCJsYW1iZGEuYW1hem9uYXdzLmNvbVwiKSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGF3c1Nka0xheWVyID0gbmV3IGxhbWJkYS5MYXllclZlcnNpb24odGhpcywgXCJBd3NTZGtMYXllclwiLCB7XG4gICAgICBjb21wYXRpYmxlUnVudGltZXM6IFtsYW1iZGEuUnVudGltZS5OT0RFSlNfMjBfWF0sXG4gICAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQocGF0aC5qb2luKF9fZGlybmFtZSwgXCIuLi9sYW1iZGEvbGF5ZXJzL2F3c19zZGtcIikpLFxuICAgICAgZGVzY3JpcHRpb246IFwiQVdTIFNESyBsaWIgaW5jbHVkaW5nIGNsaWVudC1jbG91ZGZyb250LWtleXZhbHVlc3RvcmVcIixcbiAgICB9KTtcblxuICAgIGNvbnN0IHVwZGF0ZUt2cyA9IG5ldyBsYW1iZGEuRnVuY3Rpb24odGhpcywgXCJVcGRhdGVLdnNGdW5jdGlvblwiLCB7XG4gICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMjBfWCxcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCBcIi4uL2xhbWJkYS91cGRhdGVfa3ZzXCIpKSxcbiAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgbWVtb3J5U2l6ZTogNTEyLFxuICAgICAgdGltZW91dDogRHVyYXRpb24ubWludXRlcygxMCksXG4gICAgICBsb2dSZXRlbnRpb246IGxvZ3MuUmV0ZW50aW9uRGF5cy5PTkVfV0VFSyxcbiAgICAgICAgdHJhY2luZzogbGFtYmRhLlRyYWNpbmcuQUNUSVZFLFxuICAgICAgICBsYXllcnM6IFthd3NTZGtMYXllcl0sXG4gICAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgICAgS1ZTX0FSTjogcGFyYW1zLmt2c0FybixcbiAgICAgICAgfSxcbiAgICAgICAgcm9sZTogYmFzaWNMYW1iZGFSb2xlLFxuICAgIH0pO1xuXG5cbiAgICB1cGRhdGVLdnMuYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICBcImxvZ3M6Q3JlYXRlTG9nR3JvdXBcIixcbiAgICAgICAgICBcImxvZ3M6Q3JlYXRlTG9nU3RyZWFtXCIsXG4gICAgICAgICAgXCJsb2dzOlB1dExvZ0V2ZW50c1wiLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFtcImFybjphd3M6bG9nczoqOio6KlwiXSxcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHVwZGF0ZUt2cy5hZGRUb1JvbGVQb2xpY3koXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgIFwiY2xvdWRmcm9udC1rZXl2YWx1ZXN0b3JlOkRlc2NyaWJlS2V5VmFsdWVTdG9yZVwiLFxuICAgICAgICAgIFwiY2xvdWRmcm9udC1rZXl2YWx1ZXN0b3JlOlB1dEtleVwiLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFtwYXJhbXMua3ZzQXJuXSxcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIGFkZENmblN1cHByZXNzUnVsZXModXBkYXRlS3ZzLCBbXG4gICAgICB7XG4gICAgICAgIGlkOiBcIlc1OFwiLFxuICAgICAgICByZWFzb246XG4gICAgICAgICAgXCJMYW1iZGEgaGFzIENsb3VkV2F0Y2ggcGVybWlzc2lvbnMgYnkgdXNpbmcgc2VydmljZSByb2xlIEFXU0xhbWJkYUJhc2ljRXhlY3V0aW9uUm9sZVwiLFxuICAgICAgfSxcbiAgICBdKTtcbiAgICBhZGRDZm5TdXBwcmVzc1J1bGVzKHVwZGF0ZUt2cywgW1xuICAgICAge1xuICAgICAgICBpZDogXCJXODlcIixcbiAgICAgICAgcmVhc29uOlxuICAgICAgICAgIFwiV2UgZG9uIHQgaGF2ZSBhbnkgVlBDIGluIHRoZSBzdGFjaywgd2Ugb25seSB1c2Ugc2VydmVybGVzcyBzZXJ2aWNlc1wiLFxuICAgICAgfSxcbiAgICBdKTtcbiAgICBhZGRDZm5TdXBwcmVzc1J1bGVzKHVwZGF0ZUt2cywgW1xuICAgICAge1xuICAgICAgICBpZDogXCJXOTJcIixcbiAgICAgICAgcmVhc29uOlxuICAgICAgICAgIFwiTm8gbmVlZCBmb3IgUmVzZXJ2ZWRDb25jdXJyZW50RXhlY3V0aW9ucywgc29tZSBhcmUgdXNlZCBvbmx5IGZvciB0aGUgZGVtbyB3ZWJzaXRlLCBhbmQgb3RoZXJzIGFyZSBub3QgdXNlZCBpbiBhIGNvbmN1cnJlbnQgbW9kZS5cIixcbiAgICAgIH0sXG4gICAgXSk7XG5cbiAgICBjb25zdCBkZWxldGVPbGREZXBsb3ltZW50cyA9IG5ldyBsYW1iZGEuRnVuY3Rpb24oXG4gICAgICB0aGlzLFxuICAgICAgXCJEZWxldGVPbGREZXBsb3ltZW50c1wiLFxuICAgICAge1xuICAgICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMThfWCxcbiAgICAgICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KFxuICAgICAgICAgIHBhdGguam9pbihfX2Rpcm5hbWUsIFwiLi4vbGFtYmRhL2RlbGV0ZV9vbGRfZGVwbG95bWVudHNcIilcbiAgICAgICAgKSxcbiAgICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcygzMDApLFxuICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgZW52aXJvbm1lbnQ6IHtcbiAgICAgICAgICBCVUNLRVRfTkFNRTogcGFyYW1zLmhvc3RpbmdCdWNrZXQuYnVja2V0TmFtZSxcbiAgICAgICAgfSxcbiAgICAgICAgbG9nUmV0ZW50aW9uOiBsb2dzLlJldGVudGlvbkRheXMuT05FX1dFRUssXG4gICAgICAgIHJvbGU6IGJhc2ljTGFtYmRhUm9sZSxcbiAgICAgIH1cbiAgICApO1xuXG5cbiAgICBkZWxldGVPbGREZXBsb3ltZW50cy5hZGRUb1JvbGVQb2xpY3koXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgIFwibG9nczpDcmVhdGVMb2dHcm91cFwiLFxuICAgICAgICAgIFwibG9nczpDcmVhdGVMb2dTdHJlYW1cIixcbiAgICAgICAgICBcImxvZ3M6UHV0TG9nRXZlbnRzXCIsXG4gICAgICAgIF0sXG4gICAgICAgIHJlc291cmNlczogW1wiYXJuOmF3czpsb2dzOio6KjoqXCJdLFxuICAgICAgfSlcbiAgICApO1xuXG4gICAgYWRkQ2ZuU3VwcHJlc3NSdWxlcyhkZWxldGVPbGREZXBsb3ltZW50cywgW1xuICAgICAge1xuICAgICAgICBpZDogXCJXNThcIixcbiAgICAgICAgcmVhc29uOlxuICAgICAgICAgIFwiTGFtYmRhIGhhcyBDbG91ZFdhdGNoIHBlcm1pc3Npb25zIGJ5IHVzaW5nIHNlcnZpY2Ugcm9sZSBBV1NMYW1iZGFCYXNpY0V4ZWN1dGlvblJvbGVcIixcbiAgICAgIH0sXG4gICAgXSk7XG4gICAgYWRkQ2ZuU3VwcHJlc3NSdWxlcyhkZWxldGVPbGREZXBsb3ltZW50cywgW1xuICAgICAge1xuICAgICAgICBpZDogXCJXODlcIixcbiAgICAgICAgcmVhc29uOlxuICAgICAgICAgIFwiV2UgZG9uIHQgaGF2ZSBhbnkgVlBDIGluIHRoZSBzdGFjaywgd2Ugb25seSB1c2Ugc2VydmVybGVzcyBzZXJ2aWNlc1wiLFxuICAgICAgfSxcbiAgICBdKTtcbiAgICBhZGRDZm5TdXBwcmVzc1J1bGVzKGRlbGV0ZU9sZERlcGxveW1lbnRzLCBbXG4gICAgICB7XG4gICAgICAgIGlkOiBcIlc5MlwiLFxuICAgICAgICByZWFzb246XG4gICAgICAgICAgXCJObyBuZWVkIGZvciBSZXNlcnZlZENvbmN1cnJlbnRFeGVjdXRpb25zLCBzb21lIGFyZSB1c2VkIG9ubHkgZm9yIHRoZSBkZW1vIHdlYnNpdGUsIGFuZCBvdGhlcnMgYXJlIG5vdCB1c2VkIGluIGEgY29uY3VycmVudCBtb2RlLlwiLFxuICAgICAgfSxcbiAgICBdKTtcblxuICAgIHBhcmFtcy5ob3N0aW5nQnVja2V0LmdyYW50UmVhZFdyaXRlKGRlbGV0ZU9sZERlcGxveW1lbnRzKTtcblxuICAgIE5hZ1N1cHByZXNzaW9ucy5hZGRSZXNvdXJjZVN1cHByZXNzaW9ucyhcbiAgICAgIGJhc2ljTGFtYmRhUm9sZSxcbiAgICAgIFtcbiAgICAgICAge1xuICAgICAgICAgIGlkOiBcIkF3c1NvbHV0aW9ucy1JQU01XCIsXG4gICAgICAgICAgcmVhc29uOiBcIlBlcm1pc3Npb25zIHRvIGdldCBvYmplY3RzIGFuZCBkZWxldGUgdGhlbSBpcyByZXF1aXJlZFwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIHRydWVcbiAgICApO1xuXG4gICAgY29uc3Qgc3VjY2Vzc1N0YXRlID0gbmV3IHNmbi5QYXNzKHRoaXMsIFwiU3VjY2Vzc1N0YXRlXCIpO1xuXG4gICAgY29uc3QgdXBkYXRlQ2xvdWRGcm9udEZ1bmN0aW9uSm9iID0gbmV3IHRhc2tzLkxhbWJkYUludm9rZShcbiAgICAgIHRoaXMsXG4gICAgICBcIlVwZGF0ZSBLZXlWYWx1ZVN0b3JlXCIsXG4gICAgICB7XG4gICAgICAgIGxhbWJkYUZ1bmN0aW9uOiB1cGRhdGVLdnMsXG4gICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICB9XG4gICAgKTtcblxuICAgIGNvbnN0IGRlbGV0ZU9sZERlcGxveW1lbnRzSm9iID0gbmV3IHRhc2tzLkxhbWJkYUludm9rZShcbiAgICAgIHRoaXMsXG4gICAgICBcIlB1cmdlIHByZXZpb3VzIGRlcGxveW1lbnRzIGZyb20gUzNcIixcbiAgICAgIHtcbiAgICAgICAgbGFtYmRhRnVuY3Rpb246IGRlbGV0ZU9sZERlcGxveW1lbnRzLFxuICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgfVxuICAgICk7XG5cblxuICAgIGNvbnN0IGNvbW11bkRlZmluaXRpb24gPSB1cGRhdGVDbG91ZEZyb250RnVuY3Rpb25Kb2JcbiAgICAgIC5uZXh0KGRlbGV0ZU9sZERlcGxveW1lbnRzSm9iKTtcblxuICAgIHZhciBzdGVwRnVuY3Rpb25EZWZpbml0aW9uOiBJQ2hhaW5hYmxlO1xuXG4gICAgaWYgKHBhcmFtcy5zc21Db21taXRJZFBhcmFtKSB7XG4gICAgICBjb25zdCBnZXRDb21taXRJZCA9IG5ldyB0YXNrcy5DYWxsQXdzU2VydmljZShcbiAgICAgICAgdGhpcyxcbiAgICAgICAgXCJHZXQgQ29tbWl0SUQgZnJvbSBQYXJhbWV0ZXIgU3RvcmVcIixcbiAgICAgICAge1xuICAgICAgICAgIHNlcnZpY2U6IFwic3NtXCIsXG4gICAgICAgICAgYWN0aW9uOiBcImdldFBhcmFtZXRlclwiLFxuICAgICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgIE5hbWU6IHBhcmFtcy5zc21Db21taXRJZFBhcmFtLnBhcmFtZXRlck5hbWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBpYW1SZXNvdXJjZXM6IFtwYXJhbXMuc3NtQ29tbWl0SWRQYXJhbS5wYXJhbWV0ZXJBcm5dLFxuICAgICAgICAgIGlhbUFjdGlvbjogXCJzc206Z2V0UGFyYW1ldGVyXCIsXG4gICAgICAgICAgcmVzdWx0U2VsZWN0b3I6IHtcbiAgICAgICAgICAgIGNvbW1pdElkOiBzZm4uSnNvblBhdGguc3RyaW5nQXQoXCIkLlBhcmFtZXRlci5WYWx1ZVwiKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICBjb25zdCBzc21IYXNWYWx1ZSA9IG5ldyBzZm4uQ2hvaWNlKHRoaXMsIFwiU1NNIFBhcmFtIGlzIFNFVCA/XCIpXG4gICAgICAgIC53aGVuKHNmbi5Db25kaXRpb24uc3RyaW5nRXF1YWxzKFwiJC5jb21taXRJZFwiLCBcImluaXRcIiksIHN1Y2Nlc3NTdGF0ZSlcbiAgICAgICAgLm90aGVyd2lzZShjb21tdW5EZWZpbml0aW9uKTtcblxuICAgICAgc3RlcEZ1bmN0aW9uRGVmaW5pdGlvbiA9IGdldENvbW1pdElkLm5leHQoc3NtSGFzVmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdGVwRnVuY3Rpb25EZWZpbml0aW9uID0gY29tbXVuRGVmaW5pdGlvbjtcbiAgICB9XG5cbiAgICBjb25zdCBzZm5Mb2cgPSBuZXcgTG9nR3JvdXAodGhpcywgXCJzZm5Mb2dcIiwge1xuICAgICAgbG9nR3JvdXBOYW1lOlxuICAgICAgXCIvYXdzL3ZlbmRlZGxvZ3Mvc3RhdGVzL1wiICsgU3RhY2sub2YodGhpcykuc3RhY2tOYW1lLFxuICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgcmV0ZW50aW9uOiBSZXRlbnRpb25EYXlzLk9ORV9XRUVLLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zdGVwRnVuY3Rpb24gPSBuZXcgc2ZuLlN0YXRlTWFjaGluZSh0aGlzLCBcIlN0YXRpY0hvc3RpbmdTRlwiLCB7XG4gICAgICBkZWZpbml0aW9uQm9keSA6IHNmbi5EZWZpbml0aW9uQm9keS5mcm9tQ2hhaW5hYmxlKHN0ZXBGdW5jdGlvbkRlZmluaXRpb24pLFxuICAgICAgdHJhY2luZ0VuYWJsZWQ6IHRydWUsXG4gICAgICBsb2dzOiB7XG4gICAgICAgIGRlc3RpbmF0aW9uOiBzZm5Mb2csXG4gICAgICAgIGluY2x1ZGVFeGVjdXRpb25EYXRhOiB0cnVlLFxuICAgICAgICBsZXZlbDogTG9nTGV2ZWwuQUxMLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIE5hZ1N1cHByZXNzaW9ucy5hZGRSZXNvdXJjZVN1cHByZXNzaW9ucyhcbiAgICAgIHRoaXMuc3RlcEZ1bmN0aW9uLFxuICAgICAgW1xuICAgICAgICB7XG4gICAgICAgICAgaWQ6IFwiQXdzU29sdXRpb25zLUlBTTVcIixcbiAgICAgICAgICByZWFzb246IFwiUmVxdWlyZWQgcGVybWlzc2lvbnMgZm9yIHRoaXMgU3RlcCBGdW5jdGlvblwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIHRydWVcbiAgICApO1xuICB9XG59XG4iXX0=