image-scanner-with-trivy
Version:
Scan container images with Trivy in CDK deployment
189 lines • 35.1 kB
JavaScript
;
var _a, _b, _c;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImageScannerWithTrivyV2 = exports.TargetImagePlatform = exports.TrivyIgnore = exports.TrivyIgnoreFileType = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const fs_1 = require("fs");
const path_1 = require("path");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_ecr_assets_1 = require("aws-cdk-lib/aws-ecr-assets");
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
const custom_resources_1 = require("aws-cdk-lib/custom-resources");
const constructs_1 = require("constructs");
const types_1 = require("./types");
/**
* File type for TrivyIgnore file path
*/
var TrivyIgnoreFileType;
(function (TrivyIgnoreFileType) {
/**
* .trivyignore file
*
* @see https://trivy.dev/docs/latest/configuration/filtering/#trivyignore
*/
TrivyIgnoreFileType["TRIVYIGNORE"] = "TRIVYIGNORE";
/**
* .trivyignore.yaml file
*
* @see https://trivy.dev/docs/latest/configuration/filtering/#trivyignoreyaml
*/
TrivyIgnoreFileType["TRIVYIGNORE_YAML"] = "TRIVYIGNORE_YAML";
})(TrivyIgnoreFileType || (exports.TrivyIgnoreFileType = TrivyIgnoreFileType = {}));
/**
* Union-like class for specifying Trivy ignore configuration.
*
* You can either specify ignore rules inline, or point to an existing ignore file.
*/
class TrivyIgnore {
/**
* Specify ignore rules inline (equivalent to writing lines in a .trivyignore file).
*
* @param rules Each element corresponds to one line in the .trivyignore file.
*
* @see https://trivy.dev/docs/latest/configuration/filtering/#trivyignore
*/
static fromRules(rules) {
return new TrivyIgnore(rules);
}
/**
* Specify the path to an existing trivyignore file.
*
* @param path Path to the ignore file.
* @param fileType File format. Defaults to `TrivyIgnoreFileType.TRIVYIGNORE`.
*
* @see https://trivy.dev/docs/latest/configuration/filtering/#trivyignore
* @see https://trivy.dev/docs/latest/configuration/filtering/#trivyignoreyaml
*/
static fromFilePath(path, fileType = TrivyIgnoreFileType.TRIVYIGNORE) {
const content = (0, fs_1.readFileSync)(path, 'utf-8');
// Pass lines as-is without stripping comments or empty lines
// because Trivy itself handles comment lines (starting with `#`) and empty lines when reading the ignore file.
return new TrivyIgnore(content.split('\n'), fileType);
}
constructor(rules, fileType) {
this.rules = rules;
this.fileType = fileType;
}
}
exports.TrivyIgnore = TrivyIgnore;
_a = JSII_RTTI_SYMBOL_1;
TrivyIgnore[_a] = { fqn: "image-scanner-with-trivy.TrivyIgnore", version: "2.4.3" };
/**
* Enum for Target Image Platform
*/
class TargetImagePlatform {
/**
* Custom value for target image platform
*
* The value should be in the format OS/Architecture for the image, such as `linux/arm64`.
*/
static custom(value) {
return new TargetImagePlatform(value);
}
constructor(value) {
this.value = value;
}
}
exports.TargetImagePlatform = TargetImagePlatform;
_b = JSII_RTTI_SYMBOL_1;
TargetImagePlatform[_b] = { fqn: "image-scanner-with-trivy.TargetImagePlatform", version: "2.4.3" };
/**
* Linux AMD64 platform
*/
TargetImagePlatform.LINUX_AMD64 = new TargetImagePlatform('linux/amd64');
/**
* Linux ARM64 platform
*/
TargetImagePlatform.LINUX_ARM64 = new TargetImagePlatform('linux/arm64');
// Maximum Lambda memory size for default AWS account without quota limit increase
const DEFAULT_MEMORY_SIZE = 3008;
/**
* A Construct that scans container images with Trivy.
* It uses a Lambda function as a Custom Resource provider to run Trivy and scan container images.
*/
class ImageScannerWithTrivyV2 extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
if (props.memorySize &&
!aws_cdk_lib_1.Token.isUnresolved(props.memorySize) &&
(props.memorySize < 3008 || props.memorySize > 10240)) {
throw new Error(`You can specify between \`3008\` and \`10240\` for \`memorySize\`, got ${props.memorySize}.`);
}
this.defaultLogGroup = props.defaultLogGroup;
const lambdaPurpose = 'Custom::ImageScannerWithTrivyV2CustomResourceLambda';
const customResourceLambda = new aws_lambda_1.SingletonFunction(this, 'CustomResourceLambda', {
uuid: 'cc3b41b5-4701-d86f-fe24-3a04f4a573f1',
lambdaPurpose,
runtime: aws_lambda_1.Runtime.FROM_IMAGE,
handler: aws_lambda_1.Handler.FROM_IMAGE,
code: aws_lambda_1.AssetCode.fromAssetImage((0, path_1.join)(__dirname, '../assets/lambda'), {
platform: aws_ecr_assets_1.Platform.LINUX_ARM64,
ignoreMode: aws_cdk_lib_1.IgnoreMode.DOCKER,
}),
architecture: aws_lambda_1.Architecture.ARM_64,
timeout: aws_cdk_lib_1.Duration.seconds(900),
retryAttempts: 0,
memorySize: props.memorySize ?? DEFAULT_MEMORY_SIZE,
ephemeralStorageSize: aws_cdk_lib_1.Size.gibibytes(10), // for cases that need to update trivy DB: /tmp/trivy/db/trivy.db
logGroup: this.defaultLogGroup,
});
props.repository.grantPull(customResourceLambda);
if (props.vulnsNotificationTopic) {
props.vulnsNotificationTopic.grantPublish(customResourceLambda);
}
// Grant CloudFormation DescribeStacks permission for rollback detection when suppressErrorOnRollback is enabled
const suppressErrorOnRollback = props.suppressErrorOnRollback ?? true;
if (suppressErrorOnRollback) {
customResourceLambda.addToRolePolicy(new aws_iam_1.PolicyStatement({
actions: ['cloudformation:DescribeStacks'],
resources: [aws_cdk_lib_1.Stack.of(this).stackId],
}));
}
// If multiple ImageScannerWithTrivyV2 constructs in the same stack have different default log groups, add a warning annotation.
aws_cdk_lib_1.Aspects.of(aws_cdk_lib_1.Stack.of(this)).add({
visit: (node) => {
if (node instanceof ImageScannerWithTrivyV2 &&
node._defaultLogGroup?.node.path !== this.defaultLogGroup?.node.path) {
aws_cdk_lib_1.Annotations.of(this).addWarningV2('@image-scanner-with-trivy:duplicateLambdaDefaultLogGroup', "You have to set the same log group for 'defaultLogGroup' for each ImageScannerWithTrivyV2 construct in the same stack.");
}
},
});
const imageScannerProvider = new custom_resources_1.Provider(this, 'Provider', {
onEventHandler: customResourceLambda,
});
const imageScannerProperties = {
addr: this.node.addr,
imageUri: props.imageUri,
ignoreUnfixed: String(props.ignoreUnfixed ?? false),
severity: props.severity ?? [types_1.Severity.CRITICAL],
scanners: props.scanners ?? [],
imageConfigScanners: props.imageConfigScanners ?? [],
failOnVulnerability: String(props.failOnVulnerability ?? true),
trivyIgnore: props.trivyIgnore?.rules ?? [],
trivyIgnoreFileType: props.trivyIgnore?.fileType,
platform: props.targetImagePlatform?.value ?? '',
output: props.scanLogsOutput?.bind(customResourceLambda),
suppressErrorOnRollback: String(suppressErrorOnRollback),
vulnsTopicArn: props.vulnsNotificationTopic?.topicArn,
defaultLogGroupName: this.defaultLogGroup?.logGroupName ?? `/aws/lambda/${customResourceLambda.functionName}`,
};
new aws_cdk_lib_1.CustomResource(this, 'Resource', {
resourceType: 'Custom::ImageScannerWithTrivyV2',
properties: imageScannerProperties,
serviceToken: imageScannerProvider.serviceToken,
});
// Block constructs if vulnerabilities are detected
props.blockConstructs?.forEach((construct) => {
construct.node.addDependency(this);
});
}
/** @internal */
get _defaultLogGroup() {
return this.defaultLogGroup;
}
}
exports.ImageScannerWithTrivyV2 = ImageScannerWithTrivyV2;
_c = JSII_RTTI_SYMBOL_1;
ImageScannerWithTrivyV2[_c] = { fqn: "image-scanner-with-trivy.ImageScannerWithTrivyV2", version: "2.4.3" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2Utc2Nhbm5lci13aXRoLXRyaXZ5LXYyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ltYWdlLXNjYW5uZXItd2l0aC10cml2eS12Mi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDJCQUFrQztBQUNsQywrQkFBNEI7QUFDNUIsNkNBU3FCO0FBRXJCLCtEQUFzRDtBQUN0RCxpREFBc0Q7QUFDdEQsdURBTWdDO0FBR2hDLG1FQUF3RDtBQUN4RCwyQ0FBbUQ7QUFHbkQsbUNBQWtFO0FBRWxFOztHQUVHO0FBQ0gsSUFBWSxtQkFjWDtBQWRELFdBQVksbUJBQW1CO0lBQzdCOzs7O09BSUc7SUFDSCxrREFBMkIsQ0FBQTtJQUUzQjs7OztPQUlHO0lBQ0gsNERBQXFDLENBQUE7QUFDdkMsQ0FBQyxFQWRXLG1CQUFtQixtQ0FBbkIsbUJBQW1CLFFBYzlCO0FBRUQ7Ozs7R0FJRztBQUNILE1BQWEsV0FBVztJQUN0Qjs7Ozs7O09BTUc7SUFDSSxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQWU7UUFDckMsT0FBTyxJQUFJLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSSxNQUFNLENBQUMsWUFBWSxDQUN4QixJQUFZLEVBQ1osV0FBZ0MsbUJBQW1CLENBQUMsV0FBVztRQUUvRCxNQUFNLE9BQU8sR0FBRyxJQUFBLGlCQUFZLEVBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzVDLDZEQUE2RDtRQUM3RCwrR0FBK0c7UUFDL0csT0FBTyxJQUFJLFdBQVcsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFRCxZQUNrQixLQUFlLEVBQ2YsUUFBOEI7UUFEOUIsVUFBSyxHQUFMLEtBQUssQ0FBVTtRQUNmLGFBQVEsR0FBUixRQUFRLENBQXNCO0lBQzdDLENBQUM7O0FBbENOLGtDQW1DQzs7O0FB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UUFBUTtZQUNoRCxRQUFRLEVBQUUsS0FBSyxDQUFDLG1CQUFtQixFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ2hELE1BQU0sRUFBRSxLQUFLLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxvQkFBb0IsQ0FBQztZQUN4RCx1QkFBdUIsRUFBRSxNQUFNLENBQUMsdUJBQXVCLENBQUM7WUFDeEQsYUFBYSxFQUFFLEtBQUssQ0FBQyxzQkFBc0IsRUFBRSxRQUFRO1lBQ3JELG1CQUFtQixFQUNqQixJQUFJLENBQUMsZUFBZSxFQUFFLFlBQVksSUFBSSxlQUFlLG9CQUFvQixDQUFDLFlBQVksRUFBRTtTQUMzRixDQUFDO1FBRUYsSUFBSSw0QkFBYyxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDbkMsWUFBWSxFQUFFLGlDQUFpQztZQUMvQyxVQUFVLEVBQUUsc0JBQXNCO1lBQ2xDLFlBQVksRUFBRSxvQkFBb0IsQ0FBQyxZQUFZO1NBQ2hELENBQUMsQ0FBQztRQUVILG1EQUFtRDtRQUNuRCxLQUFLLENBQUMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFO1lBQzNDLFNBQVMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGdCQUFnQjtJQUNoQixJQUFJLGdCQUFnQjtRQUNsQixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUM7SUFDOUIsQ0FBQzs7QUF6R0gsMERBMEdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVhZEZpbGVTeW5jIH0gZnJvbSAnZnMnO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHtcbiAgQW5ub3RhdGlvbnMsXG4gIEFzcGVjdHMsXG4gIEN1c3RvbVJlc291cmNlLFxuICBEdXJhdGlvbixcbiAgSWdub3JlTW9kZSxcbiAgU2l6ZSxcbiAgU3RhY2ssXG4gIFRva2VuLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBJUmVwb3NpdG9yeSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lY3InO1xuaW1wb3J0IHsgUGxhdGZvcm0gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWNyLWFzc2V0cyc7XG5pbXBvcnQgeyBQb2xpY3lTdGF0ZW1lbnQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7XG4gIEFyY2hpdGVjdHVyZSxcbiAgQXNzZXRDb2RlLFxuICBIYW5kbGVyLFxuICBSdW50aW1lLFxuICBTaW5nbGV0b25GdW5jdGlvbixcbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBJTG9nR3JvdXAgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG5pbXBvcnQgeyBJVG9waWMgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc25zJztcbmltcG9ydCB7IFByb3ZpZGVyIH0gZnJvbSAnYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QsIElDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IFNjYW5uZXJDdXN0b21SZXNvdXJjZVByb3BzIH0gZnJvbSAnLi9jdXN0b20tcmVzb3VyY2UtcHJvcHMnO1xuaW1wb3J0IHsgU2NhbkxvZ3NPdXRwdXQgfSBmcm9tICcuL3NjYW4tbG9ncy1vdXRwdXQnO1xuaW1wb3J0IHsgU2V2ZXJpdHksIFNjYW5uZXJzLCBJbWFnZUNvbmZpZ1NjYW5uZXJzIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogRmlsZSB0eXBlIGZvciBUcml2eUlnbm9yZSBmaWxlIHBhdGhcbiAqL1xuZXhwb3J0IGVudW0gVHJpdnlJZ25vcmVGaWxlVHlwZSB7XG4gIC8qKlxuICAgKiAudHJpdnlpZ25vcmUgZmlsZVxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vdHJpdnkuZGV2L2RvY3MvbGF0ZXN0L2NvbmZpZ3VyYXRpb24vZmlsdGVyaW5nLyN0cml2eWlnbm9yZVxuICAgKi9cbiAgVFJJVllJR05PUkUgPSAnVFJJVllJR05PUkUnLFxuXG4gIC8qKlxuICAgKiAudHJpdnlpZ25vcmUueWFtbCBmaWxlXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly90cml2eS5kZXYvZG9jcy9sYXRlc3QvY29uZmlndXJhdGlvbi9maWx0ZXJpbmcvI3RyaXZ5aWdub3JleWFtbFxuICAgKi9cbiAgVFJJVllJR05PUkVfWUFNTCA9ICdUUklWWUlHTk9SRV9ZQU1MJyxcbn1cblxuLyoqXG4gKiBVbmlvbi1saWtlIGNsYXNzIGZvciBzcGVjaWZ5aW5nIFRyaXZ5IGlnbm9yZSBjb25maWd1cmF0aW9uLlxuICpcbiAqIFlvdSBjYW4gZWl0aGVyIHNwZWNpZnkgaWdub3JlIHJ1bGVzIGlubGluZSwgb3IgcG9pbnQgdG8gYW4gZXhpc3RpbmcgaWdub3JlIGZpbGUuXG4gKi9cbmV4cG9ydCBjbGFzcyBUcml2eUlnbm9yZSB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IGlnbm9yZSBydWxlcyBpbmxpbmUgKGVxdWl2YWxlbnQgdG8gd3JpdGluZyBsaW5lcyBpbiBhIC50cml2eWlnbm9yZSBmaWxlKS5cbiAgICpcbiAgICogQHBhcmFtIHJ1bGVzIEVhY2ggZWxlbWVudCBjb3JyZXNwb25kcyB0byBvbmUgbGluZSBpbiB0aGUgLnRyaXZ5aWdub3JlIGZpbGUuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly90cml2eS5kZXYvZG9jcy9sYXRlc3QvY29uZmlndXJhdGlvbi9maWx0ZXJpbmcvI3RyaXZ5aWdub3JlXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21SdWxlcyhydWxlczogc3RyaW5nW10pOiBUcml2eUlnbm9yZSB7XG4gICAgcmV0dXJuIG5ldyBUcml2eUlnbm9yZShydWxlcyk7XG4gIH1cblxuICAvKipcbiAgICogU3BlY2lmeSB0aGUgcGF0aCB0byBhbiBleGlzdGluZyB0cml2eWlnbm9yZSBmaWxlLlxuICAgKlxuICAgKiBAcGFyYW0gcGF0aCBQYXRoIHRvIHRoZSBpZ25vcmUgZmlsZS5cbiAgICogQHBhcmFtIGZpbGVUeXBlIEZpbGUgZm9ybWF0LiBEZWZhdWx0cyB0byBgVHJpdnlJZ25vcmVGaWxlVHlwZS5UUklWWUlHTk9SRWAuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly90cml2eS5kZXYvZG9jcy9sYXRlc3QvY29uZmlndXJhdGlvbi9maWx0ZXJpbmcvI3RyaXZ5aWdub3JlXG4gICAqIEBzZWUgaHR0cHM6Ly90cml2eS5kZXYvZG9jcy9sYXRlc3QvY29uZmlndXJhdGlvbi9maWx0ZXJpbmcvI3RyaXZ5aWdub3JleWFtbFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tRmlsZVBhdGgoXG4gICAgcGF0aDogc3RyaW5nLFxuICAgIGZpbGVUeXBlOiBUcml2eUlnbm9yZUZpbGVUeXBlID0gVHJpdnlJZ25vcmVGaWxlVHlwZS5UUklWWUlHTk9SRSxcbiAgKTogVHJpdnlJZ25vcmUge1xuICAgIGNvbnN0IGNvbnRlbnQgPSByZWFkRmlsZVN5bmMocGF0aCwgJ3V0Zi04Jyk7XG4gICAgLy8gUGFzcyBsaW5lcyBhcy1pcyB3aXRob3V0IHN0cmlwcGluZyBjb21tZW50cyBvciBlbXB0eSBsaW5lc1xuICAgIC8vIGJlY2F1c2UgVHJpdnkgaXRzZWxmIGhhbmRsZXMgY29tbWVudCBsaW5lcyAoc3RhcnRpbmcgd2l0aCBgI2ApIGFuZCBlbXB0eSBsaW5lcyB3aGVuIHJlYWRpbmcgdGhlIGlnbm9yZSBmaWxlLlxuICAgIHJldHVybiBuZXcgVHJpdnlJZ25vcmUoY29udGVudC5zcGxpdCgnXFxuJyksIGZpbGVUeXBlKTtcbiAgfVxuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgcHVibGljIHJlYWRvbmx5IHJ1bGVzOiBzdHJpbmdbXSxcbiAgICBwdWJsaWMgcmVhZG9ubHkgZmlsZVR5cGU/OiBUcml2eUlnbm9yZUZpbGVUeXBlLFxuICApIHt9XG59XG5cbi8qKlxuICogRW51bSBmb3IgVGFyZ2V0IEltYWdlIFBsYXRmb3JtXG4gKi9cbmV4cG9ydCBjbGFzcyBUYXJnZXRJbWFnZVBsYXRmb3JtIHtcbiAgLyoqXG4gICAqIExpbnV4IEFNRDY0IHBsYXRmb3JtXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IExJTlVYX0FNRDY0ID0gbmV3IFRhcmdldEltYWdlUGxhdGZvcm0oJ2xpbnV4L2FtZDY0Jyk7XG5cbiAgLyoqXG4gICAqIExpbnV4IEFSTTY0IHBsYXRmb3JtXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IExJTlVYX0FSTTY0ID0gbmV3IFRhcmdldEltYWdlUGxhdGZvcm0oJ2xpbnV4L2FybTY0Jyk7XG5cbiAgLyoqXG4gICAqIEN1c3RvbSB2YWx1ZSBmb3IgdGFyZ2V0IGltYWdlIHBsYXRmb3JtXG4gICAqXG4gICAqIFRoZSB2YWx1ZSBzaG91bGQgYmUgaW4gdGhlIGZvcm1hdCBPUy9BcmNoaXRlY3R1cmUgZm9yIHRoZSBpbWFnZSwgc3VjaCBhcyBgbGludXgvYXJtNjRgLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjdXN0b20odmFsdWU6IHN0cmluZyk6IFRhcmdldEltYWdlUGxhdGZvcm0ge1xuICAgIHJldHVybiBuZXcgVGFyZ2V0SW1hZ2VQbGF0Zm9ybSh2YWx1ZSk7XG4gIH1cblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSB2YWx1ZTogc3RyaW5nKSB7fVxufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIEltYWdlU2Nhbm5lcldpdGhUcml2eVYyIENvbnN0cnVjdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbWFnZVNjYW5uZXJXaXRoVHJpdnlWMlByb3BzIHtcbiAgLyoqXG4gICAqIEltYWdlIFVSSSBmb3Igc2NhbiB0YXJnZXQuXG4gICAqL1xuICByZWFkb25seSBpbWFnZVVyaTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBSZXBvc2l0b3J5IGluY2x1ZGluZyB0aGUgaW1hZ2UgVVJJIGZvciBzY2FuIHRhcmdldC5cbiAgICpcbiAgICogQmVjYXVzZSBvZiBncmFudFB1bGwgdG8gQ3VzdG9tUmVzb3VyY2VMYW1iZGEuXG4gICAqL1xuICByZWFkb25seSByZXBvc2l0b3J5OiBJUmVwb3NpdG9yeTtcblxuICAvKipcbiAgICogVGhlIHVuZml4ZWQvdW5maXhhYmxlIHZ1bG5lcmFiaWxpdGllcyBtZWFuIHRoYXQgdGhlIHBhdGNoIGhhcyBub3QgeWV0IGJlZW4gcHJvdmlkZWQgb24gdGhlaXIgZGlzdHJpYnV0aW9uLlxuICAgKlxuICAgKiBUbyBoaWRlIHVuZml4ZWQvdW5maXhhYmxlIHZ1bG5lcmFiaWxpdGllcywgeW91IGNhbiB1c2UgdGhlIGAtLWlnbm9yZS11bmZpeGVkYCBmbGFnLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vdHJpdnkuZGV2L2RvY3MvbGF0ZXN0L3NjYW5uZXIvdnVsbmVyYWJpbGl0eS8jdW5maXhlZC12dWxuZXJhYmlsaXRpZXNcbiAgICovXG4gIHJlYWRvbmx5IGlnbm9yZVVuZml4ZWQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBTZXZlcml0eSBTZWxlY3Rpb25cbiAgICpcbiAgICogVGhlIHNldmVyaXR5IGlzIHRha2VuIGZyb20gdGhlIHNlbGVjdGVkIGRhdGEgc291cmNlIHNpbmNlIHRoZSBzZXZlcml0eSBmcm9tIHZlbmRvcnMgaXMgbW9yZSBhY2N1cmF0ZS5cbiAgICogVXNpbmcgQ1ZFLTIwMjMtMDQ2NCBhcyBhbiBleGFtcGxlLCB3aGlsZSBpdCBpcyByYXRlZCBhcyBcIkhJR0hcIiBpbiBOVkQsIFJlZCBIYXQgaGFzIG1hcmtlZCBpdHMgJ0ltcGFjdCcgYXMgXCJMb3dcIi4gQXMgYSByZXN1bHQsIFRyaXZ5IHdpbGwgZGlzcGxheSBpdCBhcyBcIkxvd1wiLlxuICAgKlxuICAgKiBUaGUgc2V2ZXJpdHkgZGVwZW5kcyBvbiB0aGUgY29tcGlsZSBvcHRpb24sIHRoZSBkZWZhdWx0IGNvbmZpZ3VyYXRpb24sIGV0Yy4gTlZEIGRvZXNuJ3Qga25vdyBob3cgdGhlIHZlbmRvciBkaXN0cmlidXRlcyB0aGUgc29mdHdhcmUuXG4gICAqIFJlZCBIYXQgZXZhbHVhdGVzIHRoZSBzZXZlcml0eSBtb3JlIGFjY3VyYXRlbHkuIFRoYXQncyB3aHkgVHJpdnkgcHJlZmVycyB2ZW5kb3Igc2NvcmVzIG92ZXIgTlZELlxuICAgKlxuICAgKiBJdCBkZWZhdWx0cyB0byBgQ1JJVElDQUxgIElOIFRISVMgQ09OU1RSVUNUIGZvciBzYWZldHkgaW4gQ0kvQ0QsIGJ1dCB0aGUgZGVmYXVsdCBjb25maWd1cmF0aW9uIG9mIFRyaXZ5IGlzIFwiQ1JJVElDQUwsSElHSCxNRURJVU0sTE9XLFVOS05PV05cIi5cbiAgICpcbiAgICogQGRlZmF1bHQgW1NldmVyaXR5LkNSSVRJQ0FMXVxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vdHJpdnkuZGV2L2RvY3MvbGF0ZXN0L3NjYW5uZXIvdnVsbmVyYWJpbGl0eS8jc2V2ZXJpdHktc2VsZWN0aW9uXG4gICAqL1xuICByZWFkb25seSBzZXZlcml0eT86IFNldmVyaXR5W107XG5cbiAgLyoqXG4gICAqIEVuYWJsZS9EaXNhYmxlIFNjYW5uZXJzXG4gICAqXG4gICAqIFlvdSBjYW4gZW5hYmxlL2Rpc2FibGUgc2Nhbm5lcnMgd2l0aCB0aGUgYHNjYW5uZXJzYC5cbiAgICpcbiAgICogRm9yIGV4YW1wbGUsIGNvbnRhaW5lciBpbWFnZSBzY2FubmluZyBlbmFibGVzIHZ1bG5lcmFiaWxpdHkgKFZVTE4pIGFuZCBzZWNyZXQgc2Nhbm5lcnMgKFNFQ1JFVCkgYnkgZGVmYXVsdC5cbiAgICogSWYgeW91IGRvbid0IG5lZWQgc2VjcmV0IHNjYW5uaW5nLCBpdCBjYW4gYmUgZGlzYWJsZWQgYnkgc3BlY2lmeWluZyBTY2FubmVycy5WVUxOIG9ubHkuXG4gICAqXG4gICAqIEBkZWZhdWx0IFtTZWN1cml0eS5WVUxOLFNjYW5uZXJzLlNFQ1JFVF1cbiAgICpcbiAgICogQHNlZSBodHRwczovL3RyaXZ5LmRldi9kb2NzL2xhdGVzdC9jb25maWd1cmF0aW9uL290aGVycy8jZW5hYmxlZGlzYWJsZS1zY2FubmVyc1xuICAgKi9cbiAgcmVhZG9ubHkgc2Nhbm5lcnM/OiBTY2FubmVyc1tdO1xuXG4gIC8qKlxuICAgKiBFbnVtIGZvciBJbWFnZUNvbmZpZ1NjYW5uZXJzXG4gICAqXG4gICAqIENvbnRhaW5lciBpbWFnZXMgaGF2ZSBjb25maWd1cmF0aW9uLiBkb2NrZXIgaW5zcGVjdCBhbmQgYGRvY2tlciBoaXN0b3J5YCBzaG93IHRoZSBpbmZvcm1hdGlvbiBhY2NvcmRpbmcgdG8gdGhlIGNvbmZpZ3VyYXRpb24uXG4gICAqIFRyaXZ5IHNjYW5zIHRoZSBjb25maWd1cmF0aW9uIG9mIGNvbnRhaW5lciBpbWFnZXMgZm9yXG4gICAqXG4gICAqIC0gTWlzY29uZmlndXJhdGlvbnNcbiAgICogLSBTZWNyZXRzXG4gICAqXG4gICAqIFRoZXkgYXJlIGRpc2FibGVkIGJ5IGRlZmF1bHQuIFlvdSBjYW4gZW5hYmxlIHRoZW0gd2l0aCBgaW1hZ2VDb25maWdTY2FubmVyc2AuXG4gICAqXG4gICAqIEBkZWZhdWx0IFtdXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly90cml2eS5kZXYvZG9jcy9sYXRlc3QvdGFyZ2V0L2NvbnRhaW5lcl9pbWFnZS8jY29udGFpbmVyLWltYWdlLW1ldGFkYXRhXG4gICAqL1xuICByZWFkb25seSBpbWFnZUNvbmZpZ1NjYW5uZXJzPzogSW1hZ2VDb25maWdTY2FubmVyc1tdO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGZhaWwgb24gdnVsbmVyYWJpbGl0aWVzIG9yIEVPTCAoRW5kIG9mIExpZmUpIGltYWdlc1xuICAgKlxuICAgKiBJZiBzZXQgdG8gYHRydWVgLCBUcml2eSBleGl0cyB3aXRoIGEgbm9uLXplcm8gZXhpdCBjb2RlIHdoZW4gdnVsbmVyYWJpbGl0aWVzIG9yIEVPTCBpbWFnZXMgYXJlIGRldGVjdGVkLlxuICAgKlxuICAgKiBJZiBzZXQgdG8gYGZhbHNlYCwgVHJpdnkgZXhpdHMgd2l0aCBhIHplcm8gZXhpdCBjb2RlIGV2ZW4gd2hlbiB2dWxuZXJhYmlsaXRpZXMgb3IgRU9MIGltYWdlcyBhcmUgZGV0ZWN0ZWQuXG4gICAqXG4gICAqIEl0IGRlZmF1bHRzIHRvIGB0cnVlYCBJTiBUSElTIENPTlNUUlVDVCBmb3Igc2FmZXR5IGluIENJL0NELiBJbiB0aGUgb3JpZ2luYWwgdHJpdnksIGl0IGlzIGBmYWxzZWAgKGV4aXQgY29kZSAwKS5cbiAgICpcbiAgICogKipOb3RlKio6IFdoZW4gYHNib21Gb3JtYXRgIGlzIHNwZWNpZmllZCBpbiBgc2NhbkxvZ3NPdXRwdXQuczMoKWAsIFNCT00gZ2VuZXJhdGlvbiBtb2RlIGlzIHVzZWQgaW5zdGVhZCBvZlxuICAgKiB2dWxuZXJhYmlsaXR5IHNjYW5uaW5nLiBJbiBTQk9NIG1vZGUsIFRyaXZ5IGFsd2F5cyBleGl0cyB3aXRoIGNvZGUgMCByZWdhcmRsZXNzIG9mIHRoaXMgc2V0dGluZywgYW5kXG4gICAqIG5vIFNOUyBub3RpZmljYXRpb25zIHdpbGwgYmUgc2VudCBldmVuIGlmIGB2dWxuc05vdGlmaWNhdGlvblRvcGljYCBpcyBjb25maWd1cmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly90cml2eS5kZXYvZG9jcy9sYXRlc3QvY29uZmlndXJhdGlvbi9vdGhlcnMvI2V4aXQtY29kZVxuICAgKi9cbiAgcmVhZG9ubHkgZmFpbE9uVnVsbmVyYWJpbGl0eT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIElnbm9yZSBydWxlcyBvciBpZ25vcmUgZmlsZSBmb3IgVHJpdnkuXG4gICAqXG4gICAqIFVzZSBgVHJpdnlJZ25vcmUuZnJvbVJ1bGVzKClgIHRvIHNwZWNpZnkgaW5saW5lIGlnbm9yZSBydWxlcyAoZXF1aXZhbGVudCB0byB3cml0aW5nIGxpbmVzXG4gICAqIGluIGEgYC50cml2eWlnbm9yZWAgZmlsZSksIG9yIGBUcml2eUlnbm9yZS5mcm9tRmlsZVBhdGgoKWAgdG8gcG9pbnQgdG8gYW4gZXhpc3RpbmcgaWdub3JlIGZpbGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gaWdub3JlIHJ1bGVzXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly90cml2eS5kZXYvZG9jcy9sYXRlc3QvY29uZmlndXJhdGlvbi9maWx0ZXJpbmcvI3RyaXZ5aWdub3JlXG4gICAqIEBzZWUgaHR0cHM6Ly90cml2eS5kZXYvZG9jcy9sYXRlc3QvY29uZmlndXJhdGlvbi9maWx0ZXJpbmcvI3RyaXZ5aWdub3JleWFtbFxuICAgKi9cbiAgcmVhZG9ubHkgdHJpdnlJZ25vcmU/OiBUcml2eUlnbm9yZTtcblxuICAvKipcbiAgICogTWVtb3J5IFNpemUgKE1CKSBmb3IgU2Nhbm5lciBMYW1iZGFcbiAgICpcbiAgICogWW91IGNhbiBzcGVjaWZ5IGJldHdlZW4gYDMwMDhgIGFuZCBgMTAyNDBgLlxuICAgKlxuICAgKiBJZiB0aGlzIENvbnN0cnVjdCBleGVjdXRpb24gdGVybWluYXRlcyBhYm5vcm1hbGx5IGR1ZSB0byBTSUdLSUxMLCB0cnkgYSBsYXJnZXIgc2l6ZS5cbiAgICpcbiAgICogRGVmYXVsdCB2YWx1ZSAoYDMwMDhgIE1CKSBpcyBNYXhpbXVtIExhbWJkYSBtZW1vcnkgc2l6ZSBmb3IgZGVmYXVsdCBBV1MgYWNjb3VudCB3aXRob3V0IHF1b3RhIGxpbWl0IGluY3JlYXNlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAzMDA4XG4gICAqL1xuICByZWFkb25seSBtZW1vcnlTaXplPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBTY2FuIEltYWdlIG9uIGEgc3BlY2lmaWMgQXJjaGl0ZWN0dXJlIGFuZCBPU1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRyaXZ5IGxvYWRzIGFuIGltYWdlIG9uIGEgYGxpbnV4L2FtZDY0YCBtYWNoaW5lLlxuICAgKi9cbiAgcmVhZG9ubHkgdGFyZ2V0SW1hZ2VQbGF0Zm9ybT86IFRhcmdldEltYWdlUGxhdGZvcm07XG5cbiAgLyoqXG4gICAqIFRoZSBTY2FubmVyIExhbWJkYSBmdW5jdGlvbidzIGRlZmF1bHQgbG9nIGdyb3VwXG4gICAqXG4gICAqIElmIHlvdSB1c2UgSW1hZ2VTY2FubmVyV2l0aFRyaXZ5VjIgY29uc3RydWN0IG11bHRpcGxlIHRpbWVzIGluIHRoZSBzYW1lIHN0YWNrLFxuICAgKiB5b3UgbXVzdCBzcGVjaWZ5IHRoZSBzYW1lIGxvZyBncm91cCBmb3IgZWFjaCBjb25zdHJ1Y3QuXG4gICAqXG4gICAqIFNlZSBgRGVmYXVsdCBMb2cgR3JvdXBgIHNlY3Rpb24gaW4gdGhlIFJFQURNRSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFNjYW5uZXIgTGFtYmRhIGNyZWF0ZXMgdGhlIGRlZmF1bHQgbG9nIGdyb3VwKGAvYXdzL2xhbWJkYS8ke2Z1bmN0aW9uTmFtZX1gKS5cbiAgICovXG4gIHJlYWRvbmx5IGRlZmF1bHRMb2dHcm91cD86IElMb2dHcm91cDtcblxuICAvKipcbiAgICogQ29uZmlndXJhdGlvbiBmb3Igc2NhbiBsb2dzIG91dHB1dFxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCBzY2FuIGxvZ3MgYXJlIG91dHB1dCB0byBkZWZhdWx0IGxvZyBncm91cCBjcmVhdGVkIGJ5IFNjYW5uZXIgTGFtYmRhLlxuICAgKlxuICAgKiBTcGVjaWZ5IHRoaXMgaWYgeW91IHdhbnQgdG8gc2VuZCBzY2FuIGxvZ3MgdG8gb3RoZXIgdGhhbiB0aGUgZGVmYXVsdCBsb2cgZ3JvdXAuXG4gICAqXG4gICAqICoqTm90ZSoqOiBDbG91ZFdhdGNoIExvZ3MgaGFzIGEgMSBNQiBwZXIgbG9nIGV2ZW50IGxpbWl0LiBMYXJnZSBzY2FuIHJlc3VsdHMgd2lsbCBiZVxuICAgKiBhdXRvbWF0aWNhbGx5IHNwbGl0IGludG8gbXVsdGlwbGUgZXZlbnRzIHdpdGggYFtwYXJ0IFgvWV1gIHByZWZpeGVzLiAqKkZvciBsYXJnZSBzY2FuXG4gICAqIHJlc3VsdHMsIHdlIHJlY29tbWVuZCB1c2luZyBTMyBvdXRwdXQqKiB0byBhdm9pZCBmcmFnbWVudGF0aW9uIGFuZCBtYWtlIGl0IGVhc2llciB0b1xuICAgKiB2aWV3IGNvbXBsZXRlIHJlc3VsdHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gc2NhbiBsb2dzIG91dHB1dCB0byBgZGVmYXVsdExvZ0dyb3VwYCBpZiBzcGVjaWZpZWQsIG90aGVyd2lzZSB0byB0aGUgZGVmYXVsdFxuICAgKiBsb2cgZ3JvdXAgY3JlYXRlZCBieSBTY2FubmVyIExhbWJkYS5cbiAgICovXG4gIHJlYWRvbmx5IHNjYW5Mb2dzT3V0cHV0PzogU2NhbkxvZ3NPdXRwdXQ7XG5cbiAgLyoqXG4gICAqIFN1cHByZXNzIGVycm9ycyBkdXJpbmcgcm9sbGJhY2sgc2Nhbm5lciBMYW1iZGEgZXhlY3V0aW9uXG4gICAqXG4gICAqIFdoZW4gaW1hZ2Ugc2Nhbm5pbmcgZmFpbHMsIENsb3VkRm9ybWF0aW9uIHRyaWdnZXJzIGEgcm9sbGJhY2sgYW5kIGV4ZWN1dGVzIHRoZSBwcmV2aW91c1xuICAgKiB2ZXJzaW9uIG9mIHRoZSBzY2FubmVyIExhbWJkYS4gSWYgdGhpcyBwcm9wZXJ0eSBpcyBzZXQgdG8gYHRydWVgLCB0aGUgcHJldmlvdXMgdmVyc2lvbiBvZlxuICAgKiB0aGUgc2Nhbm5lciBMYW1iZGEgd2lsbCBub3QgdGhyb3cgYW4gZXJyb3IsIGV2ZW4gaWYgdGhlIGltYWdlIHNjYW5uaW5nIGZvciB0aGUgcHJldmlvdXMgdmVyc2lvblxuICAgKiBmYWlscy5cbiAgICpcbiAgICogVGhpcyBhbGxvd3MgdGhlIHJvbGxiYWNrIHRvIGNvbXBsZXRlIHN1Y2Nlc3NmdWxseSwgYXZvaWRpbmcgUk9MTEJBQ0tfRkFJTEVEIHN0YXRlXG4gICAqIHdoZW4gaW1hZ2Ugc2Nhbm5pbmcgZmFpbHVyZXMgb2NjdXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHN1cHByZXNzRXJyb3JPblJvbGxiYWNrPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogU05TIHRvcGljIGZvciB2dWxuZXJhYmlsaXRpZXMgbm90aWZpY2F0aW9uXG4gICAqXG4gICAqIElmIHNwZWNpZmllZCwgYW4gU05TIHRvcGljIG5vdGlmaWNhdGlvbiB3aWxsIGJlIHNlbnQgd2hlbiB2dWxuZXJhYmlsaXRpZXMgb3IgRU9MIChFbmQgb2YgTGlmZSkgT1MgYXJlIGRldGVjdGVkLlxuICAgKlxuICAgKiBUaGUgbm90aWZpY2F0aW9uIGlzIHNlbnQgcmVnYXJkbGVzcyBvZiB0aGUgYGZhaWxPblZ1bG5lcmFiaWxpdHlgIHNldHRpbmcuXG4gICAqIFRoaXMgbWVhbnMgeW91IGNhbiBjaG9vc2UgdG8gcmVjZWl2ZSBub3RpZmljYXRpb25zIGV2ZW4gd2hlbiB5b3UgZG9uJ3Qgd2FudCB0aGUgZGVwbG95bWVudCB0byBmYWlsLlxuICAgKlxuICAgKiBZb3UgY2FuIHNwZWNpZnkgYW4gU05TIHRvcGljIGFzc29jaWF0ZWQgd2l0aCBBV1MgQ2hhdGJvdCwgYXMgbm90aWZpY2F0aW9ucyBhcmUgc2VudCBpbiBBV1MgQ2hhdGJvdCBtZXNzYWdlIGZvcm1hdC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBub3RpZmljYXRpb25cbiAgICovXG4gIHJlYWRvbmx5IHZ1bG5zTm90aWZpY2F0aW9uVG9waWM/OiBJVG9waWM7XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgdG8gYmxvY2sgaWYgdnVsbmVyYWJpbGl0aWVzIGFyZSBkZXRlY3RlZC5cbiAgICpcbiAgICogVGhpcyBpcyBlcXVpdmFsZW50IHRvIGNhbGxpbmcgYGNvbnN0cnVjdC5ub2RlLmFkZERlcGVuZGVuY3koaW1hZ2VTY2FubmVyKWAgZm9yIGVhY2ggY29uc3RydWN0LlxuICAgKlxuICAgKiBOb3RlOiBUaGlzIG9wdGlvbiBvbmx5IHdvcmtzIHdoZW4gYGZhaWxPblZ1bG5lcmFiaWxpdHlgIGlzIGB0cnVlYCAoZGVmYXVsdCkuXG4gICAqIElmIGBmYWlsT25WdWxuZXJhYmlsaXR5YCBpcyBzZXQgdG8gYGZhbHNlYCwgdGhlIHNjYW5uZXIgd2lsbCBub3QgZmFpbCBvbiB2dWxuZXJhYmlsaXRpZXMsXG4gICAqIGFuZCB0aGUgc3BlY2lmaWVkIGNvbnN0cnVjdHMgd2lsbCBub3QgYmUgYmxvY2tlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBjb25zdHJ1Y3RzIHRvIGJsb2NrXG4gICAqL1xuICByZWFkb25seSBibG9ja0NvbnN0cnVjdHM/OiBJQ29uc3RydWN0W107XG59XG5cbi8vIE1heGltdW0gTGFtYmRhIG1lbW9yeSBzaXplIGZvciBkZWZhdWx0IEFXUyBhY2NvdW50IHdpdGhvdXQgcXVvdGEgbGltaXQgaW5jcmVhc2VcbmNvbnN0IERFRkFVTFRfTUVNT1JZX1NJWkUgPSAzMDA4O1xuXG4vKipcbiAqIEEgQ29uc3RydWN0IHRoYXQgc2NhbnMgY29udGFpbmVyIGltYWdlcyB3aXRoIFRyaXZ5LlxuICogSXQgdXNlcyBhIExhbWJkYSBmdW5jdGlvbiBhcyBhIEN1c3RvbSBSZXNvdXJjZSBwcm92aWRlciB0byBydW4gVHJpdnkgYW5kIHNjYW4gY29udGFpbmVyIGltYWdlcy5cbiAqL1xuZXhwb3J0IGNsYXNzIEltYWdlU2Nhbm5lcldpdGhUcml2eVYyIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcHJpdmF0ZSByZWFkb25seSBkZWZhdWx0TG9nR3JvdXA/OiBJTG9nR3JvdXA7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEltYWdlU2Nhbm5lcldpdGhUcml2eVYyUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgaWYgKFxuICAgICAgcHJvcHMubWVtb3J5U2l6ZSAmJlxuICAgICAgIVRva2VuLmlzVW5yZXNvbHZlZChwcm9wcy5tZW1vcnlTaXplKSAmJlxuICAgICAgKHByb3BzLm1lbW9yeVNpemUgPCAzMDA4IHx8IHByb3BzLm1lbW9yeVNpemUgPiAxMDI0MClcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFlvdSBjYW4gc3BlY2lmeSBiZXR3ZWVuIFxcYDMwMDhcXGAgYW5kIFxcYDEwMjQwXFxgIGZvciBcXGBtZW1vcnlTaXplXFxgLCBnb3QgJHtwcm9wcy5tZW1vcnlTaXplfS5gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmRlZmF1bHRMb2dHcm91cCA9IHByb3BzLmRlZmF1bHRMb2dHcm91cDtcbiAgICBjb25zdCBsYW1iZGFQdXJwb3NlID0gJ0N1c3RvbTo6SW1hZ2VTY2FubmVyV2l0aFRyaXZ5VjJDdXN0b21SZXNvdXJjZUxhbWJkYSc7XG5cbiAgICBjb25zdCBjdXN0b21SZXNvdXJjZUxhbWJkYSA9IG5ldyBTaW5nbGV0b25GdW5jdGlvbih0aGlzLCAnQ3VzdG9tUmVzb3VyY2VMYW1iZGEnLCB7XG4gICAgICB1dWlkOiAnY2MzYjQxYjUtNDcwMS1kODZmLWZlMjQtM2EwNGY0YTU3M2YxJyxcbiAgICAgIGxhbWJkYVB1cnBvc2UsXG4gICAgICBydW50aW1lOiBSdW50aW1lLkZST01fSU1BR0UsXG4gICAgICBoYW5kbGVyOiBIYW5kbGVyLkZST01fSU1BR0UsXG4gICAgICBjb2RlOiBBc3NldENvZGUuZnJvbUFzc2V0SW1hZ2Uoam9pbihfX2Rpcm5hbWUsICcuLi9hc3NldHMvbGFtYmRhJyksIHtcbiAgICAgICAgcGxhdGZvcm06IFBsYXRmb3JtLkxJTlVYX0FSTTY0LFxuICAgICAgICBpZ25vcmVNb2RlOiBJZ25vcmVNb2RlLkRPQ0tFUixcbiAgICAgIH0pLFxuICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuQVJNXzY0LFxuICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcyg5MDApLFxuICAgICAgcmV0cnlBdHRlbXB0czogMCxcbiAgICAgIG1lbW9yeVNpemU6IHByb3BzLm1lbW9yeVNpemUgPz8gREVGQVVMVF9NRU1PUllfU0laRSxcbiAgICAgIGVwaGVtZXJhbFN0b3JhZ2VTaXplOiBTaXplLmdpYmlieXRlcygxMCksIC8vIGZvciBjYXNlcyB0aGF0IG5lZWQgdG8gdXBkYXRlIHRyaXZ5IERCOiAvdG1wL3RyaXZ5L2RiL3RyaXZ5LmRiXG4gICAgICBsb2dHcm91cDogdGhpcy5kZWZhdWx0TG9nR3JvdXAsXG4gICAgfSk7XG5cbiAgICBwcm9wcy5yZXBvc2l0b3J5LmdyYW50UHVsbChjdXN0b21SZXNvdXJjZUxhbWJkYSk7XG5cbiAgICBpZiAocHJvcHMudnVsbnNOb3RpZmljYXRpb25Ub3BpYykge1xuICAgICAgcHJvcHMudnVsbnNOb3RpZmljYXRpb25Ub3BpYy5ncmFudFB1Ymxpc2goY3VzdG9tUmVzb3VyY2VMYW1iZGEpO1xuICAgIH1cblxuICAgIC8vIEdyYW50IENsb3VkRm9ybWF0aW9uIERlc2NyaWJlU3RhY2tzIHBlcm1pc3Npb24gZm9yIHJvbGxiYWNrIGRldGVjdGlvbiB3aGVuIHN1cHByZXNzRXJyb3JPblJvbGxiYWNrIGlzIGVuYWJsZWRcbiAgICBjb25zdCBzdXBwcmVzc0Vycm9yT25Sb2xsYmFjayA9IHByb3BzLnN1cHByZXNzRXJyb3JPblJvbGxiYWNrID8/IHRydWU7XG4gICAgaWYgKHN1cHByZXNzRXJyb3JPblJvbGxiYWNrKSB7XG4gICAgICBjdXN0b21SZXNvdXJjZUxhbWJkYS5hZGRUb1JvbGVQb2xpY3koXG4gICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFsnY2xvdWRmb3JtYXRpb246RGVzY3JpYmVTdGFja3MnXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFtTdGFjay5vZih0aGlzKS5zdGFja0lkXSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIElmIG11bHRpcGxlIEltYWdlU2Nhbm5lcldpdGhUcml2eVYyIGNvbnN0cnVjdHMgaW4gdGhlIHNhbWUgc3RhY2sgaGF2ZSBkaWZmZXJlbnQgZGVmYXVsdCBsb2cgZ3JvdXBzLCBhZGQgYSB3YXJuaW5nIGFubm90YXRpb24uXG4gICAgQXNwZWN0cy5vZihTdGFjay5vZih0aGlzKSkuYWRkKHtcbiAgICAgIHZpc2l0OiAobm9kZSkgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgbm9kZSBpbnN0YW5jZW9mIEltYWdlU2Nhbm5lcldpdGhUcml2eVYyICYmXG4gICAgICAgICAgbm9kZS5fZGVmYXVsdExvZ0dyb3VwPy5ub2RlLnBhdGggIT09IHRoaXMuZGVmYXVsdExvZ0dyb3VwPy5ub2RlLnBhdGhcbiAgICAgICAgKSB7XG4gICAgICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkV2FybmluZ1YyKFxuICAgICAgICAgICAgJ0BpbWFnZS1zY2FubmVyLXdpdGgtdHJpdnk6ZHVwbGljYXRlTGFtYmRhRGVmYXVsdExvZ0dyb3VwJyxcbiAgICAgICAgICAgIFwiWW91IGhhdmUgdG8gc2V0IHRoZSBzYW1lIGxvZyBncm91cCBmb3IgJ2RlZmF1bHRMb2dHcm91cCcgZm9yIGVhY2ggSW1hZ2VTY2FubmVyV2l0aFRyaXZ5VjIgY29uc3RydWN0IGluIHRoZSBzYW1lIHN0YWNrLlwiLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCBpbWFnZVNjYW5uZXJQcm92aWRlciA9IG5ldyBQcm92aWRlcih0aGlzLCAnUHJvdmlkZXInLCB7XG4gICAgICBvbkV2ZW50SGFuZGxlcjogY3VzdG9tUmVzb3VyY2VMYW1iZGEsXG4gICAgfSk7XG5cbiAgICBjb25zdCBpbWFnZVNjYW5uZXJQcm9wZXJ0aWVzOiBTY2FubmVyQ3VzdG9tUmVzb3VyY2VQcm9wcyA9IHtcbiAgICAgIGFkZHI6IHRoaXMubm9kZS5hZGRyLFxuICAgICAgaW1hZ2VVcmk6IHByb3BzLmltYWdlVXJpLFxuICAgICAgaWdub3JlVW5maXhlZDogU3RyaW5nKHByb3BzLmlnbm9yZVVuZml4ZWQgPz8gZmFsc2UpLFxuICAgICAgc2V2ZXJpdHk6IHByb3BzLnNldmVyaXR5ID8/IFtTZXZlcml0eS5DUklUSUNBTF0sXG4gICAgICBzY2FubmVyczogcHJvcHMuc2Nhbm5lcnMgPz8gW10sXG4gICAgICBpbWFnZUNvbmZpZ1NjYW5uZXJzOiBwcm9wcy5pbWFnZUNvbmZpZ1NjYW5uZXJzID8/IFtdLFxuICAgICAgZmFpbE9uVnVsbmVyYWJpbGl0eTogU3RyaW5nKHByb3BzLmZhaWxPblZ1bG5lcmFiaWxpdHkgPz8gdHJ1ZSksXG4gICAgICB0cml2eUlnbm9yZTogcHJvcHMudHJpdnlJZ25vcmU/LnJ1bGVzID8/IFtdLFxuICAgICAgdHJpdnlJZ25vcmVGaWxlVHlwZTogcHJvcHMudHJpdnlJZ25vcmU/LmZpbGVUeXBlLFxuICAgICAgcGxhdGZvcm06IHByb3BzLnRhcmdldEltYWdlUGxhdGZvcm0/LnZhbHVlID8/ICcnLFxuICAgICAgb3V0cHV0OiBwcm9wcy5zY2FuTG9nc091dHB1dD8uYmluZChjdXN0b21SZXNvdXJjZUxhbWJkYSksXG4gICAgICBzdXBwcmVzc0Vycm9yT25Sb2xsYmFjazogU3RyaW5nKHN1cHByZXNzRXJyb3JPblJvbGxiYWNrKSxcbiAgICAgIHZ1bG5zVG9waWNBcm46IHByb3BzLnZ1bG5zTm90aWZpY2F0aW9uVG9waWM/LnRvcGljQXJuLFxuICAgICAgZGVmYXVsdExvZ0dyb3VwTmFtZTpcbiAgICAgICAgdGhpcy5kZWZhdWx0TG9nR3JvdXA/LmxvZ0dyb3VwTmFtZSA/PyBgL2F3cy9sYW1iZGEvJHtjdXN0b21SZXNvdXJjZUxhbWJkYS5mdW5jdGlvbk5hbWV9YCxcbiAgICB9O1xuXG4gICAgbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIHJlc291cmNlVHlwZTogJ0N1c3RvbTo6SW1hZ2VTY2FubmVyV2l0aFRyaXZ5VjInLFxuICAgICAgcHJvcGVydGllczogaW1hZ2VTY2FubmVyUHJvcGVydGllcyxcbiAgICAgIHNlcnZpY2VUb2tlbjogaW1hZ2VTY2FubmVyUHJvdmlkZXIuc2VydmljZVRva2VuLFxuICAgIH0pO1xuXG4gICAgLy8gQmxvY2sgY29uc3RydWN0cyBpZiB2dWxuZXJhYmlsaXRpZXMgYXJlIGRldGVjdGVkXG4gICAgcHJvcHMuYmxvY2tDb25zdHJ1Y3RzPy5mb3JFYWNoKChjb25zdHJ1Y3QpID0+IHtcbiAgICAgIGNvbnN0cnVjdC5ub2RlLmFkZERlcGVuZGVuY3kodGhpcyk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIGdldCBfZGVmYXVsdExvZ0dyb3VwKCk6IElMb2dHcm91cCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuZGVmYXVsdExvZ0dyb3VwO1xuICB9XG59XG4iXX0=