cdk-nag
Version:
Check CDK v2 applications for best practices using a combination on available rule packs.
228 lines • 34.4 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServerlessChecks = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
const aws_cdk_lib_1 = require("aws-cdk-lib");
const nag_pack_1 = require("../nag-pack");
const nag_rules_1 = require("../nag-rules");
const apigw_1 = require("../rules/apigw");
const appsync_1 = require("../rules/appsync");
const cloudwatch_1 = require("../rules/cloudwatch");
const eventbridge_1 = require("../rules/eventbridge");
const lambda_1 = require("../rules/lambda");
const sns_1 = require("../rules/sns");
const sqs_1 = require("../rules/sqs");
const stepfunctions_1 = require("../rules/stepfunctions");
/**
* Serverless Checks are a compilation of rules to validate infrastructure-as-code template against recommended practices.
*
*/
class ServerlessChecks extends nag_pack_1.NagPack {
constructor(props) {
super(props);
this.packName = 'Serverless';
}
visit(node) {
if (node instanceof aws_cdk_lib_1.CfnResource) {
this.checkLambda(node);
this.checkCloudwatch(node);
this.checkApiGw(node);
this.checkAppSync(node);
this.checkEventBridge(node);
this.checkSNS(node);
this.checkSQS(node);
this.checkStepFunctions(node);
}
}
/**
* Check Lambda Resources
* @param node the CfnResource to check
* @param ignores list of ignores for the resource
*/
checkLambda(node) {
this.applyRule({
info: 'The Lambda function does not have a configured failure destination for asynchronous invocations.',
explanation: "When a Lambda function is invoked asynchronously (e.g., by S3, SNS, or EventBridge), it's important to configure a failure destination. This allows you to capture and handle events that fail processing, improving the reliability and observability of your serverless applications.",
level: nag_rules_1.NagMessageLevel.ERROR,
rule: lambda_1.LambdaAsyncFailureDestination,
node: node,
});
this.applyRule({
info: 'The Lambda function does not have an explicit memory value configured.',
explanation: "Lambda allocates CPU power in proportion to the amount of memory configured. By default, your functions have 128 MB of memory allocated. You can increase that value up to 10 GB. With more CPU resources, your Lambda function's duration might decrease. You can use tools such as AWS Lambda Power Tuning to test your function at different memory settings to find the one that matches your cost and performance requirements the best.",
level: nag_rules_1.NagMessageLevel.ERROR,
rule: lambda_1.LambdaDefaultMemorySize,
node: node,
});
this.applyRule({
info: 'The Lambda function does not have an explicitly defined timeout value.',
explanation: 'Lambda functions have a default timeout of 3 seconds. If your timeout value is too short, Lambda might terminate invocations prematurely. On the other side, setting the timeout much higher than the average execution may cause functions to execute for longer upon code malfunction, resulting in higher costs and possibly reaching concurrency limits depending on how such functions are invoked. You can also use AWS Lambda Power Tuning to test your function at different timeout settings to find the one that matches your cost and performance requirements the best.',
level: nag_rules_1.NagMessageLevel.ERROR,
rule: lambda_1.LambdaDefaultTimeout,
node: node,
});
this.applyRule({
info: 'The Lambda function does not have a dead letter target configured.',
explanation: 'When a Lambda function has the DeadLetterConfig property set, failed messages can be temporarily stored for review in an SQS queue or an SNS topic.',
level: nag_rules_1.NagMessageLevel.ERROR,
rule: lambda_1.LambdaDLQ,
node: node,
});
this.applyRule({
info: 'The Lambda Event Source Mapping does not have a destination configured for failed invocations.',
explanation: 'Configuring a destination for failed invocations in Lambda Event Source Mappings allows you to capture and process events that fail to be processed by your Lambda function. This helps in monitoring, debugging, and implementing retry mechanisms for failed events, improving the reliability and observability of your serverless applications.',
level: nag_rules_1.NagMessageLevel.ERROR,
rule: lambda_1.LambdaEventSourceMappingDestination,
node: node,
});
this.applyRule({
info: 'The Lambda function does not use the latest runtime version.',
explanation: 'Using the latest runtime version ensures that your Lambda function has access to the most recent features, performance improvements, and security updates. It is important to regularly update your Lambda functions to use the latest runtime versions to maintain optimal performance and security.',
level: nag_rules_1.NagMessageLevel.ERROR,
rule: lambda_1.LambdaLatestVersion,
node: node,
});
this.applyRule({
info: 'The Lambda IAM role uses wildcard permissions.',
explanation: 'You should follow least-privileged access and only allow the access needed to perform a given operation. If your Lambda function needs a broad range of permissions, you should know ahead of time which permissions you will need, have evaluated the risks of using broad permissions and can suppress this rule.',
level: nag_rules_1.NagMessageLevel.WARN,
rule: lambda_1.LambdaStarPermissions,
node: node,
});
this.applyRule({
info: 'The Lambda function does not have tracing set to Tracing.ACTIVE.',
explanation: 'When a Lambda function has ACTIVE tracing, Lambda automatically samples invocation requests, based on the sampling algorithm specified by X-Ray.',
level: nag_rules_1.NagMessageLevel.WARN,
rule: lambda_1.LambdaTracing,
node: node,
});
}
/**
* Check Cloudwatch Resources
* @param node the CfnResource to check
* @param ignores list of ignores for the resource
*/
checkCloudwatch(node) {
this.applyRule({
info: 'The CloudWatch Log Group does not have an explicit retention policy defined.',
explanation: 'By default, logs are kept indefinitely and never expire. You can adjust the retention policy for each log group, keeping the indefinite retention, or choosing a retention period between one day and 10 years. For Lambda functions, this applies to their automatically created CloudWatch Log Groups.',
level: nag_rules_1.NagMessageLevel.WARN,
rule: cloudwatch_1.CloudWatchLogGroupRetentionPeriod,
node: node,
});
}
/**
* Check API Gateway Resources
* @param node the CfnResource to check
* @param ignores list of ignores for the resource
*/
checkApiGw(node) {
this.applyRule({
info: 'The API Gateway Stage does not have access logging enabled.',
explanation: 'API Gateway provides access logging for API stages. Enable access logging on your API stages to monitor API requests and responses.',
level: nag_rules_1.NagMessageLevel.ERROR,
rule: apigw_1.APIGWAccessLogging,
node: node,
});
this.applyRule({
info: 'The API Gateway Stage is using default throttling setting.',
explanation: 'API Gateway default throttling settings may not be suitable for all applications. Custom throttling limits help protect your backend systems from being overwhelmed with requests, ensure consistent performance, and can be tailored to your specific use case.',
level: nag_rules_1.NagMessageLevel.ERROR,
rule: apigw_1.APIGWDefaultThrottling,
node: node,
});
this.applyRule({
info: 'The API Gateway logs are not configured for the JSON format.',
explanation: 'You can customize the log format that Amazon API Gateway uses to send logs. JSON Structured logging makes it easier to derive queries to answer arbitrary questions about the health of your application.',
level: nag_rules_1.NagMessageLevel.WARN,
rule: apigw_1.APIGWStructuredLogging,
node: node,
});
this.applyRule({
info: 'The API Gateway does not have Tracing enabled.',
explanation: 'Amazon API Gateway provides active tracing support for AWS X-Ray. Enable active tracing on your API stages to sample incoming requests and send traces to X-Ray.',
level: nag_rules_1.NagMessageLevel.WARN,
rule: apigw_1.APIGWXrayEnabled,
node: node,
});
}
/**
* Check AppSync Resources
* @param node the CfnResource to check
* @param ignores list of ignores for the resource
*/
checkAppSync(node) {
this.applyRule({
info: 'The AppSync API does not have tracing enabled',
explanation: 'AWS AppSync can emit traces to AWS X-Ray, which enables visualizing service maps for faster troubleshooting.',
level: nag_rules_1.NagMessageLevel.WARN,
rule: appsync_1.AppSyncTracing,
node: node,
});
}
/**
* Check EventBridge Resources
* @param node the CfnResource to check
* @param ignores list of ignores for the resource
*/
checkEventBridge(node) {
this.applyRule({
info: 'The EventBridge Target does not have a DLQ configured.',
explanation: "Configuring a Dead-Letter Queue (DLQ) for EventBridge rules helps manage failed event deliveries. When a rule's target fails to process an event, the DLQ captures these failed events, allowing for analysis, troubleshooting, and potential reprocessing. This improves the reliability and observability of your event-driven architectures by providing a safety net for handling delivery failures.",
level: nag_rules_1.NagMessageLevel.ERROR,
rule: eventbridge_1.EventBusDLQ,
node: node,
});
}
/**
* Check SNS Resources
* @param node the CfnResource to check
* @param ignores list of ignores for the resource
*/
checkSNS(node) {
this.applyRule({
info: 'The SNS subscription does not have a redrive policy configured.',
explanation: 'Configuring a redrive policy helps manage message delivery failures by sending undeliverable messages to a dead-letter queue.',
level: nag_rules_1.NagMessageLevel.ERROR,
rule: sns_1.SNSRedrivePolicy,
node: node,
});
}
/**
* Check SQS Resources
* @param node the CfnResource to check
* @param ignores list of ignores for the resource
*/
checkSQS(node) {
this.applyRule({
info: 'The SQS queue does not have a redrive policy configured.',
explanation: 'Configuring a redrive policy on an SQS queue allows you to define how many times SQS will make messages available for consumers before sending them to a dead-letter queue. This helps in managing message processing failures and provides a mechanism for handling problematic messages.',
level: nag_rules_1.NagMessageLevel.ERROR,
rule: sqs_1.SQSRedrivePolicy,
node: node,
});
}
/**
* Check StepFunctions Resources
* @param node the CfnResource to check
* @param ignores list of ignores for the resource
*/
checkStepFunctions(node) {
this.applyRule({
info: 'The StepFunction state machine does not have X-Ray tracing configured.',
explanation: 'AWS StepFunctions provides active tracing support for AWS X-Ray. Enable active tracing on your API stages to sample incoming requests and send traces to X-Ray.',
level: nag_rules_1.NagMessageLevel.ERROR,
rule: stepfunctions_1.StepFunctionStateMachineXray,
node: node,
});
}
}
exports.ServerlessChecks = ServerlessChecks;
_a = JSII_RTTI_SYMBOL_1;
ServerlessChecks[_a] = { fqn: "cdk-nag.ServerlessChecks", version: "2.36.41" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVybGVzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYWNrcy9zZXJ2ZXJsZXNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUE7OztFQUdFO0FBQ0YsNkNBQTBDO0FBRTFDLDBDQUFvRDtBQUNwRCw0Q0FBK0M7QUFDL0MsMENBS3dCO0FBQ3hCLDhDQUFrRDtBQUNsRCxvREFBd0U7QUFDeEUsc0RBQW1EO0FBQ25ELDRDQVN5QjtBQUN6QixzQ0FBZ0Q7QUFDaEQsc0NBQWdEO0FBQ2hELDBEQUFzRTtBQUV0RTs7O0dBR0c7QUFDSCxNQUFhLGdCQUFpQixTQUFRLGtCQUFPO0lBQzNDLFlBQVksS0FBb0I7UUFDOUIsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2IsSUFBSSxDQUFDLFFBQVEsR0FBRyxZQUFZLENBQUM7SUFDL0IsQ0FBQztJQUNNLEtBQUssQ0FBQyxJQUFnQjtRQUMzQixJQUFJLElBQUksWUFBWSx5QkFBVyxFQUFFLENBQUM7WUFDaEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN2QixJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNCLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN4QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNwQixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3BCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoQyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxXQUFXLENBQUMsSUFBaUI7UUFDbkMsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUNiLElBQUksRUFBRSxr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O1lBQzVCLElBQUksRUFBRSxzQkFBZ0I7WUFDdEIsSUFBSSxFQUFFLElBQUk7U0FDWCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLFFBQVEsQ0FBQyxJQUFpQjtRQUNoQyxJQUFJLENBQUMsU0FBUyxDQUFDO1lBQ2IsSUFBSSxFQUFFLDBEQUEwRDtZQUNoRSxXQUFXLEVBQ1QsNFJBQTRSO1lBQzlSLEtBQUssRUFBRSwyQkFBZSxDQUFDLEtBQUs7WUFDNUIsSUFBSSxFQUFFLHNCQUFnQjtZQUN0QixJQUFJLEVBQUUsSUFBSTtTQUNYLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssa0JBQWtCLENBQUMsSUFBaUI7UUFDMUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUNiLElBQUksRUFBRSx3RUFBd0U7WUFDOUUsV0FBVyxFQUNULGlLQUFpSztZQUNuSyxLQUFLLEVBQUUsMkJBQWUsQ0FBQyxLQUFLO1lBQzVCLElBQUksRUFBRSw0Q0FBNEI7WUFDbEMsSUFBSSxFQUFFLElBQUk7U0FDWCxDQUFDLENBQUM7SUFDTCxDQUFDOztBQTFPSCw0Q0EyT0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuKi9cbmltcG9ydCB7IENmblJlc291cmNlIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgSUNvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgTmFnUGFjaywgTmFnUGFja1Byb3BzIH0gZnJvbSAnLi4vbmFnLXBhY2snO1xuaW1wb3J0IHsgTmFnTWVzc2FnZUxldmVsIH0gZnJvbSAnLi4vbmFnLXJ1bGVzJztcbmltcG9ydCB7XG4gIEFQSUdXQWNjZXNzTG9nZ2luZyxcbiAgQVBJR1dEZWZhdWx0VGhyb3R0bGluZyxcbiAgQVBJR1dTdHJ1Y3R1cmVkTG9nZ2luZyxcbiAgQVBJR1dYcmF5RW5hYmxlZCxcbn0gZnJvbSAnLi4vcnVsZXMvYXBpZ3cnO1xuaW1wb3J0IHsgQXBwU3luY1RyYWNpbmcgfSBmcm9tICcuLi9ydWxlcy9hcHBzeW5jJztcbmltcG9ydCB7IENsb3VkV2F0Y2hMb2dHcm91cFJldGVudGlvblBlcmlvZCB9IGZyb20gJy4uL3J1bGVzL2Nsb3Vkd2F0Y2gnO1xuaW1wb3J0IHsgRXZlbnRCdXNETFEgfSBmcm9tICcuLi9ydWxlcy9ldmVudGJyaWRnZSc7XG5pbXBvcnQge1xuICBMYW1iZGFBc3luY0ZhaWx1cmVEZXN0aW5hdGlvbixcbiAgTGFtYmRhRGVmYXVsdE1lbW9yeVNpemUsXG4gIExhbWJkYURlZmF1bHRUaW1lb3V0LFxuICBMYW1iZGFETFEsXG4gIExhbWJkYUV2ZW50U291cmNlTWFwcGluZ0Rlc3RpbmF0aW9uLFxuICBMYW1iZGFMYXRlc3RWZXJzaW9uLFxuICBMYW1iZGFTdGFyUGVybWlzc2lvbnMsXG4gIExhbWJkYVRyYWNpbmcsXG59IGZyb20gJy4uL3J1bGVzL2xhbWJkYSc7XG5pbXBvcnQgeyBTTlNSZWRyaXZlUG9saWN5IH0gZnJvbSAnLi4vcnVsZXMvc25zJztcbmltcG9ydCB7IFNRU1JlZHJpdmVQb2xpY3kgfSBmcm9tICcuLi9ydWxlcy9zcXMnO1xuaW1wb3J0IHsgU3RlcEZ1bmN0aW9uU3RhdGVNYWNoaW5lWHJheSB9IGZyb20gJy4uL3J1bGVzL3N0ZXBmdW5jdGlvbnMnO1xuXG4vKipcbiAqIFNlcnZlcmxlc3MgQ2hlY2tzIGFyZSBhIGNvbXBpbGF0aW9uIG9mIHJ1bGVzIHRvIHZhbGlkYXRlIGluZnJhc3RydWN0dXJlLWFzLWNvZGUgdGVtcGxhdGUgYWdhaW5zdCByZWNvbW1lbmRlZCBwcmFjdGljZXMuXG4gKlxuICovXG5leHBvcnQgY2xhc3MgU2VydmVybGVzc0NoZWNrcyBleHRlbmRzIE5hZ1BhY2sge1xuICBjb25zdHJ1Y3Rvcihwcm9wcz86IE5hZ1BhY2tQcm9wcykge1xuICAgIHN1cGVyKHByb3BzKTtcbiAgICB0aGlzLnBhY2tOYW1lID0gJ1NlcnZlcmxlc3MnO1xuICB9XG4gIHB1YmxpYyB2aXNpdChub2RlOiBJQ29uc3RydWN0KTogdm9pZCB7XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDZm5SZXNvdXJjZSkge1xuICAgICAgdGhpcy5jaGVja0xhbWJkYShub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tDbG91ZHdhdGNoKG5vZGUpO1xuICAgICAgdGhpcy5jaGVja0FwaUd3KG5vZGUpO1xuICAgICAgdGhpcy5jaGVja0FwcFN5bmMobm9kZSk7XG4gICAgICB0aGlzLmNoZWNrRXZlbnRCcmlkZ2Uobm9kZSk7XG4gICAgICB0aGlzLmNoZWNrU05TKG5vZGUpO1xuICAgICAgdGhpcy5jaGVja1NRUyhub2RlKTtcbiAgICAgIHRoaXMuY2hlY2tTdGVwRnVuY3Rpb25zKG5vZGUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBMYW1iZGEgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja0xhbWJkYShub2RlOiBDZm5SZXNvdXJjZSkge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgTGFtYmRhIGZ1bmN0aW9uIGRvZXMgbm90IGhhdmUgYSBjb25maWd1cmVkIGZhaWx1cmUgZGVzdGluYXRpb24gZm9yIGFzeW5jaHJvbm91cyBpbnZvY2F0aW9ucy4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgIFwiV2hlbiBhIExhbWJkYSBmdW5jdGlvbiBpcyBpbnZva2VkIGFzeW5jaHJvbm91c2x5IChlLmcuLCBieSBTMywgU05TLCBvciBFdmVudEJyaWRnZSksIGl0J3MgaW1wb3J0YW50IHRvIGNvbmZpZ3VyZSBhIGZhaWx1cmUgZGVzdGluYXRpb24uIFRoaXMgYWxsb3dzIHlvdSB0byBjYXB0dXJlIGFuZCBoYW5kbGUgZXZlbnRzIHRoYXQgZmFpbCBwcm9jZXNzaW5nLCBpbXByb3ZpbmcgdGhlIHJlbGlhYmlsaXR5IGFuZCBvYnNlcnZhYmlsaXR5IG9mIHlvdXIgc2VydmVybGVzcyBhcHBsaWNhdGlvbnMuXCIsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogTGFtYmRhQXN5bmNGYWlsdXJlRGVzdGluYXRpb24sXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBMYW1iZGEgZnVuY3Rpb24gZG9lcyBub3QgaGF2ZSBhbiBleHBsaWNpdCBtZW1vcnkgdmFsdWUgY29uZmlndXJlZC4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgIFwiTGFtYmRhIGFsbG9jYXRlcyBDUFUgcG93ZXIgaW4gcHJvcG9ydGlvbiB0byB0aGUgYW1vdW50IG9mIG1lbW9yeSBjb25maWd1cmVkLiBCeSBkZWZhdWx0LCB5b3VyIGZ1bmN0aW9ucyBoYXZlIDEyOCBNQiBvZiBtZW1vcnkgYWxsb2NhdGVkLiBZb3UgY2FuIGluY3JlYXNlIHRoYXQgdmFsdWUgdXAgdG8gMTAgR0IuIFdpdGggbW9yZSBDUFUgcmVzb3VyY2VzLCB5b3VyIExhbWJkYSBmdW5jdGlvbidzIGR1cmF0aW9uIG1pZ2h0IGRlY3JlYXNlLiAgWW91IGNhbiB1c2UgdG9vbHMgc3VjaCBhcyBBV1MgTGFtYmRhIFBvd2VyIFR1bmluZyB0byB0ZXN0IHlvdXIgZnVuY3Rpb24gYXQgZGlmZmVyZW50IG1lbW9yeSBzZXR0aW5ncyB0byBmaW5kIHRoZSBvbmUgdGhhdCBtYXRjaGVzIHlvdXIgY29zdCBhbmQgcGVyZm9ybWFuY2UgcmVxdWlyZW1lbnRzIHRoZSBiZXN0LlwiLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IExhbWJkYURlZmF1bHRNZW1vcnlTaXplLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcblxuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgTGFtYmRhIGZ1bmN0aW9uIGRvZXMgbm90IGhhdmUgYW4gZXhwbGljaXRseSBkZWZpbmVkIHRpbWVvdXQgdmFsdWUuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnTGFtYmRhIGZ1bmN0aW9ucyBoYXZlIGEgZGVmYXVsdCB0aW1lb3V0IG9mIDMgc2Vjb25kcy4gSWYgeW91ciB0aW1lb3V0IHZhbHVlIGlzIHRvbyBzaG9ydCwgTGFtYmRhIG1pZ2h0IHRlcm1pbmF0ZSBpbnZvY2F0aW9ucyBwcmVtYXR1cmVseS4gT24gdGhlIG90aGVyIHNpZGUsIHNldHRpbmcgdGhlIHRpbWVvdXQgbXVjaCBoaWdoZXIgdGhhbiB0aGUgYXZlcmFnZSBleGVjdXRpb24gbWF5IGNhdXNlIGZ1bmN0aW9ucyB0byBleGVjdXRlIGZvciBsb25nZXIgdXBvbiBjb2RlIG1hbGZ1bmN0aW9uLCByZXN1bHRpbmcgaW4gaGlnaGVyIGNvc3RzIGFuZCBwb3NzaWJseSByZWFjaGluZyBjb25jdXJyZW5jeSBsaW1pdHMgZGVwZW5kaW5nIG9uIGhvdyBzdWNoIGZ1bmN0aW9ucyBhcmUgaW52b2tlZC4gWW91IGNhbiBhbHNvIHVzZSBBV1MgTGFtYmRhIFBvd2VyIFR1bmluZyB0byB0ZXN0IHlvdXIgZnVuY3Rpb24gYXQgZGlmZmVyZW50IHRpbWVvdXQgc2V0dGluZ3MgdG8gZmluZCB0aGUgb25lIHRoYXQgbWF0Y2hlcyB5b3VyIGNvc3QgYW5kIHBlcmZvcm1hbmNlIHJlcXVpcmVtZW50cyB0aGUgYmVzdC4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IExhbWJkYURlZmF1bHRUaW1lb3V0LFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcblxuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgTGFtYmRhIGZ1bmN0aW9uIGRvZXMgbm90IGhhdmUgYSBkZWFkIGxldHRlciB0YXJnZXQgY29uZmlndXJlZC4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdXaGVuIGEgTGFtYmRhIGZ1bmN0aW9uIGhhcyB0aGUgRGVhZExldHRlckNvbmZpZyBwcm9wZXJ0eSBzZXQsIGZhaWxlZCBtZXNzYWdlcyBjYW4gYmUgdGVtcG9yYXJpbHkgc3RvcmVkIGZvciByZXZpZXcgaW4gYW4gU1FTIHF1ZXVlIG9yIGFuIFNOUyB0b3BpYy4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5FUlJPUixcbiAgICAgIHJ1bGU6IExhbWJkYURMUSxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG5cbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIExhbWJkYSBFdmVudCBTb3VyY2UgTWFwcGluZyBkb2VzIG5vdCBoYXZlIGEgZGVzdGluYXRpb24gY29uZmlndXJlZCBmb3IgZmFpbGVkIGludm9jYXRpb25zLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0NvbmZpZ3VyaW5nIGEgZGVzdGluYXRpb24gZm9yIGZhaWxlZCBpbnZvY2F0aW9ucyBpbiBMYW1iZGEgRXZlbnQgU291cmNlIE1hcHBpbmdzIGFsbG93cyB5b3UgdG8gY2FwdHVyZSBhbmQgcHJvY2VzcyBldmVudHMgdGhhdCBmYWlsIHRvIGJlIHByb2Nlc3NlZCBieSB5b3VyIExhbWJkYSBmdW5jdGlvbi4gVGhpcyBoZWxwcyBpbiBtb25pdG9yaW5nLCBkZWJ1Z2dpbmcsIGFuZCBpbXBsZW1lbnRpbmcgcmV0cnkgbWVjaGFuaXNtcyBmb3IgZmFpbGVkIGV2ZW50cywgaW1wcm92aW5nIHRoZSByZWxpYWJpbGl0eSBhbmQgb2JzZXJ2YWJpbGl0eSBvZiB5b3VyIHNlcnZlcmxlc3MgYXBwbGljYXRpb25zLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogTGFtYmRhRXZlbnRTb3VyY2VNYXBwaW5nRGVzdGluYXRpb24sXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBMYW1iZGEgZnVuY3Rpb24gZG9lcyBub3QgdXNlIHRoZSBsYXRlc3QgcnVudGltZSB2ZXJzaW9uLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ1VzaW5nIHRoZSBsYXRlc3QgcnVudGltZSB2ZXJzaW9uIGVuc3VyZXMgdGhhdCB5b3VyIExhbWJkYSBmdW5jdGlvbiBoYXMgYWNjZXNzIHRvIHRoZSBtb3N0IHJlY2VudCBmZWF0dXJlcywgcGVyZm9ybWFuY2UgaW1wcm92ZW1lbnRzLCBhbmQgc2VjdXJpdHkgdXBkYXRlcy4gSXQgaXMgaW1wb3J0YW50IHRvIHJlZ3VsYXJseSB1cGRhdGUgeW91ciBMYW1iZGEgZnVuY3Rpb25zIHRvIHVzZSB0aGUgbGF0ZXN0IHJ1bnRpbWUgdmVyc2lvbnMgdG8gbWFpbnRhaW4gb3B0aW1hbCBwZXJmb3JtYW5jZSBhbmQgc2VjdXJpdHkuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBMYW1iZGFMYXRlc3RWZXJzaW9uLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcblxuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgTGFtYmRhIElBTSByb2xlIHVzZXMgd2lsZGNhcmQgcGVybWlzc2lvbnMuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnWW91IHNob3VsZCBmb2xsb3cgbGVhc3QtcHJpdmlsZWdlZCBhY2Nlc3MgYW5kIG9ubHkgYWxsb3cgdGhlIGFjY2VzcyBuZWVkZWQgdG8gcGVyZm9ybSBhIGdpdmVuIG9wZXJhdGlvbi4gSWYgeW91ciBMYW1iZGEgZnVuY3Rpb24gbmVlZHMgYSBicm9hZCByYW5nZSBvZiBwZXJtaXNzaW9ucywgeW91IHNob3VsZCBrbm93IGFoZWFkIG9mIHRpbWUgd2hpY2ggcGVybWlzc2lvbnMgeW91IHdpbGwgbmVlZCwgaGF2ZSBldmFsdWF0ZWQgdGhlIHJpc2tzIG9mIHVzaW5nIGJyb2FkIHBlcm1pc3Npb25zIGFuZCBjYW4gc3VwcHJlc3MgdGhpcyBydWxlLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLldBUk4sXG4gICAgICBydWxlOiBMYW1iZGFTdGFyUGVybWlzc2lvbnMsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBMYW1iZGEgZnVuY3Rpb24gZG9lcyBub3QgaGF2ZSB0cmFjaW5nIHNldCB0byBUcmFjaW5nLkFDVElWRS4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdXaGVuIGEgTGFtYmRhIGZ1bmN0aW9uIGhhcyBBQ1RJVkUgdHJhY2luZywgTGFtYmRhIGF1dG9tYXRpY2FsbHkgc2FtcGxlcyBpbnZvY2F0aW9uIHJlcXVlc3RzLCBiYXNlZCBvbiB0aGUgc2FtcGxpbmcgYWxnb3JpdGhtIHNwZWNpZmllZCBieSBYLVJheS4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5XQVJOLFxuICAgICAgcnVsZTogTGFtYmRhVHJhY2luZyxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgQ2xvdWR3YXRjaCBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrQ2xvdWR3YXRjaChub2RlOiBDZm5SZXNvdXJjZSkge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgQ2xvdWRXYXRjaCBMb2cgR3JvdXAgZG9lcyBub3QgaGF2ZSBhbiBleHBsaWNpdCByZXRlbnRpb24gcG9saWN5IGRlZmluZWQuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQnkgZGVmYXVsdCwgbG9ncyBhcmUga2VwdCBpbmRlZmluaXRlbHkgYW5kIG5ldmVyIGV4cGlyZS4gWW91IGNhbiBhZGp1c3QgdGhlIHJldGVudGlvbiBwb2xpY3kgZm9yIGVhY2ggbG9nIGdyb3VwLCBrZWVwaW5nIHRoZSBpbmRlZmluaXRlIHJldGVudGlvbiwgb3IgY2hvb3NpbmcgYSByZXRlbnRpb24gcGVyaW9kIGJldHdlZW4gb25lIGRheSBhbmQgMTAgeWVhcnMuIEZvciBMYW1iZGEgZnVuY3Rpb25zLCB0aGlzIGFwcGxpZXMgdG8gdGhlaXIgYXV0b21hdGljYWxseSBjcmVhdGVkIENsb3VkV2F0Y2ggTG9nIEdyb3Vwcy4nLFxuICAgICAgbGV2ZWw6IE5hZ01lc3NhZ2VMZXZlbC5XQVJOLFxuICAgICAgcnVsZTogQ2xvdWRXYXRjaExvZ0dyb3VwUmV0ZW50aW9uUGVyaW9kLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBBUEkgR2F0ZXdheSBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrQXBpR3cobm9kZTogQ2ZuUmVzb3VyY2UpIHtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIEFQSSBHYXRld2F5IFN0YWdlIGRvZXMgbm90IGhhdmUgYWNjZXNzIGxvZ2dpbmcgZW5hYmxlZC4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdBUEkgR2F0ZXdheSBwcm92aWRlcyBhY2Nlc3MgbG9nZ2luZyBmb3IgQVBJIHN0YWdlcy4gRW5hYmxlIGFjY2VzcyBsb2dnaW5nIG9uIHlvdXIgQVBJIHN0YWdlcyB0byBtb25pdG9yIEFQSSByZXF1ZXN0cyBhbmQgcmVzcG9uc2VzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogQVBJR1dBY2Nlc3NMb2dnaW5nLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcblxuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgQVBJIEdhdGV3YXkgU3RhZ2UgaXMgdXNpbmcgZGVmYXVsdCB0aHJvdHRsaW5nIHNldHRpbmcuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQVBJIEdhdGV3YXkgZGVmYXVsdCB0aHJvdHRsaW5nIHNldHRpbmdzIG1heSBub3QgYmUgc3VpdGFibGUgZm9yIGFsbCBhcHBsaWNhdGlvbnMuIEN1c3RvbSB0aHJvdHRsaW5nIGxpbWl0cyBoZWxwIHByb3RlY3QgeW91ciBiYWNrZW5kIHN5c3RlbXMgZnJvbSBiZWluZyBvdmVyd2hlbG1lZCB3aXRoIHJlcXVlc3RzLCBlbnN1cmUgY29uc2lzdGVudCBwZXJmb3JtYW5jZSwgYW5kIGNhbiBiZSB0YWlsb3JlZCB0byB5b3VyIHNwZWNpZmljIHVzZSBjYXNlLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogQVBJR1dEZWZhdWx0VGhyb3R0bGluZyxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG5cbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIEFQSSBHYXRld2F5IGxvZ3MgYXJlIG5vdCBjb25maWd1cmVkIGZvciB0aGUgSlNPTiBmb3JtYXQuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnWW91IGNhbiBjdXN0b21pemUgdGhlIGxvZyBmb3JtYXQgdGhhdCBBbWF6b24gQVBJIEdhdGV3YXkgdXNlcyB0byBzZW5kIGxvZ3MuIEpTT04gU3RydWN0dXJlZCBsb2dnaW5nIG1ha2VzIGl0IGVhc2llciB0byBkZXJpdmUgcXVlcmllcyB0byBhbnN3ZXIgYXJiaXRyYXJ5IHF1ZXN0aW9ucyBhYm91dCB0aGUgaGVhbHRoIG9mIHlvdXIgYXBwbGljYXRpb24uJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuV0FSTixcbiAgICAgIHJ1bGU6IEFQSUdXU3RydWN0dXJlZExvZ2dpbmcsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBBUEkgR2F0ZXdheSBkb2VzIG5vdCBoYXZlIFRyYWNpbmcgZW5hYmxlZC4nLFxuICAgICAgZXhwbGFuYXRpb246XG4gICAgICAgICdBbWF6b24gQVBJIEdhdGV3YXkgcHJvdmlkZXMgYWN0aXZlIHRyYWNpbmcgc3VwcG9ydCBmb3IgQVdTIFgtUmF5LiBFbmFibGUgYWN0aXZlIHRyYWNpbmcgb24geW91ciBBUEkgc3RhZ2VzIHRvIHNhbXBsZSBpbmNvbWluZyByZXF1ZXN0cyBhbmQgc2VuZCB0cmFjZXMgdG8gWC1SYXkuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuV0FSTixcbiAgICAgIHJ1bGU6IEFQSUdXWHJheUVuYWJsZWQsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIEFwcFN5bmMgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja0FwcFN5bmMobm9kZTogQ2ZuUmVzb3VyY2UpIHtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIEFwcFN5bmMgQVBJIGRvZXMgbm90IGhhdmUgdHJhY2luZyBlbmFibGVkJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQVdTIEFwcFN5bmMgY2FuIGVtaXQgdHJhY2VzIHRvIEFXUyBYLVJheSwgd2hpY2ggZW5hYmxlcyB2aXN1YWxpemluZyBzZXJ2aWNlIG1hcHMgZm9yIGZhc3RlciB0cm91Ymxlc2hvb3RpbmcuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuV0FSTixcbiAgICAgIHJ1bGU6IEFwcFN5bmNUcmFjaW5nLFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBFdmVudEJyaWRnZSBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrRXZlbnRCcmlkZ2Uobm9kZTogQ2ZuUmVzb3VyY2UpIHtcbiAgICB0aGlzLmFwcGx5UnVsZSh7XG4gICAgICBpbmZvOiAnVGhlIEV2ZW50QnJpZGdlIFRhcmdldCBkb2VzIG5vdCBoYXZlIGEgRExRIGNvbmZpZ3VyZWQuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICBcIkNvbmZpZ3VyaW5nIGEgRGVhZC1MZXR0ZXIgUXVldWUgKERMUSkgZm9yIEV2ZW50QnJpZGdlIHJ1bGVzIGhlbHBzIG1hbmFnZSBmYWlsZWQgZXZlbnQgZGVsaXZlcmllcy4gV2hlbiBhIHJ1bGUncyB0YXJnZXQgZmFpbHMgdG8gcHJvY2VzcyBhbiBldmVudCwgdGhlIERMUSBjYXB0dXJlcyB0aGVzZSBmYWlsZWQgZXZlbnRzLCBhbGxvd2luZyBmb3IgYW5hbHlzaXMsIHRyb3VibGVzaG9vdGluZywgYW5kIHBvdGVudGlhbCByZXByb2Nlc3NpbmcuIFRoaXMgaW1wcm92ZXMgdGhlIHJlbGlhYmlsaXR5IGFuZCBvYnNlcnZhYmlsaXR5IG9mIHlvdXIgZXZlbnQtZHJpdmVuIGFyY2hpdGVjdHVyZXMgYnkgcHJvdmlkaW5nIGEgc2FmZXR5IG5ldCBmb3IgaGFuZGxpbmcgZGVsaXZlcnkgZmFpbHVyZXMuXCIsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogRXZlbnRCdXNETFEsXG4gICAgICBub2RlOiBub2RlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIFNOUyBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrU05TKG5vZGU6IENmblJlc291cmNlKSB7XG4gICAgdGhpcy5hcHBseVJ1bGUoe1xuICAgICAgaW5mbzogJ1RoZSBTTlMgc3Vic2NyaXB0aW9uIGRvZXMgbm90IGhhdmUgYSByZWRyaXZlIHBvbGljeSBjb25maWd1cmVkLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0NvbmZpZ3VyaW5nIGEgcmVkcml2ZSBwb2xpY3kgaGVscHMgbWFuYWdlIG1lc3NhZ2UgZGVsaXZlcnkgZmFpbHVyZXMgYnkgc2VuZGluZyB1bmRlbGl2ZXJhYmxlIG1lc3NhZ2VzIHRvIGEgZGVhZC1sZXR0ZXIgcXVldWUuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBTTlNSZWRyaXZlUG9saWN5LFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBTUVMgUmVzb3VyY2VzXG4gICAqIEBwYXJhbSBub2RlIHRoZSBDZm5SZXNvdXJjZSB0byBjaGVja1xuICAgKiBAcGFyYW0gaWdub3JlcyBsaXN0IG9mIGlnbm9yZXMgZm9yIHRoZSByZXNvdXJjZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja1NRUyhub2RlOiBDZm5SZXNvdXJjZSkge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgU1FTIHF1ZXVlIGRvZXMgbm90IGhhdmUgYSByZWRyaXZlIHBvbGljeSBjb25maWd1cmVkLicsXG4gICAgICBleHBsYW5hdGlvbjpcbiAgICAgICAgJ0NvbmZpZ3VyaW5nIGEgcmVkcml2ZSBwb2xpY3kgb24gYW4gU1FTIHF1ZXVlIGFsbG93cyB5b3UgdG8gZGVmaW5lIGhvdyBtYW55IHRpbWVzIFNRUyB3aWxsIG1ha2UgbWVzc2FnZXMgYXZhaWxhYmxlIGZvciBjb25zdW1lcnMgYmVmb3JlIHNlbmRpbmcgdGhlbSB0byBhIGRlYWQtbGV0dGVyIHF1ZXVlLiBUaGlzIGhlbHBzIGluIG1hbmFnaW5nIG1lc3NhZ2UgcHJvY2Vzc2luZyBmYWlsdXJlcyBhbmQgcHJvdmlkZXMgYSBtZWNoYW5pc20gZm9yIGhhbmRsaW5nIHByb2JsZW1hdGljIG1lc3NhZ2VzLicsXG4gICAgICBsZXZlbDogTmFnTWVzc2FnZUxldmVsLkVSUk9SLFxuICAgICAgcnVsZTogU1FTUmVkcml2ZVBvbGljeSxcbiAgICAgIG5vZGU6IG5vZGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgU3RlcEZ1bmN0aW9ucyBSZXNvdXJjZXNcbiAgICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBpZ25vcmVzIGxpc3Qgb2YgaWdub3JlcyBmb3IgdGhlIHJlc291cmNlXG4gICAqL1xuICBwcml2YXRlIGNoZWNrU3RlcEZ1bmN0aW9ucyhub2RlOiBDZm5SZXNvdXJjZSkge1xuICAgIHRoaXMuYXBwbHlSdWxlKHtcbiAgICAgIGluZm86ICdUaGUgU3RlcEZ1bmN0aW9uIHN0YXRlIG1hY2hpbmUgZG9lcyBub3QgaGF2ZSBYLVJheSB0cmFjaW5nIGNvbmZpZ3VyZWQuJyxcbiAgICAgIGV4cGxhbmF0aW9uOlxuICAgICAgICAnQVdTIFN0ZXBGdW5jdGlvbnMgcHJvdmlkZXMgYWN0aXZlIHRyYWNpbmcgc3VwcG9ydCBmb3IgQVdTIFgtUmF5LiBFbmFibGUgYWN0aXZlIHRyYWNpbmcgb24geW91ciBBUEkgc3RhZ2VzIHRvIHNhbXBsZSBpbmNvbWluZyByZXF1ZXN0cyBhbmQgc2VuZCB0cmFjZXMgdG8gWC1SYXkuJyxcbiAgICAgIGxldmVsOiBOYWdNZXNzYWdlTGV2ZWwuRVJST1IsXG4gICAgICBydWxlOiBTdGVwRnVuY3Rpb25TdGF0ZU1hY2hpbmVYcmF5LFxuICAgICAgbm9kZTogbm9kZSxcbiAgICB9KTtcbiAgfVxufVxuIl19