UNPKG

@aws/pdk

Version:

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

291 lines 48.7 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.TypeSafeRestApi = 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 fs = require("fs"); const path = require("path"); const monorepo_1 = require("../../monorepo"); const pdk_nag_1 = require("../../pdk-nag"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway"); const aws_iam_1 = require("aws-cdk-lib/aws-iam"); const aws_lambda_1 = require("aws-cdk-lib/aws-lambda"); const aws_logs_1 = require("aws-cdk-lib/aws-logs"); const aws_s3_assets_1 = require("aws-cdk-lib/aws-s3-assets"); const custom_resources_1 = require("aws-cdk-lib/custom-resources"); const cdk_nag_1 = require("cdk-nag"); const constructs_1 = require("constructs"); const prepare_spec_1 = require("./prepare-spec-event-handler/prepare-spec"); const api_gateway_auth_1 = require("./spec/api-gateway-auth"); const api_gateway_integrations_1 = require("./spec/api-gateway-integrations"); const open_api_gateway_web_acl_1 = require("./waf/open-api-gateway-web-acl"); /** * A construct for creating an api gateway rest api based on the definition in the OpenAPI spec. */ class TypeSafeRestApi extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); (0, monorepo_1.addMetric)(scope, "type-safe-rest-api"); const { integrations, specPath, operationLookup, defaultAuthorizer, corsOptions, outputSpecBucket, ...options } = props; // Upload the spec to s3 as an asset const inputSpecAsset = new aws_s3_assets_1.Asset(this, "InputSpec", { path: specPath, }); const prepareSpecOutputBucket = outputSpecBucket ?? inputSpecAsset.bucket; // We'll output the prepared spec in the same asset bucket const preparedSpecOutputKeyPrefix = `${inputSpecAsset.s3ObjectKey}-prepared`; const stack = aws_cdk_lib_1.Stack.of(this); // Lambda name prefix is truncated to 48 characters (16 below the max of 64) const lambdaNamePrefix = `${pdk_nag_1.PDKNag.getStackPrefix(stack) .split("/") .join("-") .slice(0, 40)}${this.node.addr.slice(-8).toUpperCase()}`; const prepareSpecLambdaName = `${lambdaNamePrefix}PrepSpec`; const prepareSpecRole = new aws_iam_1.Role(this, "PrepareSpecRole", { assumedBy: new aws_iam_1.ServicePrincipal("lambda.amazonaws.com"), inlinePolicies: { logs: new aws_iam_1.PolicyDocument({ statements: [ new aws_iam_1.PolicyStatement({ effect: aws_iam_1.Effect.ALLOW, actions: [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", ], resources: [ `arn:aws:logs:${stack.region}:${stack.account}:log-group:/aws/lambda/${prepareSpecLambdaName}`, `arn:aws:logs:${stack.region}:${stack.account}:log-group:/aws/lambda/${prepareSpecLambdaName}:*`, ], }), ], }), s3: new aws_iam_1.PolicyDocument({ statements: [ new aws_iam_1.PolicyStatement({ effect: aws_iam_1.Effect.ALLOW, actions: ["s3:getObject"], resources: [ inputSpecAsset.bucket.arnForObjects(inputSpecAsset.s3ObjectKey), ], }), new aws_iam_1.PolicyStatement({ effect: aws_iam_1.Effect.ALLOW, actions: ["s3:putObject"], resources: [ // The output file will include a hash of the prepared spec, which is not known until deploy time since // tokens must be resolved prepareSpecOutputBucket.arnForObjects(`${preparedSpecOutputKeyPrefix}/*`), ], }), ], }), }, }); ["AwsSolutions-IAM5", "AwsPrototyping-IAMNoWildcardPermissions"].forEach((RuleId) => { cdk_nag_1.NagSuppressions.addResourceSuppressions(prepareSpecRole, [ { id: RuleId, reason: "Cloudwatch resources have been scoped down to the LogGroup level, however * is still needed as stream names are created just in time.", appliesTo: [ { regex: `/^Resource::arn:aws:logs:${pdk_nag_1.PDKNag.getStackRegionRegex(stack)}:${pdk_nag_1.PDKNag.getStackAccountRegex(stack)}:log-group:/aws/lambda/${prepareSpecLambdaName}:\*/g`, }, ], }, { id: RuleId, reason: "S3 resources have been scoped down to the appropriate prefix in the CDK asset bucket, however * is still needed as since the prepared spec hash is not known until deploy time.", appliesTo: [ { regex: `/^Resource::arn:${pdk_nag_1.PDKNag.getStackPartitionRegex(stack)}:s3:.*/${preparedSpecOutputKeyPrefix}/\*/g`, }, ], }, ], true); }); // Create a custom resource for preparing the spec for deployment (adding integrations, authorizers, etc) const prepareSpec = new aws_lambda_1.Function(this, "PrepareSpecHandler", { handler: "index.handler", runtime: aws_lambda_1.Runtime.NODEJS_18_X, code: aws_lambda_1.Code.fromAsset(path.join(__dirname, "./prepare-spec-event-handler")), timeout: aws_cdk_lib_1.Duration.seconds(30), role: prepareSpecRole, functionName: prepareSpecLambdaName, }); const providerFunctionName = `${lambdaNamePrefix}PrepSpecProvider`; const providerRole = new aws_iam_1.Role(this, "PrepareSpecProviderRole", { assumedBy: new aws_iam_1.ServicePrincipal("lambda.amazonaws.com"), inlinePolicies: { logs: new aws_iam_1.PolicyDocument({ statements: [ new aws_iam_1.PolicyStatement({ effect: aws_iam_1.Effect.ALLOW, actions: [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", ], resources: [ `arn:aws:logs:${stack.region}:${stack.account}:log-group:/aws/lambda/${providerFunctionName}`, `arn:aws:logs:${stack.region}:${stack.account}:log-group:/aws/lambda/${providerFunctionName}:*`, ], }), ], }), }, }); const provider = new custom_resources_1.Provider(this, "PrepareSpecProvider", { onEventHandler: prepareSpec, role: providerRole, providerFunctionName, }); ["AwsSolutions-IAM5", "AwsPrototyping-IAMNoWildcardPermissions"].forEach((RuleId) => { cdk_nag_1.NagSuppressions.addResourceSuppressions(providerRole, [ { id: RuleId, reason: "Cloudwatch resources have been scoped down to the LogGroup level, however * is still needed as stream names are created just in time.", }, ], true); }); ["AwsSolutions-L1", "AwsPrototyping-LambdaLatestVersion"].forEach((RuleId) => { cdk_nag_1.NagSuppressions.addResourceSuppressions(provider, [ { id: RuleId, reason: "Latest runtime cannot be configured. CDK will need to upgrade the Provider construct accordingly.", }, ], true); }); const serializedCorsOptions = corsOptions && { allowHeaders: corsOptions.allowHeaders || [ ...aws_apigateway_1.Cors.DEFAULT_HEADERS, "x-amz-content-sha256", ], allowMethods: corsOptions.allowMethods || aws_apigateway_1.Cors.ALL_METHODS, allowOrigins: corsOptions.allowOrigins, statusCode: corsOptions.statusCode || 204, }; const prepareSpecOptions = { defaultAuthorizerReference: (0, api_gateway_auth_1.serializeAsAuthorizerReference)(defaultAuthorizer), integrations: Object.fromEntries(Object.entries(integrations).map(([operationId, integration]) => [ operationId, { integration: integration.integration.render({ operationId, scope: this, ...operationLookup[operationId], corsOptions: serializedCorsOptions, operationLookup, }), methodAuthorizer: (0, api_gateway_auth_1.serializeAsAuthorizerReference)(integration.authorizer), options: integration.options, }, ])), securitySchemes: (0, api_gateway_auth_1.prepareSecuritySchemes)(this, integrations, defaultAuthorizer, options.apiKeyOptions), corsOptions: serializedCorsOptions, operationLookup, apiKeyOptions: options.apiKeyOptions, gatewayResponses: options.gatewayResponses, }; // Spec preparation will happen in a custom resource lambda so that references to lambda integrations etc can be // resolved. However, we also prepare inline to perform some additional validation at synth time. const spec = JSON.parse(fs.readFileSync(specPath, "utf-8")); this.extendedApiSpecification = (0, prepare_spec_1.prepareApiSpec)(spec, prepareSpecOptions); const prepareApiSpecCustomResourceProperties = { inputSpecLocation: { bucket: inputSpecAsset.bucket.bucketName, key: inputSpecAsset.s3ObjectKey, }, outputSpecLocation: { bucket: prepareSpecOutputBucket.bucketName, key: preparedSpecOutputKeyPrefix, }, ...prepareSpecOptions, }; const prepareSpecCustomResource = new aws_cdk_lib_1.CustomResource(this, "PrepareSpecCustomResource", { serviceToken: provider.serviceToken, properties: { options: prepareApiSpecCustomResourceProperties, }, }); // Create the api gateway resources from the spec, augmenting the spec with the properties specific to api gateway // such as integrations or auth types this.api = new aws_apigateway_1.SpecRestApi(this, id, { apiDefinition: this.node.tryGetContext("type-safe-api-local") ? aws_apigateway_1.ApiDefinition.fromInline(this.extendedApiSpecification) : aws_apigateway_1.ApiDefinition.fromBucket(prepareSpecOutputBucket, prepareSpecCustomResource.getAttString("outputSpecKey")), deployOptions: { accessLogDestination: new aws_apigateway_1.LogGroupLogDestination(new aws_logs_1.LogGroup(this, `AccessLogs`)), accessLogFormat: aws_apigateway_1.AccessLogFormat.clf(), loggingLevel: aws_apigateway_1.MethodLoggingLevel.INFO, }, ...options, }); this.api.node.addDependency(prepareSpecCustomResource); // While the api will be updated when the output path from the custom resource changes, CDK still needs to know when // to redeploy the api. This is achieved by including a hash of the spec in the logical id (internalised in the // addToLogicalId method since this is how changes of individual resources/methods etc trigger redeployments in CDK) this.api.latestDeployment?.addToLogicalId(this.extendedApiSpecification); // Grant API Gateway permission to invoke the integrations Object.keys(integrations).forEach((operationId) => { integrations[operationId].integration.grant({ operationId, scope: this, api: this.api, ...operationLookup[operationId], operationLookup, }); }); // Grant API Gateway permission to invoke each custom authorizer lambda (if any) (0, api_gateway_integrations_1.getAuthorizerFunctions)(props).forEach(({ label, function: lambda }) => { new aws_lambda_1.CfnPermission(this, `LambdaPermission-${label}`, { action: "lambda:InvokeFunction", principal: "apigateway.amazonaws.com", functionName: lambda.functionArn, sourceArn: stack.formatArn({ service: "execute-api", resource: this.api.restApiId, resourceName: "*/*", }), }); }); // Create and associate the web acl if not disabled if (!props.webAclOptions?.disable) { const acl = new open_api_gateway_web_acl_1.OpenApiGatewayWebAcl(this, `${id}-Acl`, { ...props.webAclOptions, apiDeploymentStageArn: this.api.deploymentStage.stageArn, }); this.webAcl = acl.webAcl; this.ipSet = acl.ipSet; this.webAclAssociation = acl.webAclAssociation; } ["AwsSolutions-IAM4", "AwsPrototyping-IAMNoManagedPolicies"].forEach((RuleId) => { cdk_nag_1.NagSuppressions.addResourceSuppressions(this, [ { id: RuleId, reason: "Cloudwatch Role requires access to create/read groups at the root level.", appliesTo: [ { regex: `/^Policy::arn:${pdk_nag_1.PDKNag.getStackPartitionRegex(stack)}:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs$/g`, }, ], }, ], true); }); ["AwsSolutions-APIG2", "AwsPrototyping-APIGWRequestValidation"].forEach((RuleId) => { cdk_nag_1.NagSuppressions.addResourceSuppressions(this, [ { id: RuleId, reason: "This construct implements fine grained validation via OpenApi.", }, ], true); }); } } exports.TypeSafeRestApi = TypeSafeRestApi; _a = JSII_RTTI_SYMBOL_1; TypeSafeRestApi[_a] = { fqn: "@aws/pdk.type_safe_api.TypeSafeRestApi", version: "0.26.14" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZS1zYWZlLXJlc3QtYXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidHlwZS1zYWZlLXJlc3QtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUE7c0NBQ3NDO0FBQ3RDLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFDN0IsNENBQTBDO0FBQzFDLDBDQUFzQztBQUN0Qyw2Q0FBb0U7QUFDcEUsK0RBU29DO0FBQ3BDLGlEQU02QjtBQUM3Qix1REFLZ0M7QUFDaEMsbURBQWdEO0FBRWhELDZEQUFrRDtBQU1sRCxtRUFBd0Q7QUFDeEQscUNBQTBDO0FBQzFDLDJDQUF1QztBQUV2Qyw0RUFHbUQ7QUFFbkQsOERBR2lDO0FBQ2pDLDhFQUF5RTtBQUN6RSw2RUFBc0U7QUFpRHRFOztHQUVHO0FBQ0gsTUFBYSxlQUFnQixTQUFRLHNCQUFTO0lBc0I1QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTJCO1FBQ25FLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsSUFBQSxvQkFBUyxFQUFDLEtBQUssRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO1FBRXZDLE1BQU0sRUFDSixZQUFZLEVBQ1osUUFBUSxFQUNSLGVBQWUsRUFDZixpQkFBaUIsRUFDakIsV0FBVyxFQUNYLGdCQUFnQixFQUNoQixHQUFHLE9BQU8sRUFDWCxHQUFHLEtBQUssQ0FBQztRQUVWLG9DQUFvQztRQUNwQyxNQUFNLGNBQWMsR0FBRyxJQUFJLHFCQUFLLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRTtZQUNsRCxJQUFJLEVBQUUsUUFBUTtTQUNmLENBQUMsQ0FBQztRQUVILE1BQU0sdUJBQXVCLEdBQUcsZ0JBQWdCLElBQUksY0FBYyxDQUFDLE1BQU0sQ0FBQztRQUMxRSwwREFBMEQ7UUFDMUQsTUFBTSwyQkFBMkIsR0FBRyxHQUFHLGNBQWMsQ0FBQyxXQUFXLFdBQVcsQ0FBQztRQUU3RSxNQUFNLEtBQUssR0FBRyxtQkFBSyxDQUFDLEVBQUUs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LENBQUMsTUFBTSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQztZQUN2QixJQUFJLENBQUMsaUJBQWlCLEdBQUcsR0FBRyxDQUFDLGlCQUFpQixDQUFDO1FBQ2pELENBQUM7UUFFRCxDQUFDLG1CQUFtQixFQUFFLHFDQUFxQyxDQUFDLENBQUMsT0FBTyxDQUNsRSxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ1QseUJBQWUsQ0FBQyx1QkFBdUIsQ0FDckMsSUFBSSxFQUNKO2dCQUNFO29CQUNFLEVBQUUsRUFBRSxNQUFNO29CQUNWLE1BQU0sRUFDSiwwRUFBMEU7b0JBQzVFLFNBQVMsRUFBRTt3QkFDVDs0QkFDRSxLQUFLLEVBQUUsaUJBQWlCLGdCQUFNLENBQUMsc0JBQXNCLENBQ25ELEtBQUssQ0FDTix1RUFBdUU7eUJBQ3pFO3FCQUNGO2lCQUNGO2FBQ0YsRUFDRCxJQUFJLENBQ0wsQ0FBQztRQUNKLENBQUMsQ0FDRixDQUFDO1FBRUYsQ0FBQyxvQkFBb0IsRUFBRSx1Q0FBdUMsQ0FBQyxDQUFDLE9BQU8sQ0FDckUsQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUNULHlCQUFlLENBQUMsdUJBQXVCLENBQ3JDLElBQUksRUFDSjtnQkFDRTtvQkFDRSxFQUFFLEVBQUUsTUFBTTtvQkFDVixNQUFNLEVBQ0osZ0VBQWdFO2lCQUNuRTthQUNGLEVBQ0QsSUFBSSxDQUNMLENBQUM7UUFDSixDQUFDLENBQ0YsQ0FBQztJQUNKLENBQUM7O0FBOVhILDBDQStYQyIsInNvdXJjZXNDb250ZW50IjpbIi8qISBDb3B5cmlnaHQgW0FtYXpvbi5jb21dKGh0dHA6Ly9hbWF6b24uY29tLyksIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMCAqL1xuaW1wb3J0ICogYXMgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBhZGRNZXRyaWMgfSBmcm9tIFwiQGF3cy9tb25vcmVwb1wiO1xuaW1wb3J0IHsgUERLTmFnIH0gZnJvbSBcIkBhd3MvcGRrLW5hZ1wiO1xuaW1wb3J0IHsgQ3VzdG9tUmVzb3VyY2UsIER1cmF0aW9uLCBTaXplLCBTdGFjayB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHtcbiAgQWNjZXNzTG9nRm9ybWF0LFxuICBBcGlEZWZpbml0aW9uLFxuICBDb3JzLFxuICBHYXRld2F5UmVzcG9uc2VPcHRpb25zLFxuICBMb2dHcm91cExvZ0Rlc3RpbmF0aW9uLFxuICBNZXRob2RMb2dnaW5nTGV2ZWwsXG4gIFJlc3RBcGlCYXNlUHJvcHMsXG4gIFNwZWNSZXN0QXBpLFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWFwaWdhdGV3YXlcIjtcbmltcG9ydCB7XG4gIEVmZmVjdCxcbiAgUG9saWN5RG9jdW1lbnQsXG4gIFBvbGljeVN0YXRlbWVudCxcbiAgUm9sZSxcbiAgU2VydmljZVByaW5jaXBhbCxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1pYW1cIjtcbmltcG9ydCB7XG4gIENmblBlcm1pc3Npb24sXG4gIENvZGUsXG4gIEZ1bmN0aW9uIGFzIExhbWJkYUZ1bmN0aW9uLFxuICBSdW50aW1lLFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxhbWJkYVwiO1xuaW1wb3J0IHsgTG9nR3JvdXAgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxvZ3NcIjtcbmltcG9ydCB7IElCdWNrZXQgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXMzXCI7XG5pbXBvcnQgeyBBc3NldCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtczMtYXNzZXRzXCI7XG5pbXBvcnQge1xuICBDZm5JUFNldCxcbiAgQ2ZuV2ViQUNMLFxuICBDZm5XZWJBQ0xBc3NvY2lhdGlvbixcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy13YWZ2MlwiO1xuaW1wb3J0IHsgUHJvdmlkZXIgfSBmcm9tIFwiYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlc1wiO1xuaW1wb3J0IHsgTmFnU3VwcHJlc3Npb25zIH0gZnJvbSBcImNkay1uYWdcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBQcmVwYXJlQXBpU3BlY0N1c3RvbVJlc291cmNlUHJvcGVydGllcyB9IGZyb20gXCIuL3ByZXBhcmUtc3BlYy1ldmVudC1oYW5kbGVyXCI7XG5pbXBvcnQge1xuICBwcmVwYXJlQXBpU3BlYyxcbiAgUHJlcGFyZUFwaVNwZWNPcHRpb25zLFxufSBmcm9tIFwiLi9wcmVwYXJlLXNwZWMtZXZlbnQtaGFuZGxlci9wcmVwYXJlLXNwZWNcIjtcbmltcG9ydCB7IFNlcmlhbGl6ZWRDb3JzT3B0aW9ucywgVHlwZVNhZmVBcGlPcHRpb25zIH0gZnJvbSBcIi4vc3BlY1wiO1xuaW1wb3J0IHtcbiAgcHJlcGFyZVNlY3VyaXR5U2NoZW1lcyxcbiAgc2VyaWFsaXplQXNBdXRob3JpemVyUmVmZXJlbmNlLFxufSBmcm9tIFwiLi9zcGVjL2FwaS1nYXRld2F5LWF1dGhcIjtcbmltcG9ydCB7IGdldEF1dGhvcml6ZXJGdW5jdGlvbnMgfSBmcm9tIFwiLi9zcGVjL2FwaS1nYXRld2F5LWludGVncmF0aW9uc1wiO1xuaW1wb3J0IHsgT3BlbkFwaUdhdGV3YXlXZWJBY2wgfSBmcm9tIFwiLi93YWYvb3Blbi1hcGktZ2F0ZXdheS13ZWItYWNsXCI7XG5pbXBvcnQgeyBUeXBlU2FmZUFwaVdlYkFjbE9wdGlvbnMgfSBmcm9tIFwiLi93YWYvdHlwZXNcIjtcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciB0aGUgVHlwZVNhZmVSZXN0QXBpIGNvbnN0cnVjdFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFR5cGVTYWZlUmVzdEFwaVByb3BzXG4gIGV4dGVuZHMgUmVzdEFwaUJhc2VQcm9wcyxcbiAgICBUeXBlU2FmZUFwaU9wdGlvbnMge1xuICAvKipcbiAgICogUGF0aCB0byB0aGUgSlNPTiBvcGVuIGFwaSBzcGVjXG4gICAqL1xuICByZWFkb25seSBzcGVjUGF0aDogc3RyaW5nO1xuICAvKipcbiAgICogT3B0aW9ucyBmb3IgdGhlIEFXUyBXQUYgdjIgV2ViQUNMIGFzc29jaWF0ZWQgd2l0aCB0aGUgYXBpLiBCeSBkZWZhdWx0LCBhIFdlYiBBQ0wgd2l0aCB0aGUgQVdTIGRlZmF1bHQgbWFuYWdlZFxuICAgKiBydWxlIHNldCB3aWxsIGJlIGFzc29jaWF0ZWQgd2l0aCB0aGUgQVBJLiBUaGVzZSBvcHRpb25zIG1heSBkaXNhYmxlIG9yIG92ZXJyaWRlIHRoZSBkZWZhdWx0cy5cbiAgICovXG4gIHJlYWRvbmx5IHdlYkFjbE9wdGlvbnM/OiBUeXBlU2FmZUFwaVdlYkFjbE9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIEEgU2l6ZShpbiBieXRlcywga2liaWJ5dGVzLCBtZWJpYnl0ZXMgZXRjKSB0aGF0IGlzIHVzZWQgdG8gZW5hYmxlIGNvbXByZXNzaW9uICh3aXRoIG5vbi1uZWdhdGl2ZVxuICAgKiBiZXR3ZWVuIDAgYW5kIDEwNDg1NzYwICgxME0pIGJ5dGVzLCBpbmNsdXNpdmUpIG9yIGRpc2FibGUgY29tcHJlc3Npb25cbiAgICogKHdoZW4gdW5kZWZpbmVkKSBvbiBhbiBBUEkuIFdoZW4gY29tcHJlc3Npb24gaXMgZW5hYmxlZCwgY29tcHJlc3Npb24gb3JcbiAgICogZGVjb21wcmVzc2lvbiBpcyBub3QgYXBwbGllZCBvbiB0aGUgcGF5bG9hZCBpZiB0aGUgcGF5bG9hZCBzaXplIGlzXG4gICAqIHNtYWxsZXIgdGhhbiB0aGlzIHZhbHVlLiBTZXR0aW5nIGl0IHRvIHplcm8gYWxsb3dzIGNvbXByZXNzaW9uIGZvciBhbnlcbiAgICogcGF5bG9hZCBzaXplLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIENvbXByZXNzaW9uIGlzIGRpc2FibGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgbWluQ29tcHJlc3Npb25TaXplPzogU2l6ZTtcblxuICAvKipcbiAgICogQnkgZGVmYXVsdCwgdGhlIHNwZWMgaXMgcHJlcGFyZWQgYW5kIG91dHB1dHRlZCBpbnRvIHRoZSBDREsgYXNzZXRzIGJ1Y2tldC4gSWYgdGhpcyBpcyB1bmRlc2lyZWQsXG4gICAqIHVzZSB0aGlzIG9wdGlvbiB0byBzcGVjaWZ5IHRoZSBvdXRwdXQgYnVja2V0LlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0U3BlY0J1Y2tldD86IElCdWNrZXQ7XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIGdhdGV3YXkgcmVzcG9uc2VzIGZvciB0aGUgQVBJLlxuICAgKlxuICAgKiBOb3RlIHRoYXQgVHlwZSBTYWZlIEFQSSBhdXRvbWF0aWNhbGx5IGNvbmZpZ3VyZXMgcmVxdWVzdCB2YWxpZGF0aW9uIGZvciB5b3UsIGFuZCBkZWZpbmVzIGFcbiAgICogZGVmYXVsdCBCQURfUkVRVUVTVF9CT0RZIGdhdGV3YXkgcmVzcG9uc2Ugd2hpY2ggcmV0dXJucyB0aGUgdmFsaWRhdGlvbiBlcnJvciBtZXNzYWdlLiBZb3UgY2FuXG4gICAqIHVzZSB0aGlzIHByb3BlcnR5IHRvIG92ZXJyaWRlIHRoaXMgZ2F0ZXdheSByZXNwb25zZSBpZiBkZXNpcmVkLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcGlnYXRld2F5L2xhdGVzdC9kZXZlbG9wZXJndWlkZS9hcGktZ2F0ZXdheS1nYXRld2F5UmVzcG9uc2UtZGVmaW5pdGlvbi5odG1sXG4gICAqL1xuICByZWFkb25seSBnYXRld2F5UmVzcG9uc2VzPzogR2F0ZXdheVJlc3BvbnNlT3B0aW9uc1tdO1xufVxuXG4vKipcbiAqIEEgY29uc3RydWN0IGZvciBjcmVhdGluZyBhbiBhcGkgZ2F0ZXdheSByZXN0IGFwaSBiYXNlZCBvbiB0aGUgZGVmaW5pdGlvbiBpbiB0aGUgT3BlbkFQSSBzcGVjLlxuICovXG5leHBvcnQgY2xhc3MgVHlwZVNhZmVSZXN0QXBpIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgLyoqXG4gICAqIFVuZGVybHlpbmcgQVBJIEdhdGV3YXkgQVBJIGNvbnN0cnVjdFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGFwaTogU3BlY1Jlc3RBcGk7XG4gIC8qKlxuICAgKiBUaGUgT3BlbkFQSSBzcGVjaWZpY2F0aW9uIHdpdGggYXBwbGllZCBBUEkgZ2F0ZXdheSBleHRlbnNpb25zXG4gICAqL1xuICByZWFkb25seSBleHRlbmRlZEFwaVNwZWNpZmljYXRpb246IGFueTtcbiAgLyoqXG4gICAqIFJlZmVyZW5jZSB0byB0aGUgd2ViYWNsLCBpZiBjcmVhdGVkXG4gICAqL1xuICByZWFkb25seSB3ZWJBY2w/OiBDZm5XZWJBQ0w7XG4gIC8qKlxuICAgKiBSZWZlcmVuY2UgdG8gdGhlIElQIHNldCBpZiBjcmVhdGVkXG4gICAqL1xuICByZWFkb25seSBpcFNldD86IENmbklQU2V0O1xuICAvKipcbiAgICogUmVmZXJlbmNlIHRvIHRoZSB3ZWIgYWNsIGFzc29jaWF0aW9uIGlmIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IHdlYkFjbEFzc29jaWF0aW9uPzogQ2ZuV2ViQUNMQXNzb2NpYXRpb247XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFR5cGVTYWZlUmVzdEFwaVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGFkZE1ldHJpYyhzY29wZSwgXCJ0eXBlLXNhZmUtcmVzdC1hcGlcIik7XG5cbiAgICBjb25zdCB7XG4gICAgICBpbnRlZ3JhdGlvbnMsXG4gICAgICBzcGVjUGF0aCxcbiAgICAgIG9wZXJhdGlvbkxvb2t1cCxcbiAgICAgIGRlZmF1bHRBdXRob3JpemVyLFxuICAgICAgY29yc09wdGlvbnMsXG4gICAgICBvdXRwdXRTcGVjQnVja2V0LFxuICAgICAgLi4ub3B0aW9uc1xuICAgIH0gPSBwcm9wcztcblxuICAgIC8vIFVwbG9hZCB0aGUgc3BlYyB0byBzMyBhcyBhbiBhc3NldFxuICAgIGNvbnN0IGlucHV0U3BlY0Fzc2V0ID0gbmV3IEFzc2V0KHRoaXMsIFwiSW5wdXRTcGVjXCIsIHtcbiAgICAgIHBhdGg6IHNwZWNQYXRoLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcHJlcGFyZVNwZWNPdXRwdXRCdWNrZXQgPSBvdXRwdXRTcGVjQnVja2V0ID8/IGlucHV0U3BlY0Fzc2V0LmJ1Y2tldDtcbiAgICAvLyBXZSdsbCBvdXRwdXQgdGhlIHByZXBhcmVkIHNwZWMgaW4gdGhlIHNhbWUgYXNzZXQgYnVja2V0XG4gICAgY29uc3QgcHJlcGFyZWRTcGVjT3V0cHV0S2V5UHJlZml4ID0gYCR7aW5wdXRTcGVjQXNzZXQuczNPYmplY3RLZXl9LXByZXBhcmVkYDtcblxuICAgIGNvbnN0IHN0YWNrID0gU3RhY2sub2YodGhpcyk7XG5cbiAgICAvLyBMYW1iZGEgbmFtZSBwcmVmaXggaXMgdHJ1bmNhdGVkIHRvIDQ4IGNoYXJhY3RlcnMgKDE2IGJlbG93IHRoZSBtYXggb2YgNjQpXG4gICAgY29uc3QgbGFtYmRhTmFtZVByZWZpeCA9IGAke1BES05hZy5nZXRTdGFja1ByZWZpeChzdGFjaylcbiAgICAgIC5zcGxpdChcIi9cIilcbiAgICAgIC5qb2luKFwiLVwiKVxuICAgICAgLnNsaWNlKDAsIDQwKX0ke3RoaXMubm9kZS5hZGRyLnNsaWNlKC04KS50b1VwcGVyQ2FzZSgpfWA7XG4gICAgY29uc3QgcHJlcGFyZVNwZWNMYW1iZGFOYW1lID0gYCR7bGFtYmRhTmFtZVByZWZpeH1QcmVwU3BlY2A7XG4gICAgY29uc3QgcHJlcGFyZVNwZWNSb2xlID0gbmV3IFJvbGUodGhpcywgXCJQcmVwYXJlU3BlY1JvbGVcIiwge1xuICAgICAgYXNzdW1lZEJ5OiBuZXcgU2VydmljZVByaW5jaXBhbChcImxhbWJkYS5hbWF6b25hd3MuY29tXCIpLFxuICAgICAgaW5saW5lUG9saWNpZXM6IHtcbiAgICAgICAgbG9nczogbmV3IFBvbGljeURvY3VtZW50KHtcbiAgICAgICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgICAgICBcImxvZ3M6Q3JlYXRlTG9nR3JvdXBcIixcbiAgICAgICAgICAgICAgICBcImxvZ3M6Q3JlYXRlTG9nU3RyZWFtXCIsXG4gICAgICAgICAgICAgICAgXCJsb2dzOlB1dExvZ0V2ZW50c1wiLFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICAgICAgICBgYXJuOmF3czpsb2dzOiR7c3RhY2sucmVnaW9ufToke3N0YWNrLmFjY291bnR9OmxvZy1ncm91cDovYXdzL2xhbWJkYS8ke3ByZXBhcmVTcGVjTGFtYmRhTmFtZX1gLFxuICAgICAgICAgICAgICAgIGBhcm46YXdzOmxvZ3M6JHtzdGFjay5yZWdpb259OiR7c3RhY2suYWNjb3VudH06bG9nLWdyb3VwOi9hd3MvbGFtYmRhLyR7cHJlcGFyZVNwZWNMYW1iZGFOYW1lfToqYCxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pLFxuICAgICAgICBzMzogbmV3IFBvbGljeURvY3VtZW50KHtcbiAgICAgICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICAgICAgICAgIGFjdGlvbnM6IFtcInMzOmdldE9iamVjdFwiXSxcbiAgICAgICAgICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgICAgICAgICAgaW5wdXRTcGVjQXNzZXQuYnVja2V0LmFybkZvck9iamVjdHMoaW5wdXRTcGVjQXNzZXQuczNPYmplY3RLZXkpLFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICAgICAgICAgIGFjdGlvbnM6IFtcInMzOnB1dE9iamVjdFwiXSxcbiAgICAgICAgICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgICAgICAgICAgLy8gVGhlIG91dHB1dCBmaWxlIHdpbGwgaW5jbHVkZSBhIGhhc2ggb2YgdGhlIHByZXBhcmVkIHNwZWMsIHdoaWNoIGlzIG5vdCBrbm93biB1bnRpbCBkZXBsb3kgdGltZSBzaW5jZVxuICAgICAgICAgICAgICAgIC8vIHRva2VucyBtdXN0IGJlIHJlc29sdmVkXG4gICAgICAgICAgICAgICAgcHJlcGFyZVNwZWNPdXRwdXRCdWNrZXQuYXJuRm9yT2JqZWN0cyhcbiAgICAgICAgICAgICAgICAgIGAke3ByZXBhcmVkU3BlY091dHB1dEtleVByZWZpeH0vKmBcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgXSxcbiAgICAgICAgfSksXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgW1wiQXdzU29sdXRpb25zLUlBTTVcIiwgXCJBd3NQcm90b3R5cGluZy1JQU1Ob1dpbGRjYXJkUGVybWlzc2lvbnNcIl0uZm9yRWFjaChcbiAgICAgIChSdWxlSWQpID0+IHtcbiAgICAgICAgTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zKFxuICAgICAgICAgIHByZXBhcmVTcGVjUm9sZSxcbiAgICAgICAgICBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiBSdWxlSWQsXG4gICAgICAgICAgICAgIHJlYXNvbjpcbiAgICAgICAgICAgICAgICBcIkNsb3Vkd2F0Y2ggcmVzb3VyY2VzIGhhdmUgYmVlbiBzY29wZWQgZG93biB0byB0aGUgTG9nR3JvdXAgbGV2ZWwsIGhvd2V2ZXIgKiBpcyBzdGlsbCBuZWVkZWQgYXMgc3RyZWFtIG5hbWVzIGFyZSBjcmVhdGVkIGp1c3QgaW4gdGltZS5cIixcbiAgICAgICAgICAgICAgYXBwbGllc1RvOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcmVnZXg6IGAvXlJlc291cmNlOjphcm46YXdzOmxvZ3M6JHtQREtOYWcuZ2V0U3RhY2tSZWdpb25SZWdleChcbiAgICAgICAgICAgICAgICAgICAgc3RhY2tcbiAgICAgICAgICAgICAgICAgICl9OiR7UERLTmFnLmdldFN0YWNrQWNjb3VudFJlZ2V4KFxuICAgICAgICAgICAgICAgICAgICBzdGFja1xuICAgICAgICAgICAgICAgICAgKX06bG9nLWdyb3VwOi9hd3MvbGFtYmRhLyR7cHJlcGFyZVNwZWNMYW1iZGFOYW1lfTpcXCovZ2AsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiBSdWxlSWQsXG4gICAgICAgICAgICAgIHJlYXNvbjpcbiAgICAgICAgICAgICAgICBcIlMzIHJlc291cmNlcyBoYXZlIGJlZW4gc2NvcGVkIGRvd24gdG8gdGhlIGFwcHJvcHJpYXRlIHByZWZpeCBpbiB0aGUgQ0RLIGFzc2V0IGJ1Y2tldCwgaG93ZXZlciAqIGlzIHN0aWxsIG5lZWRlZCBhcyBzaW5jZSB0aGUgcHJlcGFyZWQgc3BlYyBoYXNoIGlzIG5vdCBrbm93biB1bnRpbCBkZXBsb3kgdGltZS5cIixcbiAgICAgICAgICAgICAgYXBwbGllc1RvOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcmVnZXg6IGAvXlJlc291cmNlOjphcm46JHtQREtOYWcuZ2V0U3RhY2tQYXJ0aXRpb25SZWdleChcbiAgICAgICAgICAgICAgICAgICAgc3RhY2tcbiAgICAgICAgICAgICAgICAgICl9OnMzOi4qLyR7cHJlcGFyZWRTcGVjT3V0cHV0S2V5UHJlZml4fS9cXCovZ2AsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICB0cnVlXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgKTtcblxuICAgIC8vIENyZWF0ZSBhIGN1c3RvbSByZXNvdXJjZSBmb3IgcHJlcGFyaW5nIHRoZSBzcGVjIGZvciBkZXBsb3ltZW50IChhZGRpbmcgaW50ZWdyYXRpb25zLCBhdXRob3JpemVycywgZXRjKVxuICAgIGNvbnN0IHByZXBhcmVTcGVjID0gbmV3IExhbWJkYUZ1bmN0aW9uKHRoaXMsIFwiUHJlcGFyZVNwZWNIYW5kbGVyXCIsIHtcbiAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgcnVudGltZTogUnVudGltZS5OT0RFSlNfMThfWCxcbiAgICAgIGNvZGU6IENvZGUuZnJvbUFzc2V0KFxuICAgICAgICBwYXRoLmpvaW4oX19kaXJuYW1lLCBcIi4vcHJlcGFyZS1zcGVjLWV2ZW50LWhhbmRsZXJcIilcbiAgICAgICksXG4gICAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKDMwKSxcbiAgICAgIHJvbGU6IHByZXBhcmVTcGVjUm9sZSxcbiAgICAgIGZ1bmN0aW9uTmFtZTogcHJlcGFyZVNwZWNMYW1iZGFOYW1lLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcHJvdmlkZXJGdW5jdGlvbk5hbWUgPSBgJHtsYW1iZGFOYW1lUHJlZml4fVByZXBTcGVjUHJvdmlkZXJgO1xuICAgIGNvbnN0IHByb3ZpZGVyUm9sZSA9IG5ldyBSb2xlKHRoaXMsIFwiUHJlcGFyZVNwZWNQcm92aWRlclJvbGVcIiwge1xuICAgICAgYXNzdW1lZEJ5OiBuZXcgU2VydmljZVByaW5jaXBhbChcImxhbWJkYS5hbWF6b25hd3MuY29tXCIpLFxuICAgICAgaW5saW5lUG9saWNpZXM6IHtcbiAgICAgICAgbG9nczogbmV3IFBvbGljeURvY3VtZW50KHtcbiAgICAgICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgICAgICBcImxvZ3M6Q3JlYXRlTG9nR3JvdXBcIixcbiAgICAgICAgICAgICAgICBcImxvZ3M6Q3JlYXRlTG9nU3RyZWFtXCIsXG4gICAgICAgICAgICAgICAgXCJsb2dzOlB1dExvZ0V2ZW50c1wiLFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICAgICAgICBgYXJuOmF3czpsb2dzOiR7c3RhY2sucmVnaW9ufToke3N0YWNrLmFjY291bnR9OmxvZy1ncm91cDovYXdzL2xhbWJkYS8ke3Byb3ZpZGVyRnVuY3Rpb25OYW1lfWAsXG4gICAgICAgICAgICAgICAgYGFybjphd3M6bG9nczoke3N0YWNrLnJlZ2lvbn06JHtzdGFjay5hY2NvdW50fTpsb2ctZ3JvdXA6L2F3cy9sYW1iZGEvJHtwcm92aWRlckZ1bmN0aW9uTmFtZX06KmAsXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICBdLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCBwcm92aWRlciA9IG5ldyBQcm92aWRlcih0aGlzLCBcIlByZXBhcmVTcGVjUHJvdmlkZXJcIiwge1xuICAgICAgb25FdmVudEhhbmRsZXI6IHByZXBhcmVTcGVjLFxuICAgICAgcm9sZTogcHJvdmlkZXJSb2xlLFxuICAgICAgcHJvdmlkZXJGdW5jdGlvbk5hbWUsXG4gICAgfSk7XG5cbiAgICBbXCJBd3NTb2x1dGlvbnMtSUFNNVwiLCBcIkF3c1Byb3RvdHlwaW5nLUlBTU5vV2lsZGNhcmRQZXJtaXNzaW9uc1wiXS5mb3JFYWNoKFxuICAgICAgKFJ1bGVJZCkgPT4ge1xuICAgICAgICBOYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnMoXG4gICAgICAgICAgcHJvdmlkZXJSb2xlLFxuICAgICAgICAgIFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgaWQ6IFJ1bGVJZCxcbiAgICAgICAgICAgICAgcmVhc29uOlxuICAgICAgICAgICAgICAgIFwiQ2xvdWR3YXRjaCByZXNvdXJjZXMgaGF2ZSBiZWVuIHNjb3BlZCBkb3duIHRvIHRoZSBMb2dHcm91cCBsZXZlbCwgaG93ZXZlciAqIGlzIHN0aWxsIG5lZWRlZCBhcyBzdHJlYW0gbmFtZXMgYXJlIGNyZWF0ZWQganVzdCBpbiB0aW1lLlwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgW1wiQXdzU29sdXRpb25zLUwxXCIsIFwiQXdzUHJvdG90eXBpbmctTGFtYmRhTGF0ZXN0VmVyc2lvblwiXS5mb3JFYWNoKFxuICAgICAgKFJ1bGVJZCkgPT4ge1xuICAgICAgICBOYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnMoXG4gICAgICAgICAgcHJvdmlkZXIsXG4gICAgICAgICAgW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBpZDogUnVsZUlkLFxuICAgICAgICAgICAgICByZWFzb246XG4gICAgICAgICAgICAgICAgXCJMYXRlc3QgcnVudGltZSBjYW5ub3QgYmUgY29uZmlndXJlZC4gQ0RLIHdpbGwgbmVlZCB0byB1cGdyYWRlIHRoZSBQcm92aWRlciBjb25zdHJ1Y3QgYWNjb3JkaW5nbHkuXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgdHJ1ZVxuICAgICAgICApO1xuICAgICAgfVxuICAgICk7XG5cbiAgICBjb25zdCBzZXJpYWxpemVkQ29yc09wdGlvbnM6IFNlcmlhbGl6ZWRDb3JzT3B0aW9ucyB8IHVuZGVmaW5lZCA9XG4gICAgICBjb3JzT3B0aW9ucyAmJiB7XG4gICAgICAgIGFsbG93SGVhZGVyczogY29yc09wdGlvbnMuYWxsb3dIZWFkZXJzIHx8IFtcbiAgICAgICAgICAuLi5Db3JzLkRFRkFVTFRfSEVBREVSUyxcbiAgICAgICAgICBcIngtYW16LWNvbnRlbnQtc2hhMjU2XCIsXG4gICAgICAgIF0sXG4gICAgICAgIGFsbG93TWV0aG9kczogY29yc09wdGlvbnMuYWxsb3dNZXRob2RzIHx8IENvcnMuQUxMX01FVEhPRFMsXG4gICAgICAgIGFsbG93T3JpZ2luczogY29yc09wdGlvbnMuYWxsb3dPcmlnaW5zLFxuICAgICAgICBzdGF0dXNDb2RlOiBjb3JzT3B0aW9ucy5zdGF0dXNDb2RlIHx8IDIwNCxcbiAgICAgIH07XG5cbiAgICBjb25zdCBwcmVwYXJlU3BlY09wdGlvbnM6IFByZXBhcmVBcGlTcGVjT3B0aW9ucyA9IHtcbiAgICAgIGRlZmF1bHRBdXRob3JpemVyUmVmZXJlbmNlOlxuICAgICAgICBzZXJpYWxpemVBc0F1dGhvcml6ZXJSZWZlcmVuY2UoZGVmYXVsdEF1dGhvcml6ZXIpLFxuICAgICAgaW50ZWdyYXRpb25zOiBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICAgIE9iamVjdC5lbnRyaWVzKGludGVncmF0aW9ucykubWFwKChbb3BlcmF0aW9uSWQsIGludGVncmF0aW9uXSkgPT4gW1xuICAgICAgICAgIG9wZXJhdGlvbklkLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGludGVncmF0aW9uOiBpbnRlZ3JhdGlvbi5pbnRlZ3JhdGlvbi5yZW5kZXIoe1xuICAgICAgICAgICAgICBvcGVyYXRpb25JZCxcbiAgICAgICAgICAgICAgc2NvcGU6IHRoaXMsXG4gICAgICAgICAgICAgIC4uLm9wZXJhdGlvbkxvb2t1cFtvcGVyYXRpb25JZF0sXG4gICAgICAgICAgICAgIGNvcnNPcHRpb25zOiBzZXJpYWxpemVkQ29yc09wdGlvbnMsXG4gICAgICAgICAgICAgIG9wZXJhdGlvbkxvb2t1cCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgbWV0aG9kQXV0aG9yaXplcjogc2VyaWFsaXplQXNBdXRob3JpemVyUmVmZXJlbmNlKFxuICAgICAgICAgICAgICBpbnRlZ3JhdGlvbi5hdXRob3JpemVyXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgb3B0aW9uczogaW50ZWdyYXRpb24ub3B0aW9ucyxcbiAgICAgICAgICB9LFxuICAgICAgICBdKVxuICAgICAgKSxcbiAgICAgIHNlY3VyaXR5U2NoZW1lczogcHJlcGFyZVNlY3VyaXR5U2NoZW1lcyhcbiAgICAgICAgdGhpcyxcbiAgICAgICAgaW50ZWdyYXRpb25zLFxuICAgICAgICBkZWZhdWx0QXV0aG9yaXplcixcbiAgICAgICAgb3B0aW9ucy5hcGlLZXlPcHRpb25zXG4gICAgICApLFxuICAgICAgY29yc09wdGlvbnM6IHNlcmlhbGl6ZWRDb3JzT3B0aW9ucyxcbiAgICAgIG9wZXJhdGlvbkxvb2t1cCxcbiAgICAgIGFwaUtleU9wdGlvbnM6IG9wdGlvbnMuYXBpS2V5T3B0aW9ucyxcbiAgICAgIGdhdGV3YXlSZXNwb25zZXM6IG9wdGlvbnMuZ2F0ZXdheVJlc3BvbnNlcyxcbiAgICB9O1xuXG4gICAgLy8gU3BlYyBwcmVwYXJhdGlvbiB3aWxsIGhhcHBlbiBpbiBhIGN1c3RvbSByZXNvdXJjZSBsYW1iZGEgc28gdGhhdCByZWZlcmVuY2VzIHRvIGxhbWJkYSBpbnRlZ3JhdGlvbnMgZXRjIGNhbiBiZVxuICAgIC8vIHJlc29sdmVkLiBIb3dldmVyLCB3ZSBhbHNvIHByZXBhcmUgaW5saW5lIHRvIHBlcmZvcm0gc29tZSBhZGRpdGlvbmFsIHZhbGlkYXRpb24gYXQgc3ludGggdGltZS5cbiAgICBjb25zdCBzcGVjID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMoc3BlY1BhdGgsIFwidXRmLThcIikpO1xuICAgIHRoaXMuZXh0ZW5kZWRBcGlTcGVjaWZpY2F0aW9uID0gcHJlcGFyZUFwaVNwZWMoc3BlYywgcHJlcGFyZVNwZWNPcHRpb25zKTtcblxuICAgIGNvbnN0IHByZXBhcmVBcGlTcGVjQ3VzdG9tUmVzb3VyY2VQcm9wZXJ0aWVzOiBQcmVwYXJlQXBpU3BlY0N1c3RvbVJlc291cmNlUHJvcGVydGllcyA9XG4gICAgICB7XG4gICAgICAgIGlucHV0U3BlY0xvY2F0aW9uOiB7XG4gICAgICAgICAgYnVja2V0OiBpbnB1dFNwZWNBc3NldC5idWNrZXQuYnVja2V0TmFtZSxcbiAgICAgICAgICBrZXk6IGlucHV0U3BlY0Fzc2V0LnMzT2JqZWN0S2V5LFxuICAgICAgICB9LFxuICAgICAgICBvdXRwdXRTcGVjTG9jYXRpb246IHtcbiAgICAgICAgICBidWNrZXQ6IHByZXBhcmVTcGVjT3V0cHV0QnVja2V0LmJ1Y2tldE5hbWUsXG4gICAgICAgICAga2V5OiBwcmVwYXJlZFNwZWNPdXRwdXRLZXlQcmVmaXgsXG4gICAgICAgIH0sXG4gICAgICAgIC4uLnByZXBhcmVTcGVjT3B0aW9ucyxcbiAgICAgIH07XG5cbiAgICBjb25zdCBwcmVwYXJlU3BlY0N1c3RvbVJlc291cmNlID0gbmV3IEN1c3RvbVJlc291cmNlKFxuICAgICAgdGhpcyxcbiAgICAgIFwiUHJlcGFyZVNwZWNDdXN0b21SZXNvdXJjZVwiLFxuICAgICAge1xuICAgICAgICBzZXJ2aWNlVG9rZW46IHByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgIG9wdGlvbnM6IHByZXBhcmVBcGlTcGVjQ3VzdG9tUmVzb3VyY2VQcm9wZXJ0aWVzLFxuICAgICAgICB9LFxuICAgICAgfVxuICAgICk7XG5cbiAgICAvLyBDcmVhdGUgdGhlIGFwaSBnYXRld2F5IHJlc291cmNlcyBmcm9tIHRoZSBzcGVjLCBhdWdtZW50aW5nIHRoZSBzcGVjIHdpdGggdGhlIHByb3BlcnRpZXMgc3BlY2lmaWMgdG8gYXBpIGdhdGV3YXlcbiAgICAvLyBzdWNoIGFzIGludGVncmF0aW9ucyBvciBhdXRoIHR5cGVzXG4gICAgdGhpcy5hcGkgPSBuZXcgU3BlY1Jlc3RBcGkodGhpcywgaWQsIHtcbiAgICAgIGFwaURlZmluaXRpb246IHRoaXMubm9kZS50cnlHZXRDb250ZXh0KFwidHlwZS1zYWZlLWFwaS1sb2NhbFwiKVxuICAgICAgICA/IEFwaURlZmluaXRpb24uZnJvbUlubGluZSh0aGlzLmV4dGVuZGVkQXBpU3BlY2lmaWNhdGlvbilcbiAgICAgICAgOiBBcGlEZWZpbml0aW9uLmZyb21CdWNrZXQoXG4gICAgICAgICAgICBwcmVwYXJlU3BlY091dHB1dEJ1Y2tldCxcbiAgICAgICAgICAgIHByZXBhcmVTcGVjQ3VzdG9tUmVzb3VyY2UuZ2V0QXR0U3RyaW5nKFwib3V0cHV0U3BlY0tleVwiKVxuICAgICAgICAgICksXG4gICAgICBkZXBsb3lPcHRpb25zOiB7XG4gICAgICAgIGFjY2Vzc0xvZ0Rlc3RpbmF0aW9uOiBuZXcgTG9nR3JvdXBMb2dEZXN0aW5hdGlvbihcbiAgICAgICAgICBuZXcgTG9nR3JvdXAodGhpcywgYEFjY2Vzc0xvZ3NgKVxuICAgICAgICApLFxuICAgICAgICBhY2Nlc3NMb2dGb3JtYXQ6IEFjY2Vzc0xvZ0Zvcm1hdC5jbGYoKSxcbiAgICAgICAgbG9nZ2luZ0xldmVsOiBNZXRob2RMb2dnaW5nTGV2ZWwuSU5GTyxcbiAgICAgIH0sXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hcGkubm9kZS5hZGREZXBlbmRlbmN5KHByZXBhcmVTcGVjQ3VzdG9tUmVzb3VyY2UpO1xuXG4gICAgLy8gV2hpbGUgdGhlIGFwaSB3aWxsIGJlIHVwZGF0ZWQgd2hlbiB0aGUgb3V0cHV0IHBhdGggZnJvbSB0aGUgY3VzdG9tIHJlc291cmNlIGNoYW5nZXMsIENESyBzdGlsbCBuZWVkcyB0byBrbm93IHdoZW5cbiAgICAvLyB0byByZWRlcGxveSB0aGUgYXBpLiBUaGlzIGlzIGFjaGlldmVkIGJ5IGluY2x1ZGluZyBhIGhhc2ggb2YgdGhlIHNwZWMgaW4gdGhlIGxvZ2ljYWwgaWQgKGludGVybmFsaXNlZCBpbiB0aGVcbiAgICAvLyBhZGRUb0xvZ2ljYWxJZCBtZXRob2Qgc2luY2UgdGhpcyBpcyBob3cgY2hhbmdlcyBvZiBpbmRpdmlkdWFsIHJlc291cmNlcy9tZXRob2RzIGV0YyB0cmlnZ2VyIHJlZGVwbG95bWVudHMgaW4gQ0RLKVxuICAgIHRoaXMuYXBpLmxhdGVzdERlcGxveW1lbnQ/LmFkZFRvTG9naWNhbElkKHRoaXMuZXh0ZW5kZWRBcGlTcGVjaWZpY2F0aW9uKTtcblxuICAgIC8vIEdyYW50IEFQSSBHYXRld2F5IHBlcm1pc3Npb24gdG8gaW52b2tlIHRoZSBpbnRlZ3JhdGlvbnNcbiAgICBPYmplY3Qua2V5cyhpbnRlZ3JhdGlvbnMpLmZvckVhY2goKG9wZXJhdGlvbklkKSA9PiB7XG4gICAgICBpbnRlZ3JhdGlvbnNbb3BlcmF0aW9uSWRdLmludGVncmF0aW9uLmdyYW50KHtcbiAgICAgICAgb3BlcmF0aW9uSWQsXG4gICAgICAgIHNjb3BlOiB0aGlzLFxuICAgICAgICBhcGk6IHRoaXMuYXBpLFxuICAgICAgICAuLi5vcGVyYXRpb25Mb29rdXBbb3BlcmF0aW9uSWRdLFxuICAgICAgICBvcGVyYXRpb25Mb29rdXAsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIEdyYW50IEFQSSBHYXRld2F5IHBlcm1pc3Npb24gdG8gaW52b2tlIGVhY2ggY3VzdG9tIGF1dGhvcml6ZXIgbGFtYmRhIChpZiBhbnkpXG4gICAgZ2V0QXV0aG9yaXplckZ1bmN0aW9ucyhwcm9wcykuZm9yRWFjaCgoeyBsYWJlbCwgZnVuY3Rpb246IGxhbWJkYSB9KSA9PiB7XG4gICAgICBuZXcgQ2ZuUGVybWlzc2lvbih0aGlzLCBgTGFtYmRhUGVybWlzc2lvbi0ke2xhYmVsfWAsIHtcbiAgICAgICAgYWN0aW9uOiBcImxhbWJkYTpJbnZva2VGdW5jdGlvblwiLFxuICAgICAgICBwcmluY2lwYWw6IFwiYXBpZ2F0ZXdheS5hbWF6b25hd3MuY29tXCIsXG4gICAgICAgIGZ1bmN0aW9uTmFtZTogbGFtYmRhLmZ1bmN0aW9uQXJuLFxuICAgICAgICBzb3VyY2VBcm46IHN0YWNrLmZvcm1hdEFybih7XG4gICAgICAgICAgc2VydmljZTogXCJleGVjdXRlLWFwaVwiLFxuICAgICAgICAgIHJlc291cmNlOiB0aGlzLmFwaS5yZXN0QXBpSWQsXG4gICAgICAgICAgcmVzb3VyY2VOYW1lOiBcIiovKlwiLFxuICAgICAgICB9KSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gQ3JlYXRlIGFuZCBhc3NvY2lhdGUgdGhlIHdlYiBhY2wgaWYgbm90IGRpc2FibGVkXG4gICAgaWYgKCFwcm9wcy53ZWJBY2xPcHRpb25zPy5kaXNhYmxlKSB7XG4gICAgICBjb25zdCBhY2wgPSBuZXcgT3BlbkFwaUdhdGV3YXlXZWJBY2wodGhpcywgYCR7aWR9LUFjbGAsIHtcbiAgICAgICAgLi4ucHJvcHMud2ViQWNsT3B0aW9ucyxcbiAgICAgICAgYXBpRGVwbG95bWVudFN0YWdlQXJuOiB0aGlzLmFwaS5kZXBsb3ltZW50U3RhZ2Uuc3RhZ2VBcm4sXG4gICAgICB9KTtcblxuICAgICAgdGhpcy53ZWJBY2wgPSBhY2wud2ViQWNsO1xuICAgICAgdGhpcy5pcFNldCA9IGFjbC5pcFNldDtcbiAgICAgIHRoaXMud2ViQWNsQXNzb2NpYXRpb24gPSBhY2wud2ViQWNsQXNzb2NpYXRpb247XG4gICAgfVxuXG4gICAgW1wiQXdzU29sdXRpb25zLUlBTTRcIiwgXCJBd3NQcm90b3R5cGluZy1JQU1Ob01hbmFnZWRQb2xpY2llc1wiXS5mb3JFYWNoKFxuICAgICAgKFJ1bGVJZCkgPT4ge1xuICAgICAgICBOYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnMoXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiBSdWxlSWQsXG4gICAgICAgICAgICAgIHJlYXNvbjpcbiAgICAgICAgICAgICAgICBcIkNsb3Vkd2F0Y2ggUm9sZSByZXF1aXJlcyBhY2Nlc3MgdG8gY3JlYXRlL3JlYWQgZ3JvdXBzIGF0IHRoZSByb290IGxldmVsLlwiLFxuICAgICAgICAgICAgICBhcHBsaWVzVG86IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICByZWdleDogYC9eUG9saWN5Ojphcm46JHtQREtOYWcuZ2V0U3RhY2tQYXJ0aXRpb25SZWdleChcbiAgICAgICAgICAgICAgICAgICAgc3RhY2tcbiAgICAgICAgICAgICAgICAgICl9OmlhbTo6YXdzOnBvbGljeS9zZXJ2aWNlLXJvbGUvQW1hem9uQVBJR2F0ZXdheVB1c2hUb0Nsb3VkV2F0Y2hMb2dzJC9nYCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgW1wiQXdzU29sdXRpb25zLUFQSUcyXCIsIFwiQXdzUHJvdG90eXBpbmctQVBJR1dSZXF1ZXN0VmFsaWRhdGlvblwiXS5mb3JFYWNoKFxuICAgICAgKFJ1bGVJZCkgPT4ge1xuICAgICAgICBOYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnMoXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiBSdWxlSWQsXG4gICAgICAgICAgICAgIHJlYXNvbjpcbiAgICAgICAgICAgICAgICBcIlRoaXMgY29uc3RydWN0IGltcGxlbWVudHMgZmluZSBncmFpbmVkIHZhbGlkYXRpb24gdmlhIE9wZW5BcGkuXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgdHJ1ZVxuICAgICAgICApO1xuICAgICAgfVxuICAgICk7XG4gIH1cbn1cbiJdfQ==