UNPKG

@aws-solutions-constructs/core

Version:
143 lines 23.4 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. A copy of the License is located at * * http://www.apache.org/licenses/LICENSE-2.0 * * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * and limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.buildWebSocketQueueApi = buildWebSocketQueueApi; exports.buildWebSocketApiProps = buildWebSocketApiProps; exports.buildWebSocketQueueRouteOptions = buildWebSocketQueueRouteOptions; const cdk = require("aws-cdk-lib"); const apigateway = require("aws-cdk-lib/aws-apigateway"); const apigwv2 = require("aws-cdk-lib/aws-apigatewayv2"); const aws_apigatewayv2_integrations_1 = require("aws-cdk-lib/aws-apigatewayv2-integrations"); const iam = require("aws-cdk-lib/aws-iam"); const cloudwatch_log_group_helper_1 = require("./cloudwatch-log-group-helper"); const utils_1 = require("./utils"); const websocket_api_defaults_1 = require("./websocket-api-defaults"); /** * Builds an AWS API Gateway WebSocket API integrated with an Amazon SQS queue. * * @param scope The construct scope where the resources will be created. * @param id The unique ID for the resources. * @param props The configuration properties for the WebSocket API and SQS queue integration. * @returns */ function buildWebSocketQueueApi(scope, id, props) { // Setup the API Gateway role const apiGatewayRole = new iam.Role(scope, "LambdaRestApiCloudWatchRole", { assumedBy: new iam.ServicePrincipal("apigateway.amazonaws.com"), }); props.queue.grantSendMessages(apiGatewayRole); const finalProps = (0, utils_1.consolidateProps)(buildWebSocketApiProps(apiGatewayRole, props.queue, props.createDefaultRoute, props.defaultRouteRequestTemplate, props.defaultIamAuthorization), props.webSocketApiProps); const webSocketApi = buildApiGatewayV2WebSocket(scope, id, { webSocketApiProps: finalProps, existingWebSocketApi: props.existingWebSocketApi, }); if (props.customRouteName) { webSocketApi.addRoute(props.customRouteName, buildWebSocketQueueRouteOptions(apiGatewayRole, props.queue, props.customRouteName, props.defaultRouteRequestTemplate)); } if (props.existingWebSocketApi === undefined && props.defaultIamAuthorization === false && finalProps.connectRouteOptions?.authorizer === undefined) { (0, utils_1.printWarning)("This construct will create a WebSocket with NO Authorizer (defaultIamAuthorization is set to false)."); } const webSocketStage = new apigwv2.WebSocketStage(scope, "Stage", { stageName: "prod", webSocketApi, autoDeploy: true, }); (0, utils_1.addCfnGuardSuppressRules)(webSocketStage, ["API_GW_CACHE_ENABLED_AND_ENCRYPTED"]); const apiGatewayLogGroup = (0, cloudwatch_log_group_helper_1.buildLogGroup)(scope, "LogGroup", props.logGroupProps); apiGatewayLogGroup.grant(apiGatewayRole, "logs:CreateLogGroup", "logs:CreateLogStream", "logs:DescribeLogGroups", "logs:DescribeLogStreams", "logs:PutLogEvents", "logs:GetLogEvents", "logs:FilterLogEvents"); const cfnStage = webSocketStage.node.defaultChild; cfnStage.addPropertyOverride("AccessLogSettings", { DestinationArn: apiGatewayLogGroup.logGroupArn, Format: apigateway.AccessLogFormat.clf().toString(), }); cfnStage.addPropertyOverride("DefaultRouteSettings", { DataTraceEnabled: false, DetailedMetricsEnabled: true, LoggingLevel: "ERROR", }); (0, utils_1.addCfnSuppressRules)(webSocketStage, [ { id: "AwsSolutions-APIG1", reason: "Access logging configuration has been provided as per ApiGateway v2 requirements", }, ]); (0, utils_1.addCfnSuppressRules)(apiGatewayRole.node.tryFindChild("DefaultPolicy")?.node.tryFindChild("Resource"), [ { id: "AwsSolutions-IAM5", reason: "The APIGateway requires permissions to KMS so that it can write to an encrypted SQS queue", }, ]); return { webSocketApi, webSocketStage, apiGatewayRole, apiGatewayLogGroup, }; } /** * build ApiGateway v2 WebSocket L2 construct. If existing WebSocketApi instance is provided, it returns that instance, * if not, it creates a new WebSocketApi using the user provided props. * * @param scope * @param props * @returns */ function buildApiGatewayV2WebSocket(scope, id, props) { if (props.existingWebSocketApi) { return props.existingWebSocketApi; } else { return new apigwv2.WebSocketApi(scope, `WebSocketApi${id}`, props.webSocketApiProps); } } /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ function buildWebSocketApiProps(role, sqsQueue, createDefaultRoute, requestTemplate, defaultIamAuthorization) { if (createDefaultRoute) { if (!role || !sqsQueue) { throw new Error("role and sqs must be provided to create a default route"); } } // prettier-ignore // Sonar exception reason: - typescript:S6571 - required because we are not passing all values. Using partial may cause @jsii to not work. const websocketApiProps = { defaultRouteOptions: createDefaultRoute ? buildWebSocketQueueRouteOptions(role, sqsQueue, '$default', requestTemplate) : undefined, connectRouteOptions: (defaultIamAuthorization === undefined || defaultIamAuthorization === true) ? websocket_api_defaults_1.connectRouteOptions : undefined }; return websocketApiProps; } /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ function buildWebSocketQueueRouteOptions(role, sqsQueue, routeName, requestTemplate) { return { integration: new aws_apigatewayv2_integrations_1.WebSocketAwsIntegration(routeName, { integrationMethod: apigwv2.HttpMethod.POST, integrationUri: `arn:${cdk.Aws.PARTITION}:apigateway:${cdk.Aws.REGION}:sqs:path/${cdk.Aws.ACCOUNT_ID}/${sqsQueue.queueName}`, requestTemplates: requestTemplate ?? { [routeName === "$default" ? "$default" : routeName]: websocket_api_defaults_1.DEFAULT_ROUTE_QUEUE_VTL_CONFIG, }, templateSelectionExpression: routeName === "$default" ? "\\$default" : routeName, passthroughBehavior: apigwv2.PassthroughBehavior.NEVER, credentialsRole: role, requestParameters: { "integration.request.header.Content-Type": "'application/x-www-form-urlencoded'", }, }), }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vic29ja2V0LWFwaS1oZWxwZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ3ZWJzb2NrZXQtYXBpLWhlbHBlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7O0dBV0c7O0FBbURILHdEQWdHQztBQXFCRCx3REFvQkM7QUFLRCwwRUFxQkM7QUFwTkQsbUNBQW1DO0FBQ25DLHlEQUF5RDtBQUN6RCx3REFBd0Q7QUFDeEQsNkZBQW9GO0FBQ3BGLDJDQUEyQztBQUkzQywrRUFBOEQ7QUFDOUQsbUNBQXdHO0FBQ3hHLHFFQUErRjtBQStCL0Y7Ozs7Ozs7R0FPRztBQUNILFNBQWdCLHNCQUFzQixDQUNwQyxLQUFnQixFQUNoQixFQUFVLEVBQ1YsS0FBb0M7SUFFcEMsNkJBQTZCO0lBQzdCLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsNkJBQTZCLEVBQUU7UUFDeEUsU0FBUyxFQUFFLElBQUksR0FBRyxDQUFDLGdCQUFnQixDQUFDLDBCQUEwQixDQUFDO0tBQ2hFLENBQUMsQ0FBQztJQUNILEtBQUssQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDOUMsTUFBTSxVQUFVLEdBQUcsSUFBQSx3QkFBZ0IsRUFDakMsc0JBQXNCLENBQ3BCLGNBQWMsRUFDZCxLQUFLLENBQUMsS0FBSyxFQUNYLEtBQUssQ0FBQyxrQkFBa0IsRUFDeEIsS0FBSyxDQUFDLDJCQUEyQixFQUNqQyxLQUFLLENBQUMsdUJBQXVCLENBQzlCLEVBQ0QsS0FBSyxDQUFDLGlCQUFpQixDQUNLLENBQUM7SUFDL0IsTUFBTSxZQUFZLEdBQUcsMEJBQTBCLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtRQUN6RCxpQkFBaUIsRUFBRSxVQUFVO1FBQzdCLG9CQUFvQixFQUFFLEtBQUssQ0FBQyxvQkFBb0I7S0FDakQsQ0FBQyxDQUFDO0lBRUgsSUFBSSxLQUFLLENBQUMsZUFBZSxFQUFF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QVksQ0FBQyxDQUFDLENBQUMsU0FBUztZQUNoRixtQkFBbUIsRUFBRSxPQUFPLENBQUMsbUJBQW1CLENBQUMsS0FBSztZQUN0RCxlQUFlLEVBQUUsSUFBSTtZQUNyQixpQkFBaUIsRUFBRTtnQkFDakIseUNBQXlDLEVBQUUscUNBQXFDO2FBQ2pGO1NBQ0YsQ0FBQztLQUNILENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiAgQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIikuIFlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqICB3aXRoIHRoZSBMaWNlbnNlLiBBIGNvcHkgb2YgdGhlIExpY2Vuc2UgaXMgbG9jYXRlZCBhdFxuICpcbiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogIG9yIGluIHRoZSAnbGljZW5zZScgZmlsZSBhY2NvbXBhbnlpbmcgdGhpcyBmaWxlLiBUaGlzIGZpbGUgaXMgZGlzdHJpYnV0ZWQgb24gYW4gJ0FTIElTJyBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTXG4gKiAgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZXhwcmVzcyBvciBpbXBsaWVkLiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnNcbiAqICBhbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0ICogYXMgY2RrIGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0ICogYXMgYXBpZ2F0ZXdheSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWFwaWdhdGV3YXlcIjtcbmltcG9ydCAqIGFzIGFwaWd3djIgZnJvbSBcImF3cy1jZGstbGliL2F3cy1hcGlnYXRld2F5djJcIjtcbmltcG9ydCB7IFdlYlNvY2tldEF3c0ludGVncmF0aW9uIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1hcGlnYXRld2F5djItaW50ZWdyYXRpb25zXCI7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1pYW1cIjtcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSBcImF3cy1jZGstbGliL2F3cy1sb2dzXCI7XG5pbXBvcnQgKiBhcyBzcXMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zcXNcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBidWlsZExvZ0dyb3VwIH0gZnJvbSBcIi4vY2xvdWR3YXRjaC1sb2ctZ3JvdXAtaGVscGVyXCI7XG5pbXBvcnQgeyBhZGRDZm5HdWFyZFN1cHByZXNzUnVsZXMsIGFkZENmblN1cHByZXNzUnVsZXMsIGNvbnNvbGlkYXRlUHJvcHMsIHByaW50V2FybmluZyB9IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgeyBjb25uZWN0Um91dGVPcHRpb25zLCBERUZBVUxUX1JPVVRFX1FVRVVFX1ZUTF9DT05GSUcgfSBmcm9tIFwiLi93ZWJzb2NrZXQtYXBpLWRlZmF1bHRzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQnVpbGRXZWJTb2NrZXRRdWV1ZUFwaVJlc3BvbnNlIHtcbiAgcmVhZG9ubHkgd2ViU29ja2V0QXBpOiBhcGlnd3YyLldlYlNvY2tldEFwaTtcbiAgcmVhZG9ubHkgd2ViU29ja2V0U3RhZ2U6IGFwaWd3djIuV2ViU29ja2V0U3RhZ2U7XG4gIHJlYWRvbmx5IGFwaUdhdGV3YXlSb2xlOiBpYW0uUm9sZTtcbiAgcmVhZG9ubHkgYXBpR2F0ZXdheUxvZ0dyb3VwOiBsb2dzLkxvZ0dyb3VwO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkV2ViU29ja2V0QXBpUHJvcHMge1xuICAvKipcbiAgICogRXhpc3RpbmcgaW5zdGFuY2Ugb2YgQXBpR2F0ZXdheSB2MiBXZWJTb2NrZXRcbiAgICovXG4gIHJlYWRvbmx5IGV4aXN0aW5nV2ViU29ja2V0QXBpPzogYXBpZ3d2Mi5XZWJTb2NrZXRBcGk7XG5cbiAgLyoqXG4gICAqIFVzZXIgcHJvdmlkZWQgcHJvcGVydGllcyBvZiBBcGlnYXRld2F5IHYyIFdlYlNvY2tldFxuICAgKi9cbiAgcmVhZG9ubHkgd2ViU29ja2V0QXBpUHJvcHM/OiBhcGlnd3YyLldlYlNvY2tldEFwaVByb3BzO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkV2ViU29ja2V0UXVldWVBcGlSZXF1ZXN0IHtcbiAgcmVhZG9ubHkgcXVldWU6IHNxcy5JUXVldWU7XG4gIHJlYWRvbmx5IGRlZmF1bHRSb3V0ZVJlcXVlc3RUZW1wbGF0ZT86IHsgW2NvbnRlbnRUeXBlOiBzdHJpbmddOiBzdHJpbmcgfTtcbiAgcmVhZG9ubHkgY3JlYXRlRGVmYXVsdFJvdXRlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgd2ViU29ja2V0QXBpUHJvcHM/OiBhcGlnd3YyLldlYlNvY2tldEFwaVByb3BzO1xuICByZWFkb25seSBleGlzdGluZ1dlYlNvY2tldEFwaT86IGFwaWd3djIuV2ViU29ja2V0QXBpO1xuICByZWFkb25seSBsb2dHcm91cFByb3BzPzogbG9ncy5Mb2dHcm91cFByb3BzO1xuICByZWFkb25seSBkZWZhdWx0SWFtQXV0aG9yaXphdGlvbj86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGN1c3RvbVJvdXRlTmFtZT86IHN0cmluZztcbn1cbi8qKlxuICogQnVpbGRzIGFuIEFXUyBBUEkgR2F0ZXdheSBXZWJTb2NrZXQgQVBJIGludGVncmF0ZWQgd2l0aCBhbiBBbWF6b24gU1FTIHF1ZXVlLlxuICpcbiAqIEBwYXJhbSBzY29wZSBUaGUgY29uc3RydWN0IHNjb3BlIHdoZXJlIHRoZSByZXNvdXJjZXMgd2lsbCBiZSBjcmVhdGVkLlxuICogQHBhcmFtIGlkIFRoZSB1bmlxdWUgSUQgZm9yIHRoZSByZXNvdXJjZXMuXG4gKiBAcGFyYW0gcHJvcHMgVGhlIGNvbmZpZ3VyYXRpb24gcHJvcGVydGllcyBmb3IgdGhlIFdlYlNvY2tldCBBUEkgYW5kIFNRUyBxdWV1ZSBpbnRlZ3JhdGlvbi5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFdlYlNvY2tldFF1ZXVlQXBpKFxuICBzY29wZTogQ29uc3RydWN0LFxuICBpZDogc3RyaW5nLFxuICBwcm9wczogQnVpbGRXZWJTb2NrZXRRdWV1ZUFwaVJlcXVlc3Rcbik6IEJ1aWxkV2ViU29ja2V0UXVldWVBcGlSZXNwb25zZSB7XG4gIC8vIFNldHVwIHRoZSBBUEkgR2F0ZXdheSByb2xlXG4gIGNvbnN0IGFwaUdhdGV3YXlSb2xlID0gbmV3IGlhbS5Sb2xlKHNjb3BlLCBcIkxhbWJkYVJlc3RBcGlDbG91ZFdhdGNoUm9sZVwiLCB7XG4gICAgYXNzdW1lZEJ5OiBuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoXCJhcGlnYXRld2F5LmFtYXpvbmF3cy5jb21cIiksXG4gIH0pO1xuICBwcm9wcy5xdWV1ZS5ncmFudFNlbmRNZXNzYWdlcyhhcGlHYXRld2F5Um9sZSk7XG4gIGNvbnN0IGZpbmFsUHJvcHMgPSBjb25zb2xpZGF0ZVByb3BzKFxuICAgIGJ1aWxkV2ViU29ja2V0QXBpUHJvcHMoXG4gICAgICBhcGlHYXRld2F5Um9sZSxcbiAgICAgIHByb3BzLnF1ZXVlLFxuICAgICAgcHJvcHMuY3JlYXRlRGVmYXVsdFJvdXRlLFxuICAgICAgcHJvcHMuZGVmYXVsdFJvdXRlUmVxdWVzdFRlbXBsYXRlLFxuICAgICAgcHJvcHMuZGVmYXVsdElhbUF1dGhvcml6YXRpb25cbiAgICApLFxuICAgIHByb3BzLndlYlNvY2tldEFwaVByb3BzXG4gICkgYXMgYXBpZ3d2Mi5XZWJTb2NrZXRBcGlQcm9wcztcbiAgY29uc3Qgd2ViU29ja2V0QXBpID0gYnVpbGRBcGlHYXRld2F5VjJXZWJTb2NrZXQoc2NvcGUsIGlkLCB7XG4gICAgd2ViU29ja2V0QXBpUHJvcHM6IGZpbmFsUHJvcHMsXG4gICAgZXhpc3RpbmdXZWJTb2NrZXRBcGk6IHByb3BzLmV4aXN0aW5nV2ViU29ja2V0QXBpLFxuICB9KTtcblxuICBpZiAocHJvcHMuY3VzdG9tUm91dGVOYW1lKSB7XG4gICAgd2ViU29ja2V0QXBpLmFkZFJvdXRlKFxuICAgICAgcHJvcHMuY3VzdG9tUm91dGVOYW1lLFxuICAgICAgYnVpbGRXZWJTb2NrZXRRdWV1ZVJvdXRlT3B0aW9ucyhhcGlHYXRld2F5Um9sZSwgcHJvcHMucXVldWUsIHByb3BzLmN1c3RvbVJvdXRlTmFtZSwgcHJvcHMuZGVmYXVsdFJvdXRlUmVxdWVzdFRlbXBsYXRlKVxuICAgICk7XG4gIH1cblxuICBpZiAoXG4gICAgcHJvcHMuZXhpc3RpbmdXZWJTb2NrZXRBcGkgPT09IHVuZGVmaW5lZCAmJlxuICAgIHByb3BzLmRlZmF1bHRJYW1BdXRob3JpemF0aW9uID09PSBmYWxzZSAmJlxuICAgIGZpbmFsUHJvcHMuY29ubmVjdFJvdXRlT3B0aW9ucz8uYXV0aG9yaXplciA9PT0gdW5kZWZpbmVkXG4gICkge1xuICAgIHByaW50V2FybmluZyhcbiAgICAgIFwiVGhpcyBjb25zdHJ1Y3Qgd2lsbCBjcmVhdGUgYSBXZWJTb2NrZXQgd2l0aCBOTyBBdXRob3JpemVyIChkZWZhdWx0SWFtQXV0aG9yaXphdGlvbiBpcyBzZXQgdG8gZmFsc2UpLlwiXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IHdlYlNvY2tldFN0YWdlID0gbmV3IGFwaWd3djIuV2ViU29ja2V0U3RhZ2Uoc2NvcGUsIFwiU3RhZ2VcIiwge1xuICAgIHN0YWdlTmFtZTogXCJwcm9kXCIsXG4gICAgd2ViU29ja2V0QXBpLFxuICAgIGF1dG9EZXBsb3k6IHRydWUsXG4gIH0pO1xuXG4gIGFkZENmbkd1YXJkU3VwcHJlc3NSdWxlcyh3ZWJTb2NrZXRTdGFnZSwgW1wiQVBJX0dXX0NBQ0hFX0VOQUJMRURfQU5EX0VOQ1JZUFRFRFwiXSk7XG5cbiAgY29uc3QgYXBpR2F0ZXdheUxvZ0dyb3VwID0gYnVpbGRMb2dHcm91cChzY29wZSwgXCJMb2dHcm91cFwiLCBwcm9wcy5sb2dHcm91cFByb3BzKTtcbiAgYXBpR2F0ZXdheUxvZ0dyb3VwLmdyYW50KFxuICAgIGFwaUdhdGV3YXlSb2xlLFxuICAgIFwibG9nczpDcmVhdGVMb2dHcm91cFwiLFxuICAgIFwibG9nczpDcmVhdGVMb2dTdHJlYW1cIixcbiAgICBcImxvZ3M6RGVzY3JpYmVMb2dHcm91cHNcIixcbiAgICBcImxvZ3M6RGVzY3JpYmVMb2dTdHJlYW1zXCIsXG4gICAgXCJsb2dzOlB1dExvZ0V2ZW50c1wiLFxuICAgIFwibG9nczpHZXRMb2dFdmVudHNcIixcbiAgICBcImxvZ3M6RmlsdGVyTG9nRXZlbnRzXCJcbiAgKTtcblxuICBjb25zdCBjZm5TdGFnZTogYXBpZ3d2Mi5DZm5TdGFnZSA9IHdlYlNvY2tldFN0YWdlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGFwaWd3djIuQ2ZuU3RhZ2U7XG4gIGNmblN0YWdlLmFkZFByb3BlcnR5T3ZlcnJpZGUoXCJBY2Nlc3NMb2dTZXR0aW5nc1wiLCB7XG4gICAgRGVzdGluYXRpb25Bcm46IGFwaUdhdGV3YXlMb2dHcm91cC5sb2dHcm91cEFybixcbiAgICBGb3JtYXQ6IGFwaWdhdGV3YXkuQWNjZXNzTG9nRm9ybWF0LmNsZigpLnRvU3RyaW5nKCksXG4gIH0pO1xuICBjZm5TdGFnZS5hZGRQcm9wZXJ0eU92ZXJyaWRlKFwiRGVmYXVsdFJvdXRlU2V0dGluZ3NcIiwge1xuICAgIERhdGFUcmFjZUVuYWJsZWQ6IGZhbHNlLFxuICAgIERldGFpbGVkTWV0cmljc0VuYWJsZWQ6IHRydWUsXG4gICAgTG9nZ2luZ0xldmVsOiBcIkVSUk9SXCIsXG4gIH0pO1xuXG4gIGFkZENmblN1cHByZXNzUnVsZXMod2ViU29ja2V0U3RhZ2UsIFtcbiAgICB7XG4gICAgICBpZDogXCJBd3NTb2x1dGlvbnMtQVBJRzFcIixcbiAgICAgIHJlYXNvbjogXCJBY2Nlc3MgbG9nZ2luZyBjb25maWd1cmF0aW9uIGhhcyBiZWVuIHByb3ZpZGVkIGFzIHBlciBBcGlHYXRld2F5IHYyIHJlcXVpcmVtZW50c1wiLFxuICAgIH0sXG4gIF0pO1xuXG4gIGFkZENmblN1cHByZXNzUnVsZXMoXG4gICAgYXBpR2F0ZXdheVJvbGUubm9kZS50cnlGaW5kQ2hpbGQoXCJEZWZhdWx0UG9saWN5XCIpPy5ub2RlLnRyeUZpbmRDaGlsZChcIlJlc291cmNlXCIpIGFzIGNkay5DZm5SZXNvdXJjZSxcbiAgICBbXG4gICAgICB7XG4gICAgICAgIGlkOiBcIkF3c1NvbHV0aW9ucy1JQU01XCIsXG4gICAgICAgIHJlYXNvbjogXCJUaGUgQVBJR2F0ZXdheSByZXF1aXJlcyBwZXJtaXNzaW9ucyB0byBLTVMgc28gdGhhdCBpdCBjYW4gd3JpdGUgdG8gYW4gZW5jcnlwdGVkIFNRUyBxdWV1ZVwiLFxuICAgICAgfSxcbiAgICBdXG4gICk7XG5cbiAgcmV0dXJuIHtcbiAgICB3ZWJTb2NrZXRBcGksXG4gICAgd2ViU29ja2V0U3RhZ2UsXG4gICAgYXBpR2F0ZXdheVJvbGUsXG4gICAgYXBpR2F0ZXdheUxvZ0dyb3VwLFxuICB9O1xufVxuXG4vKipcbiAqIGJ1aWxkIEFwaUdhdGV3YXkgdjIgV2ViU29ja2V0IEwyIGNvbnN0cnVjdC4gSWYgZXhpc3RpbmcgV2ViU29ja2V0QXBpIGluc3RhbmNlIGlzIHByb3ZpZGVkLCBpdCByZXR1cm5zIHRoYXQgaW5zdGFuY2UsXG4gKiBpZiBub3QsIGl0IGNyZWF0ZXMgYSBuZXcgV2ViU29ja2V0QXBpIHVzaW5nIHRoZSB1c2VyIHByb3ZpZGVkIHByb3BzLlxuICpcbiAqIEBwYXJhbSBzY29wZVxuICogQHBhcmFtIHByb3BzXG4gKiBAcmV0dXJuc1xuICovXG5mdW5jdGlvbiBidWlsZEFwaUdhdGV3YXlWMldlYlNvY2tldChzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQnVpbGRXZWJTb2NrZXRBcGlQcm9wcyk6IGFwaWd3djIuV2ViU29ja2V0QXBpIHtcbiAgaWYgKHByb3BzLmV4aXN0aW5nV2ViU29ja2V0QXBpKSB7XG4gICAgcmV0dXJuIHByb3BzLmV4aXN0aW5nV2ViU29ja2V0QXBpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBuZXcgYXBpZ3d2Mi5XZWJTb2NrZXRBcGkoc2NvcGUsIGBXZWJTb2NrZXRBcGkke2lkfWAsIHByb3BzLndlYlNvY2tldEFwaVByb3BzKTtcbiAgfVxufVxuXG4vKipcbiAqIEBpbnRlcm5hbCBUaGlzIGlzIGFuIGludGVybmFsIGNvcmUgZnVuY3Rpb24gYW5kIHNob3VsZCBub3QgYmUgY2FsbGVkIGRpcmVjdGx5IGJ5IFNvbHV0aW9ucyBDb25zdHJ1Y3RzIGNsaWVudHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFdlYlNvY2tldEFwaVByb3BzKFxuICByb2xlPzogaWFtLlJvbGUsXG4gIHNxc1F1ZXVlPzogc3FzLklRdWV1ZSxcbiAgY3JlYXRlRGVmYXVsdFJvdXRlPzogYm9vbGVhbixcbiAgcmVxdWVzdFRlbXBsYXRlPzogeyBbY29udGVudFR5cGU6IHN0cmluZ106IHN0cmluZyB9LFxuICBkZWZhdWx0SWFtQXV0aG9yaXphdGlvbj86IGJvb2xlYW5cbik6IGFwaWd3djIuV2ViU29ja2V0QXBpUHJvcHMge1xuICBpZiAoY3JlYXRlRGVmYXVsdFJvdXRlKSB7XG4gICAgaWYgKCFyb2xlIHx8ICFzcXNRdWV1ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwicm9sZSBhbmQgc3FzIG11c3QgYmUgcHJvdmlkZWQgdG8gY3JlYXRlIGEgZGVmYXVsdCByb3V0ZVwiKTtcbiAgICB9XG4gIH1cblxuICAvLyBwcmV0dGllci1pZ25vcmVcbiAgLy8gU29uYXIgZXhjZXB0aW9uIHJlYXNvbjogLSB0eXBlc2NyaXB0OlM2NTcxIC0gcmVxdWlyZWQgYmVjYXVzZSB3ZSBhcmUgbm90IHBhc3NpbmcgYWxsIHZhbHVlcy4gVXNpbmcgcGFydGlhbCBtYXkgY2F1c2UgQGpzaWkgdG8gbm90IHdvcmsuXG4gIGNvbnN0IHdlYnNvY2tldEFwaVByb3BzOiBhcGlnd3YyLldlYlNvY2tldEFwaVByb3BzID0geyAvLyBOT1NPTkFSXG4gICAgZGVmYXVsdFJvdXRlT3B0aW9uczogY3JlYXRlRGVmYXVsdFJvdXRlID8gYnVpbGRXZWJTb2NrZXRRdWV1ZVJvdXRlT3B0aW9ucyhyb2xlISwgc3FzUXVldWUhLCAnJGRlZmF1bHQnLCByZXF1ZXN0VGVtcGxhdGUpIDogdW5kZWZpbmVkLFxuICAgIGNvbm5lY3RSb3V0ZU9wdGlvbnM6IChkZWZhdWx0SWFtQXV0aG9yaXphdGlvbiA9PT0gdW5kZWZpbmVkIHx8IGRlZmF1bHRJYW1BdXRob3JpemF0aW9uID09PSB0cnVlKSA/IGNvbm5lY3RSb3V0ZU9wdGlvbnMgOiB1bmRlZmluZWRcbiAgfTtcbiAgcmV0dXJuIHdlYnNvY2tldEFwaVByb3BzO1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbCBUaGlzIGlzIGFuIGludGVybmFsIGNvcmUgZnVuY3Rpb24gYW5kIHNob3VsZCBub3QgYmUgY2FsbGVkIGRpcmVjdGx5IGJ5IFNvbHV0aW9ucyBDb25zdHJ1Y3RzIGNsaWVudHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFdlYlNvY2tldFF1ZXVlUm91dGVPcHRpb25zKFxuICByb2xlOiBpYW0uUm9sZSxcbiAgc3FzUXVldWU6IHNxcy5JUXVldWUsXG4gIHJvdXRlTmFtZTogc3RyaW5nLFxuICByZXF1ZXN0VGVtcGxhdGU/OiB7IFtjb250ZW50VHlwZTogc3RyaW5nXTogc3RyaW5nIH1cbik6IGFwaWd3djIuV2ViU29ja2V0Um91dGVPcHRpb25zIHtcbiAgcmV0dXJuIHtcbiAgICBpbnRlZ3JhdGlvbjogbmV3IFdlYlNvY2tldEF3c0ludGVncmF0aW9uKHJvdXRlTmFtZSwge1xuICAgICAgaW50ZWdyYXRpb25NZXRob2Q6IGFwaWd3djIuSHR0cE1ldGhvZC5QT1NULFxuICAgICAgaW50ZWdyYXRpb25Vcmk6IGBhcm46JHtjZGsuQXdzLlBBUlRJVElPTn06YXBpZ2F0ZXdheToke2Nkay5Bd3MuUkVHSU9OfTpzcXM6cGF0aC8ke2Nkay5Bd3MuQUNDT1VOVF9JRH0vJHtzcXNRdWV1ZS5xdWV1ZU5hbWV9YCxcbiAgICAgIHJlcXVlc3RUZW1wbGF0ZXM6IHJlcXVlc3RUZW1wbGF0ZSA/PyB7XG4gICAgICAgIFtyb3V0ZU5hbWUgPT09IFwiJGRlZmF1bHRcIiA/IFwiJGRlZmF1bHRcIiA6IHJvdXRlTmFtZV06IERFRkFVTFRfUk9VVEVfUVVFVUVfVlRMX0NPTkZJRyxcbiAgICAgIH0sXG4gICAgICB0ZW1wbGF0ZVNlbGVjdGlvbkV4cHJlc3Npb246IHJvdXRlTmFtZSA9PT0gXCIkZGVmYXVsdFwiID8gXCJcXFxcJGRlZmF1bHRcIiA6IHJvdXRlTmFtZSxcbiAgICAgIHBhc3N0aHJvdWdoQmVoYXZpb3I6IGFwaWd3djIuUGFzc3Rocm91Z2hCZWhhdmlvci5ORVZFUixcbiAgICAgIGNyZWRlbnRpYWxzUm9sZTogcm9sZSxcbiAgICAgIHJlcXVlc3RQYXJhbWV0ZXJzOiB7XG4gICAgICAgIFwiaW50ZWdyYXRpb24ucmVxdWVzdC5oZWFkZXIuQ29udGVudC1UeXBlXCI6IFwiJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCdcIixcbiAgICAgIH0sXG4gICAgfSksXG4gIH07XG59XG4iXX0=