image-scanner-with-trivy
Version:
Scan container images with Trivy in CDK deployment
139 lines • 33.9 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImageScannerWithTrivy = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
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 aws_logs_1 = require("aws-cdk-lib/aws-logs");
const custom_resources_1 = require("aws-cdk-lib/custom-resources");
const constructs_1 = require("constructs");
const types_1 = require("./types");
// 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.
*
* @deprecated Use ImageScannerWithTrivyV2 instead. This will be removed in the next major version.
*/
class ImageScannerWithTrivy 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}.`);
}
const lambdaPurpose = 'Custom::ImageScannerWithTrivyCustomResourceLambda';
const customResourceLambda = new aws_lambda_1.SingletonFunction(this, 'CustomResourceLambda', {
uuid: '470b6343-d267-f753-226c-1e99f09f319a',
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,
// exclude node_modules
// because the native binary of the installed esbuild changes depending on the cpu architecture
// and the hash value of the image asset changes depending on the execution environment.
exclude: ['node_modules'],
}),
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
});
props.repository.grantPull(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],
}));
}
const customResourceLambdaLogGroupConstructName = `DefaultLogGroupFor${lambdaPurpose}`;
this.validateLambdaDefaultLogGroupOptions(customResourceLambdaLogGroupConstructName, props);
if (props.defaultLogGroupRemovalPolicy || props.defaultLogGroupRetentionDays) {
this.ensureLambdaDefaultLogGroup(customResourceLambda, customResourceLambdaLogGroupConstructName, props);
}
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 ?? [],
exitCode: props.exitCode ?? 1, // TODO: Remove exitCode and exitOnEol properties in the next major version, as they are now controlled by failOnVulnerability.
exitOnEol: props.exitOnEol ?? 1, // TODO: Remove exitCode and exitOnEol properties in the next major version, as they are now controlled by failOnVulnerability.
failOnVulnerability: 'true', // dummy value for v2 property
trivyIgnore: props.trivyIgnore ?? [],
platform: props.platform ?? '',
output: props.scanLogsOutput?.bind(customResourceLambda),
suppressErrorOnRollback: String(suppressErrorOnRollback),
defaultLogGroupName: `/aws/lambda/${customResourceLambda.functionName}`,
};
new aws_cdk_lib_1.CustomResource(this, 'Resource', {
resourceType: 'Custom::ImageScannerWithTrivy',
properties: imageScannerProperties,
serviceToken: imageScannerProvider.serviceToken,
});
}
/**
* Validates that specified default log group options are the same for existing default log group.
*/
validateLambdaDefaultLogGroupOptions(logGroupConstructName, props) {
const existing = aws_cdk_lib_1.Stack.of(this).node.tryFindChild(logGroupConstructName);
if (!existing)
return;
const cfnLogGroup = existing.node.defaultChild;
if (!this.isSameResourceDeletionBehavior(props.defaultLogGroupRemovalPolicy, cfnLogGroup.cfnOptions.deletionPolicy) ||
cfnLogGroup.retentionInDays !== props.defaultLogGroupRetentionDays) {
aws_cdk_lib_1.Annotations.of(this).addWarningV2('@image-scanner-with-trivy:duplicateLambdaDefaultLogGroupOptions', "You have to set the same values for 'defaultLogGroupRemovalPolicy' and 'defaultLogGroupRetentionDays' for each ImageScannerWithTrivy construct in the same stack.");
}
}
/**
* Creates the default log group for Scanner Lambda if it does not exist.
*
* This method checks if the default log group for Scanner Lambda exists in children of the stack construct.
* If it does not exist, it creates the default log group for Scanner Lambda as a child of the stack construct.
*/
ensureLambdaDefaultLogGroup(singletonFunction, logGroupConstructName, props) {
const existing = aws_cdk_lib_1.Stack.of(this).node.tryFindChild(logGroupConstructName);
if (existing) {
return existing;
}
return new aws_logs_1.LogGroup(aws_cdk_lib_1.Stack.of(this), logGroupConstructName, {
logGroupName: `/aws/lambda/${singletonFunction.functionName}`,
retention: props.defaultLogGroupRetentionDays,
removalPolicy: props.defaultLogGroupRemovalPolicy,
});
}
isSameResourceDeletionBehavior(removalPolicy, deletionPolicy) {
switch (removalPolicy) {
case aws_cdk_lib_1.RemovalPolicy.DESTROY:
return deletionPolicy === aws_cdk_lib_1.CfnDeletionPolicy.DELETE;
case aws_cdk_lib_1.RemovalPolicy.RETAIN:
return deletionPolicy === aws_cdk_lib_1.CfnDeletionPolicy.RETAIN;
case aws_cdk_lib_1.RemovalPolicy.SNAPSHOT:
return deletionPolicy === aws_cdk_lib_1.CfnDeletionPolicy.SNAPSHOT;
case aws_cdk_lib_1.RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE:
return deletionPolicy === aws_cdk_lib_1.CfnDeletionPolicy.RETAIN_EXCEPT_ON_CREATE;
case undefined:
return deletionPolicy === undefined;
default:
return removalPolicy;
}
}
}
exports.ImageScannerWithTrivy = ImageScannerWithTrivy;
_a = JSII_RTTI_SYMBOL_1;
ImageScannerWithTrivy[_a] = { fqn: "image-scanner-with-trivy.ImageScannerWithTrivy", version: "2.4.3" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2Utc2Nhbm5lci13aXRoLXRyaXZ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ltYWdlLXNjYW5uZXItd2l0aC10cml2eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLCtCQUE0QjtBQUM1Qiw2Q0FTcUI7QUFFckIsK0RBQXNEO0FBQ3RELGlEQUFzRDtBQUN0RCx1REFNZ0M7QUFDaEMsbURBQTRFO0FBQzVFLG1FQUF3RDtBQUN4RCwyQ0FBdUM7QUFHdkMsbUNBQWtFO0FBdU5sRSxrRkFBa0Y7QUFDbEYsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUM7QUFFakM7Ozs7O0dBS0c7QUFDSCxNQUFhLHFCQUFzQixTQUFRLHNCQUFTO0lBQ2xELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBaUM7UUFDekUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixJQUNFLEtBQUssQ0FBQyxVQUFVO1lBQ2hCLENBQUMsbUJBQUssQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQztZQUNyQyxDQUFDLEtBQUssQ0FBQyxVQUFVLEdBQUcsSUFBSSxJQUFJLEtBQUssQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLEVBQ3JELENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUNiLDBFQUEwRSxLQUFLLENBQUMsVUFBVSxHQUFHLENBQzlGLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQUcsbURBQW1ELENBQUM7UUFDMUUsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLDhCQUFpQixDQUFDLElBQUksRUFBRSxzQkFBc0IsRUFBRTtZQUMvRSxJQUFJLEVBQUUsc0NBQXNDO1lBQzVDLGFBQWE7WUFDYixPQUFPLEVBQUUsb0JBQU8sQ0FBQyxVQUFVO1lBQzNCLE9BQU8sRUFBRSxvQkFBTyxDQUFDLFVBQVU7WUFDM0IsSUFBSSxFQUFFLHNCQUFTLENBQUMsY0FBYyxDQUFDLElBQUEsV0FBSSxF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YSxFQUFFLEtBQUssQ0FBQyw0QkFBNEI7U0FDbEQsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLDhCQUE4QixDQUNwQyxhQUE2QixFQUM3QixjQUFrQztRQUVsQyxRQUFRLGFBQWEsRUFBRSxDQUFDO1lBQ3RCLEtBQUssMkJBQWEsQ0FBQyxPQUFPO2dCQUN4QixPQUFPLGNBQWMsS0FBSywrQkFBaUIsQ0FBQyxNQUFNLENBQUM7WUFDckQsS0FBSywyQkFBYSxDQUFDLE1BQU07Z0JBQ3ZCLE9BQU8sY0FBYyxLQUFLLCtCQUFpQixDQUFDLE1BQU0sQ0FBQztZQUNyRCxLQUFLLDJCQUFhLENBQUMsUUFBUTtnQkFDekIsT0FBTyxjQUFjLEtBQUssK0JBQWlCLENBQUMsUUFBUSxDQUFDO1lBQ3ZELEtBQUssMkJBQWEsQ0FBQywwQkFBMEI7Z0JBQzNDLE9BQU8sY0FBYyxLQUFLLCtCQUFpQixDQUFDLHVCQUF1QixDQUFDO1lBQ3RFLEtBQUssU0FBUztnQkFDWixPQUFPLGNBQWMsS0FBSyxTQUFTLENBQUM7WUFDdEM7Z0JBQ0UsT0FBTyxhQUE2QixDQUFDO1FBQ3pDLENBQUM7SUFDSCxDQUFDOztBQTdKSCxzREE4SkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBqb2luIH0gZnJvbSAncGF0aCc7XG5pbXBvcnQge1xuICBBbm5vdGF0aW9ucyxcbiAgQ2ZuRGVsZXRpb25Qb2xpY3ksXG4gIEN1c3RvbVJlc291cmNlLFxuICBEdXJhdGlvbixcbiAgUmVtb3ZhbFBvbGljeSxcbiAgU2l6ZSxcbiAgU3RhY2ssXG4gIFRva2VuLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBJUmVwb3NpdG9yeSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lY3InO1xuaW1wb3J0IHsgUGxhdGZvcm0gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWNyLWFzc2V0cyc7XG5pbXBvcnQgeyBQb2xpY3lTdGF0ZW1lbnQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7XG4gIEFyY2hpdGVjdHVyZSxcbiAgQXNzZXRDb2RlLFxuICBIYW5kbGVyLFxuICBSdW50aW1lLFxuICBTaW5nbGV0b25GdW5jdGlvbixcbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBDZm5Mb2dHcm91cCwgTG9nR3JvdXAsIFJldGVudGlvbkRheXMgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG5pbXBvcnQgeyBQcm92aWRlciB9IGZyb20gJ2F3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXMnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBTY2FubmVyQ3VzdG9tUmVzb3VyY2VQcm9wcyB9IGZyb20gJy4vY3VzdG9tLXJlc291cmNlLXByb3BzJztcbmltcG9ydCB7IFNjYW5Mb2dzT3V0cHV0IH0gZnJvbSAnLi9zY2FuLWxvZ3Mtb3V0cHV0JztcbmltcG9ydCB7IFNldmVyaXR5LCBTY2FubmVycywgSW1hZ2VDb25maWdTY2FubmVycyB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIEltYWdlU2Nhbm5lcldpdGhUcml2eSBDb25zdHJ1Y3QuXG4gKlxuICogQGRlcHJlY2F0ZWQgVXNlIEltYWdlU2Nhbm5lcldpdGhUcml2eVYyUHJvcHMgaW5zdGVhZC4gVGhpcyB3aWxsIGJlIHJlbW92ZWQgaW4gdGhlIG5leHQgbWFqb3IgdmVyc2lvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbWFnZVNjYW5uZXJXaXRoVHJpdnlQcm9wcyB7XG4gIC8qKlxuICAgKiBJbWFnZSBVUkkgZm9yIHNjYW4gdGFyZ2V0LlxuICAgKi9cbiAgcmVhZG9ubHkgaW1hZ2VVcmk6IHN0cmluZztcblxuICAvKipcbiAgICogUmVwb3NpdG9yeSBpbmNsdWRpbmcgdGhlIGltYWdlIFVSSSBmb3Igc2NhbiB0YXJnZXQuXG4gICAqXG4gICAqIEJlY2F1c2Ugb2YgZ3JhbnRQdWxsIHRvIEN1c3RvbVJlc291cmNlTGFtYmRhLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVwb3NpdG9yeTogSVJlcG9zaXRvcnk7XG5cbiAgLyoqXG4gICAqIFRoZSB1bmZpeGVkL3VuZml4YWJsZSB2dWxuZXJhYmlsaXRpZXMgbWVhbiB0aGF0IHRoZSBwYXRjaCBoYXMgbm90IHlldCBiZWVuIHByb3ZpZGVkIG9uIHRoZWlyIGRpc3RyaWJ1dGlvbi5cbiAgICpcbiAgICogVG8gaGlkZSB1bmZpeGVkL3VuZml4YWJsZSB2dWxuZXJhYmlsaXRpZXMsIHlvdSBjYW4gdXNlIHRoZSBgLS1pZ25vcmUtdW5maXhlZGAgZmxhZy5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICpcbiAgICogQHNlZSBodHRwczovL2FxdWFzZWN1cml0eS5naXRodWIuaW8vdHJpdnkvbGF0ZXN0L2RvY3Mvc2Nhbm5lci92dWxuZXJhYmlsaXR5LyN1bmZpeGVkLXZ1bG5lcmFiaWxpdGllc1xuICAgKi9cbiAgcmVhZG9ubHkgaWdub3JlVW5maXhlZD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFNldmVyaXR5IFNlbGVjdGlvblxuICAgKlxuICAgKiBUaGUgc2V2ZXJpdHkgaXMgdGFrZW4gZnJvbSB0aGUgc2VsZWN0ZWQgZGF0YSBzb3VyY2Ugc2luY2UgdGhlIHNldmVyaXR5IGZyb20gdmVuZG9ycyBpcyBtb3JlIGFjY3VyYXRlLlxuICAgKiBVc2luZyBDVkUtMjAyMy0wNDY0IGFzIGFuIGV4YW1wbGUsIHdoaWxlIGl0IGlzIHJhdGVkIGFzIFwiSElHSFwiIGluIE5WRCwgUmVkIEhhdCBoYXMgbWFya2VkIGl0cyAnSW1wYWN0JyBhcyBcIkxvd1wiLiBBcyBhIHJlc3VsdCwgVHJpdnkgd2lsbCBkaXNwbGF5IGl0IGFzIFwiTG93XCIuXG4gICAqXG4gICAqIFRoZSBzZXZlcml0eSBkZXBlbmRzIG9uIHRoZSBjb21waWxlIG9wdGlvbiwgdGhlIGRlZmF1bHQgY29uZmlndXJhdGlvbiwgZXRjLiBOVkQgZG9lc24ndCBrbm93IGhvdyB0aGUgdmVuZG9yIGRpc3RyaWJ1dGVzIHRoZSBzb2Z0d2FyZS5cbiAgICogUmVkIEhhdCBldmFsdWF0ZXMgdGhlIHNldmVyaXR5IG1vcmUgYWNjdXJhdGVseS4gVGhhdCdzIHdoeSBUcml2eSBwcmVmZXJzIHZlbmRvciBzY29yZXMgb3ZlciBOVkQuXG4gICAqXG4gICAqIEl0IGRlZmF1bHRzIHRvIGBDUklUSUNBTGAgSU4gVEhJUyBDT05TVFJVQ1QgZm9yIHNhZmV0eSBpbiBDSS9DRCwgYnV0IHRoZSBkZWZhdWx0IGNvbmZpZ3VyYXRpb24gb2YgVHJpdnkgaXMgXCJDUklUSUNBTCxISUdILE1FRElVTSxMT1csVU5LTk9XTlwiLlxuICAgKlxuICAgKiBAZGVmYXVsdCBbU2V2ZXJpdHkuQ1JJVElDQUxdXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9hcXVhc2VjdXJpdHkuZ2l0aHViLmlvL3RyaXZ5L2xhdGVzdC9kb2NzL3NjYW5uZXIvdnVsbmVyYWJpbGl0eS8jc2V2ZXJpdHktc2VsZWN0aW9uXG4gICAqL1xuICByZWFkb25seSBzZXZlcml0eT86IFNldmVyaXR5W107XG5cbiAgLyoqXG4gICAqIEVuYWJsZS9EaXNhYmxlIFNjYW5uZXJzXG4gICAqXG4gICAqIFlvdSBjYW4gZW5hYmxlL2Rpc2FibGUgc2Nhbm5lcnMgd2l0aCB0aGUgYHNjYW5uZXJzYC5cbiAgICpcbiAgICogRm9yIGV4YW1wbGUsIGNvbnRhaW5lciBpbWFnZSBzY2FubmluZyBlbmFibGVzIHZ1bG5lcmFiaWxpdHkgKFZVTE4pIGFuZCBzZWNyZXQgc2Nhbm5lcnMgKFNFQ1JFVCkgYnkgZGVmYXVsdC5cbiAgICogSWYgeW91IGRvbid0IG5lZWQgc2VjcmV0IHNjYW5uaW5nLCBpdCBjYW4gYmUgZGlzYWJsZWQgYnkgc3BlY2lmeWluZyBTY2FubmVycy5WVUxOIG9ubHkuXG4gICAqXG4gICAqIEBkZWZhdWx0IFtTZWN1cml0eS5WVUxOLFNjYW5uZXJzLlNFQ1JFVF1cbiAgICpcbiAgICogQHNlZSBodHRwczovL2FxdWFzZWN1cml0eS5naXRodWIuaW8vdHJpdnkvbGF0ZXN0L2RvY3MvY29uZmlndXJhdGlvbi9vdGhlcnMvI2VuYWJsZWRpc2FibGUtc2Nhbm5lcnNcbiAgICovXG4gIHJlYWRvbmx5IHNjYW5uZXJzPzogU2Nhbm5lcnNbXTtcblxuICAvKipcbiAgICogRW51bSBmb3IgSW1hZ2VDb25maWdTY2FubmVyc1xuICAgKlxuICAgKiBDb250YWluZXIgaW1hZ2VzIGhhdmUgY29uZmlndXJhdGlvbi4gZG9ja2VyIGluc3BlY3QgYW5kIGBkb2NrZXIgaGlzdG9yeWAgc2hvdyB0aGUgaW5mb3JtYXRpb24gYWNjb3JkaW5nIHRvIHRoZSBjb25maWd1cmF0aW9uLlxuICAgKiBUcml2eSBzY2FucyB0aGUgY29uZmlndXJhdGlvbiBvZiBjb250YWluZXIgaW1hZ2VzIGZvclxuICAgKlxuICAgKiAtIE1pc2NvbmZpZ3VyYXRpb25zXG4gICAqIC0gU2VjcmV0c1xuICAgKlxuICAgKiBUaGV5IGFyZSBkaXNhYmxlZCBieSBkZWZhdWx0LiBZb3UgY2FuIGVuYWJsZSB0aGVtIHdpdGggYGltYWdlQ29uZmlnU2Nhbm5lcnNgLlxuICAgKlxuICAgKiBAZGVmYXVsdCBbXVxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vYXF1YXNlY3VyaXR5LmdpdGh1Yi5pby90cml2eS9sYXRlc3QvZG9jcy90YXJnZXQvY29udGFpbmVyX2ltYWdlLyNjb250YWluZXItaW1hZ2UtbWV0YWRhdGFcbiAgICovXG4gIHJlYWRvbmx5IGltYWdlQ29uZmlnU2Nhbm5lcnM/OiBJbWFnZUNvbmZpZ1NjYW5uZXJzW107XG5cbiAgLyoqXG4gICAqIEV4aXQgQ29kZVxuICAgKlxuICAgKiBVc2UgdGhlIGBleGl0Q29kZWAgb3B0aW9uIGlmIHlvdSB3YW50IHRvIGV4aXQgd2l0aCBhIG5vbi16ZXJvIGV4aXQgY29kZS5cbiAgICpcbiAgICogWW91IGNhbiBzcGVjaWZ5IDAgaWYgeW91IGRvIG5vdCB3YW50IHRvIGV4aXQgZXZlbiB3aGVuIHZ1bG5lcmFiaWxpdGllcyBhcmUgZGV0ZWN0ZWQuXG4gICAqXG4gICAqIEl0IGRlZmF1bHRzIHRvIDEgSU4gVEhJUyBDT05TVFJVQ1QgZm9yIHNhZmV0eSBpbiBDSS9DRC4gSW4gdGhlIG9yaWdpbmFsIHRyaXZ5LCBpdCBpcyAwLlxuICAgKlxuICAgKiBAZGVmYXVsdCAxXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9hcXVhc2VjdXJpdHkuZ2l0aHViLmlvL3RyaXZ5L2xhdGVzdC9kb2NzL2NvbmZpZ3VyYXRpb24vb3RoZXJzLyNleGl0LWNvZGVcbiAgICovXG4gIHJlYWRvbmx5IGV4aXRDb2RlPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBFeGl0IG9uIEVPTFxuICAgKlxuICAgKiBTb21ldGltZXMgeW91IG1heSBzdXJwcmlzaW5nbHkgZ2V0IDAgdnVsbmVyYWJpbGl0aWVzIGluIGFuIG9sZCBpbWFnZTpcbiAgICogIC0gRW5hYmxpbmcgLS1pZ25vcmUtdW5maXhlZCBvcHRpb24gd2hpbGUgYWxsIHBhY2thZ2VzIGhhdmUgbm8gZml4ZWQgdmVyc2lvbnMuXG4gICAqICAtIFNjYW5uaW5nIGEgcmF0aGVyIG91dGRhdGVkIE9TIChlLmcuIFVidW50dSAxMC4wNCkuXG4gICAqXG4gICAqIEFuIE9TIGF0IHRoZSBlbmQgb2Ygc2VydmljZS9saWZlIChFT0wpIHVzdWFsbHkgZ2V0cyBpbnRvIHRoaXMgc2l0dWF0aW9uLCB3aGljaCBpcyBkZWZpbml0ZWx5IGZ1bGwgb2YgdnVsbmVyYWJpbGl0aWVzLlxuICAgKiBgZXhpdE9uRW9sYCBjYW4gZmFpbCBzY2FubmluZyBvbiBFT0wgT1Mgd2l0aCBhIG5vbi16ZXJvIGNvZGUuXG4gICAqXG4gICAqIEl0IGRlZmF1bHRzIHRvIDEgSU4gVEhJUyBDT05TVFJVQ1QgZm9yIHNhZmV0eSBpbiBDSS9DRC4gSW4gdGhlIG9yaWdpbmFsIHRyaXZ5LCBpdCBpcyAwLlxuICAgKlxuICAgKiBAZGVmYXVsdCAxXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9hcXVhc2VjdXJpdHkuZ2l0aHViLmlvL3RyaXZ5L2xhdGVzdC9kb2NzL2NvbmZpZ3VyYXRpb24vb3RoZXJzLyNleGl0LW9uLWVvbFxuICAgKi9cbiAgcmVhZG9ubHkgZXhpdE9uRW9sPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBCeSBGaW5kaW5nIElEc1xuICAgKlxuICAgKiBUaGUgaWdub3JlIHJ1bGVzIHdyaXR0ZW4gdG8gdGhlIC50cml2eWlnbm9yZSBpbiB0cml2eS5cbiAgICogUHV0IGVhY2ggbGluZSB5b3Ugd3JpdGUgaW4gdGhlIGZpbGUgaW50byBvbmUgZWxlbWVudCBvZiB0aGUgYXJyYXkuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqICAgICAkIGNhdCAudHJpdnlpZ25vcmVcbiAgICogICAgICMgQWNjZXB0IHRoZSByaXNrXG4gICAqICAgICBDVkUtMjAxOC0xNDYxOFxuICAgKlxuICAgKiAgICAgIyBBY2NlcHQgdGhlIHJpc2sgdW50aWwgMjAyMy0wMS0wMVxuICAgKiAgICAgQ1ZFLTIwMTktMTQ2OTcgZXhwOjIwMjMtMDEtMDFcbiAgICpcbiAgICogICAgICMgTm8gaW1wYWN0IGluIG91ciBzZXR0aW5nc1xuICAgKiAgICAgQ1ZFLTIwMTktMTU0M1xuICAgKlxuICAgKiAgICAgIyBJZ25vcmUgbWlzY29uZmlndXJhdGlvbnNcbiAgICogICAgIEFWRC1EUy0wMDAyXG4gICAqXG4gICAqICAgICAjIElnbm9yZSBzZWNyZXRzXG4gICAqICAgICBnZW5lcmljLXVud2FudGVkLXJ1bGVcbiAgICogICAgIGF3cy1hY2NvdW50LWlkXG4gICAqXG4gICAqIEBkZWZhdWx0IFtdXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9hcXVhc2VjdXJpdHkuZ2l0aHViLmlvL3RyaXZ5L2xhdGVzdC9kb2NzL2NvbmZpZ3VyYXRpb24vZmlsdGVyaW5nLyN0cml2eWlnbm9yZVxuICAgKi9cbiAgcmVhZG9ubHkgdHJpdnlJZ25vcmU/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTWVtb3J5IFNpemUgKE1CKSBmb3IgU2Nhbm5lciBMYW1iZGFcbiAgICpcbiAgICogWW91IGNhbiBzcGVjaWZ5IGJldHdlZW4gYDMwMDhgIGFuZCBgMTAyNDBgLlxuICAgKlxuICAgKiBJZiB0aGlzIENvbnN0cnVjdCBleGVjdXRpb24gdGVybWluYXRlcyBhYm5vcm1hbGx5IGR1ZSB0byBTSUdLSUxMLCB0cnkgYSBsYXJnZXIgc2l6ZS5cbiAgICpcbiAgICogRGVmYXVsdCB2YWx1ZSAoYDMwMDhgIE1CKSBpcyBNYXhpbXVtIExhbWJkYSBtZW1vcnkgc2l6ZSBmb3IgZGVmYXVsdCBBV1MgYWNjb3VudCB3aXRob3V0IHF1b3RhIGxpbWl0IGluY3JlYXNlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAzMDA4XG4gICAqL1xuICByZWFkb25seSBtZW1vcnlTaXplPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBTY2FuIEltYWdlIG9uIGEgc3BlY2lmaWMgQXJjaGl0ZWN0dXJlIGFuZCBPU1xuICAgKlxuICAgKiBCeSBkZWZhdWx0LCBUcml2eSBsb2FkcyBhbiBpbWFnZSBvbiBhIGBsaW51eC9hbWQ2NGAgbWFjaGluZS5cbiAgICpcbiAgICogVG8gY3VzdG9taXplIHRoaXMsIHBhc3MgYSBgcGxhdGZvcm1gIGFyZ3VtZW50IGluIHRoZSBmb3JtYXQgT1MvQXJjaGl0ZWN0dXJlIGZvciB0aGUgaW1hZ2UsIHN1Y2ggYXMgYGxpbnV4L2FybTY0YFxuICAgKlxuICAgKiBAZGVmYXVsdCAtXG4gICAqL1xuICByZWFkb25seSBwbGF0Zm9ybT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHJlbW92YWwgcG9saWN5IHRvIGFwcGx5IHRvIFNjYW5uZXIgTGFtYmRhJ3MgZGVmYXVsdCBsb2cgZ3JvdXBcbiAgICpcbiAgICogSWYgeW91IHVzZSBJbWFnZVNjYW5uZXJXaXRoVHJpdnkgY29uc3RydWN0IG11bHRpcGxlIHRpbWVzIGluIHRoZSBzYW1lIHN0YWNrLCB5b3UgY2Fubm90IHNldCBkaWZmZXJlbnQgcmVtb3ZhbCBwb2xpY2llcyBmb3IgdGhlIGRlZmF1bHQgbG9nIGdyb3VwLlxuICAgKiBTZWUgYE5vdGVzYCBzZWN0aW9uIGluIHRoZSBSRUFETUUgZm9yIG1vcmUgZGV0YWlscy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBTY2FubmVyIExhbWJkYSBjcmVhdGVzIHRoZSBkZWZhdWx0IGxvZyBncm91cChgL2F3cy9sYW1iZGEvJHtmdW5jdGlvbk5hbWV9YCkuXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0TG9nR3JvdXBSZW1vdmFsUG9saWN5PzogUmVtb3ZhbFBvbGljeTtcblxuICAvKipcbiAgICogVGhlIG51bWJlciBvZiBkYXlzIGxvZyBldmVudHMgYXJlIGtlcHQgaW4gU2Nhbm5lciBMYW1iZGEncyBkZWZhdWx0IGxvZyBncm91cFxuICAgKlxuICAgKiBJZiB5b3UgdXNlIEltYWdlU2Nhbm5lcldpdGhUcml2eSBjb25zdHJ1Y3QgbXVsdGlwbGUgdGltZXMgaW4gdGhlIHNhbWUgc3RhY2ssIHlvdSBjYW5ub3Qgc2V0IGRpZmZlcmVudCByZXRlbnRpb24gZGF5cyBmb3IgdGhlIGRlZmF1bHQgbG9nIGdyb3VwLlxuICAgKiBTZWUgYE5vdGVzYCBzZWN0aW9uIGluIHRoZSBSRUFETUUgZm9yIG1vcmUgZGV0YWlscy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBTY2FubmVyIExhbWJkYSBjcmVhdGVzIHRoZSBkZWZhdWx0IGxvZyBncm91cChgL2F3cy9sYW1iZGEvJHtmdW5jdGlvbk5hbWV9YCkgYW5kIGxvZyBldmVudHMgbmV2ZXIgZXhwaXJlLlxuICAgKi9cbiAgcmVhZG9ubHkgZGVmYXVsdExvZ0dyb3VwUmV0ZW50aW9uRGF5cz86IFJldGVudGlvbkRheXM7XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gZm9yIHNjYW4gbG9ncyBvdXRwdXRcbiAgICpcbiAgICogQnkgZGVmYXVsdCwgc2NhbiBsb2dzIGFyZSBvdXRwdXQgdG8gZGVmYXVsdCBsb2cgZ3JvdXAgY3JlYXRlZCBieSBTY2FubmVyIExhbWJkYS5cbiAgICpcbiAgICogU3BlY2lmeSB0aGlzIGlmIHlvdSB3YW50IHRvIHNlbmQgc2NhbiBsb2dzIHRvIG90aGVyIHRoYW4gdGhlIGRlZmF1bHQgbG9nIGdyb3VwLlxuICAgKlxuICAgKiBDdXJyZW50bHksIG9ubHkgYGNsb3VkV2F0Y2hMb2dzYCBpcyBzdXBwb3J0ZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gc2NhbiBsb2dzIG91dHB1dCB0byBkZWZhdWx0IGxvZyBncm91cCBjcmVhdGVkIGJ5IFNjYW5uZXIgTGFtYmRhKGAvYXdzL2xhbWJkYS8ke2Z1bmN0aW9uTmFtZX1gKVxuICAgKi9cbiAgcmVhZG9ubHkgc2NhbkxvZ3NPdXRwdXQ/OiBTY2FuTG9nc091dHB1dDtcblxuICAvKipcbiAgICogU3VwcHJlc3MgZXJyb3JzIGR1cmluZyByb2xsYmFjayBzY2FubmVyIExhbWJkYSBleGVjdXRpb25cbiAgICpcbiAgICogV2hlbiBpbWFnZSBzY2FubmluZyBmYWlscywgQ2xvdWRGb3JtYXRpb24gdHJpZ2dlcnMgYSByb2xsYmFjayBhbmQgZXhlY3V0ZXMgdGhlIHByZXZpb3VzXG4gICAqIHZlcnNpb24gb2YgdGhlIHNjYW5uZXIgTGFtYmRhLiBJZiB0aGlzIHByb3BlcnR5IGlzIHNldCB0byBgdHJ1ZWAsIHRoZSBwcmV2aW91cyB2ZXJzaW9uIG9mXG4gICAqIHRoZSBzY2FubmVyIExhbWJkYSB3aWxsIG5vdCB0aHJvdyBhbiBlcnJvciwgZXZlbiBpZiB0aGUgaW1hZ2Ugc2Nhbm5pbmcgZm9yIHRoZSBwcmV2aW91cyB2ZXJzaW9uXG4gICAqIGZhaWxzLlxuICAgKlxuICAgKiBUaGlzIGFsbG93cyB0aGUgcm9sbGJhY2sgdG8gY29tcGxldGUgc3VjY2Vzc2Z1bGx5LCBhdm9pZGluZyBST0xMQkFDS19GQUlMRUQgc3RhdGVcbiAgICogd2hlbiBpbWFnZSBzY2FubmluZyBmYWlsdXJlcyBvY2N1ci5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgc3VwcHJlc3NFcnJvck9uUm9sbGJhY2s/OiBib29sZWFuO1xufVxuXG4vLyBNYXhpbXVtIExhbWJkYSBtZW1vcnkgc2l6ZSBmb3IgZGVmYXVsdCBBV1MgYWNjb3VudCB3aXRob3V0IHF1b3RhIGxpbWl0IGluY3JlYXNlXG5jb25zdCBERUZBVUxUX01FTU9SWV9TSVpFID0gMzAwODtcblxuLyoqXG4gKiBBIENvbnN0cnVjdCB0aGF0IHNjYW5zIGNvbnRhaW5lciBpbWFnZXMgd2l0aCBUcml2eS5cbiAqIEl0IHVzZXMgYSBMYW1iZGEgZnVuY3Rpb24gYXMgYSBDdXN0b20gUmVzb3VyY2UgcHJvdmlkZXIgdG8gcnVuIFRyaXZ5IGFuZCBzY2FuIGNvbnRhaW5lciBpbWFnZXMuXG4gKlxuICogQGRlcHJlY2F0ZWQgVXNlIEltYWdlU2Nhbm5lcldpdGhUcml2eVYyIGluc3RlYWQuIFRoaXMgd2lsbCBiZSByZW1vdmVkIGluIHRoZSBuZXh0IG1ham9yIHZlcnNpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBJbWFnZVNjYW5uZXJXaXRoVHJpdnkgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogSW1hZ2VTY2FubmVyV2l0aFRyaXZ5UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgaWYgKFxuICAgICAgcHJvcHMubWVtb3J5U2l6ZSAmJlxuICAgICAgIVRva2VuLmlzVW5yZXNvbHZlZChwcm9wcy5tZW1vcnlTaXplKSAmJlxuICAgICAgKHByb3BzLm1lbW9yeVNpemUgPCAzMDA4IHx8IHByb3BzLm1lbW9yeVNpemUgPiAxMDI0MClcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFlvdSBjYW4gc3BlY2lmeSBiZXR3ZWVuIFxcYDMwMDhcXGAgYW5kIFxcYDEwMjQwXFxgIGZvciBcXGBtZW1vcnlTaXplXFxgLCBnb3QgJHtwcm9wcy5tZW1vcnlTaXplfS5gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBsYW1iZGFQdXJwb3NlID0gJ0N1c3RvbTo6SW1hZ2VTY2FubmVyV2l0aFRyaXZ5Q3VzdG9tUmVzb3VyY2VMYW1iZGEnO1xuICAgIGNvbnN0IGN1c3RvbVJlc291cmNlTGFtYmRhID0gbmV3IFNpbmdsZXRvbkZ1bmN0aW9uKHRoaXMsICdDdXN0b21SZXNvdXJjZUxhbWJkYScsIHtcbiAgICAgIHV1aWQ6ICc0NzBiNjM0My1kMjY3LWY3NTMtMjI2Yy0xZTk5ZjA5ZjMxOWEnLFxuICAgICAgbGFtYmRhUHVycG9zZSxcbiAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuRlJPTV9JTUFHRSxcbiAgICAgIGhhbmRsZXI6IEhhbmRsZXIuRlJPTV9JTUFHRSxcbiAgICAgIGNvZGU6IEFzc2V0Q29kZS5mcm9tQXNzZXRJbWFnZShqb2luKF9fZGlybmFtZSwgJy4uL2Fzc2V0cy9sYW1iZGEnKSwge1xuICAgICAgICBwbGF0Zm9ybTogUGxhdGZvcm0uTElOVVhfQVJNNjQsXG4gICAgICAgIC8vIGV4Y2x1ZGUgbm9kZV9tb2R1bGVzXG4gICAgICAgIC8vIGJlY2F1c2UgdGhlIG5hdGl2ZSBiaW5hcnkgb2YgdGhlIGluc3RhbGxlZCBlc2J1aWxkIGNoYW5nZXMgZGVwZW5kaW5nIG9uIHRoZSBjcHUgYXJjaGl0ZWN0dXJlXG4gICAgICAgIC8vIGFuZCB0aGUgaGFzaCB2YWx1ZSBvZiB0aGUgaW1hZ2UgYXNzZXQgY2hhbmdlcyBkZXBlbmRpbmcgb24gdGhlIGV4ZWN1dGlvbiBlbnZpcm9ubWVudC5cbiAgICAgICAgZXhjbHVkZTogWydub2RlX21vZHVsZXMnXSxcbiAgICAgIH0pLFxuICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuQVJNXzY0LFxuICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcyg5MDApLFxuICAgICAgcmV0cnlBdHRlbXB0czogMCxcbiAgICAgIG1lbW9yeVNpemU6IHByb3BzLm1lbW9yeVNpemUgPz8gREVGQVVMVF9NRU1PUllfU0laRSxcbiAgICAgIGVwaGVtZXJhbFN0b3JhZ2VTaXplOiBTaXplLmdpYmlieXRlcygxMCksIC8vIGZvciBjYXNlcyB0aGF0IG5lZWQgdG8gdXBkYXRlIHRyaXZ5IERCOiAvdG1wL3RyaXZ5L2RiL3RyaXZ5LmRiXG4gICAgfSk7XG4gICAgcHJvcHMucmVwb3NpdG9yeS5ncmFudFB1bGwoY3VzdG9tUmVzb3VyY2VMYW1iZGEpO1xuXG4gICAgLy8gR3JhbnQgQ2xvdWRGb3JtYXRpb24gRGVzY3JpYmVTdGFja3MgcGVybWlzc2lvbiBmb3Igcm9sbGJhY2sgZGV0ZWN0aW9uIHdoZW4gc3VwcHJlc3NFcnJvck9uUm9sbGJhY2sgaXMgZW5hYmxlZFxuICAgIGNvbnN0IHN1cHByZXNzRXJyb3JPblJvbGxiYWNrID0gcHJvcHMuc3VwcHJlc3NFcnJvck9uUm9sbGJhY2sgPz8gdHJ1ZTtcbiAgICBpZiAoc3VwcHJlc3NFcnJvck9uUm9sbGJhY2spIHtcbiAgICAgIGN1c3RvbVJlc291cmNlTGFtYmRhLmFkZFRvUm9sZVBvbGljeShcbiAgICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgYWN0aW9uczogWydjbG91ZGZvcm1hdGlvbjpEZXNjcmliZVN0YWNrcyddLFxuICAgICAgICAgIHJlc291cmNlczogW1N0YWNrLm9mKHRoaXMpLnN0YWNrSWRdLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgY3VzdG9tUmVzb3VyY2VMYW1iZGFMb2dHcm91cENvbnN0cnVjdE5hbWUgPSBgRGVmYXVsdExvZ0dyb3VwRm9yJHtsYW1iZGFQdXJwb3NlfWA7XG5cbiAgICB0aGlzLnZhbGlkYXRlTGFtYmRhRGVmYXVsdExvZ0dyb3VwT3B0aW9ucyhjdXN0b21SZXNvdXJjZUxhbWJkYUxvZ0dyb3VwQ29uc3RydWN0TmFtZSwgcHJvcHMpO1xuXG4gICAgaWYgKHByb3BzLmRlZmF1bHRMb2dHcm91cFJlbW92YWxQb2xpY3kgfHwgcHJvcHMuZGVmYXVsdExvZ0dyb3VwUmV0ZW50aW9uRGF5cykge1xuICAgICAgdGhpcy5lbnN1cmVMYW1iZGFEZWZhdWx0TG9nR3JvdXAoXG4gICAgICAgIGN1c3RvbVJlc291cmNlTGFtYmRhLFxuICAgICAgICBjdXN0b21SZXNvdXJjZUxhbWJkYUxvZ0dyb3VwQ29uc3RydWN0TmFtZSxcbiAgICAgICAgcHJvcHMsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGltYWdlU2Nhbm5lclByb3ZpZGVyID0gbmV3IFByb3ZpZGVyKHRoaXMsICdQcm92aWRlcicsIHtcbiAgICAgIG9uRXZlbnRIYW5kbGVyOiBjdXN0b21SZXNvdXJjZUxhbWJkYSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGltYWdlU2Nhbm5lclByb3BlcnRpZXM6IFNjYW5uZXJDdXN0b21SZXNvdXJjZVByb3BzID0ge1xuICAgICAgYWRkcjogdGhpcy5ub2RlLmFkZHIsXG4gICAgICBpbWFnZVVyaTogcHJvcHMuaW1hZ2VVcmksXG4gICAgICBpZ25vcmVVbmZpeGVkOiBTdHJpbmcocHJvcHMuaWdub3JlVW5maXhlZCA/PyBmYWxzZSksXG4gICAgICBzZXZlcml0eTogcHJvcHMuc2V2ZXJpdHkgPz8gW1NldmVyaXR5LkNSSVRJQ0FMXSxcbiAgICAgIHNjYW5uZXJzOiBwcm9wcy5zY2FubmVycyA/PyBbXSxcbiAgICAgIGltYWdlQ29uZmlnU2Nhbm5lcnM6IHByb3BzLmltYWdlQ29uZmlnU2Nhbm5lcnMgPz8gW10sXG4gICAgICBleGl0Q29kZTogcHJvcHMuZXhpdENvZGUgPz8gMSwgLy8gVE9ETzogUmVtb3ZlIGV4aXRDb2RlIGFuZCBleGl0T25Fb2wgcHJvcGVydGllcyBpbiB0aGUgbmV4dCBtYWpvciB2ZXJzaW9uLCBhcyB0aGV5IGFyZSBub3cgY29udHJvbGxlZCBieSBmYWlsT25WdWxuZXJhYmlsaXR5LlxuICAgICAgZXhpdE9uRW9sOiBwcm9wcy5leGl0T25Fb2wgPz8gMSwgLy8gVE9ETzogUmVtb3ZlIGV4aXRDb2RlIGFuZCBleGl0T25Fb2wgcHJvcGVydGllcyBpbiB0aGUgbmV4dCBtYWpvciB2ZXJzaW9uLCBhcyB0aGV5IGFyZSBub3cgY29udHJvbGxlZCBieSBmYWlsT25WdWxuZXJhYmlsaXR5LlxuICAgICAgZmFpbE9uVnVsbmVyYWJpbGl0eTogJ3RydWUnLCAvLyBkdW1teSB2YWx1ZSBmb3IgdjIgcHJvcGVydHlcbiAgICAgIHRyaXZ5SWdub3JlOiBwcm9wcy50cml2eUlnbm9yZSA/PyBbXSxcbiAgICAgIHBsYXRmb3JtOiBwcm9wcy5wbGF0Zm9ybSA/PyAnJyxcbiAgICAgIG91dHB1dDogcHJvcHMuc2NhbkxvZ3NPdXRwdXQ/LmJpbmQoY3VzdG9tUmVzb3VyY2VMYW1iZGEpLFxuICAgICAgc3VwcHJlc3NFcnJvck9uUm9sbGJhY2s6IFN0cmluZyhzdXBwcmVzc0Vycm9yT25Sb2xsYmFjayksXG4gICAgICBkZWZhdWx0TG9nR3JvdXBOYW1lOiBgL2F3cy9sYW1iZGEvJHtjdXN0b21SZXNvdXJjZUxhbWJkYS5mdW5jdGlvbk5hbWV9YCxcbiAgICB9O1xuXG4gICAgbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIHJlc291cmNlVHlwZTogJ0N1c3RvbTo6SW1hZ2VTY2FubmVyV2l0aFRyaXZ5JyxcbiAgICAgIHByb3BlcnRpZXM6IGltYWdlU2Nhbm5lclByb3BlcnRpZXMsXG4gICAgICBzZXJ2aWNlVG9rZW46IGltYWdlU2Nhbm5lclByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgdGhhdCBzcGVjaWZpZWQgZGVmYXVsdCBsb2cgZ3JvdXAgb3B0aW9ucyBhcmUgdGhlIHNhbWUgZm9yIGV4aXN0aW5nIGRlZmF1bHQgbG9nIGdyb3VwLlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZUxhbWJkYURlZmF1bHRMb2dHcm91cE9wdGlvbnMoXG4gICAgbG9nR3JvdXBDb25zdHJ1Y3ROYW1lOiBzdHJpbmcsXG4gICAgcHJvcHM6IEltYWdlU2Nhbm5lcldpdGhUcml2eVByb3BzLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBleGlzdGluZyA9IFN0YWNrLm9mKHRoaXMpLm5vZGUudHJ5RmluZENoaWxkKGxvZ0dyb3VwQ29uc3RydWN0TmFtZSkgYXNcbiAgICAgIHwgTG9nR3JvdXBcbiAgICAgIHwgdW5kZWZpbmVkO1xuICAgIGlmICghZXhpc3RpbmcpIHJldHVybjtcblxuICAgIGNvbnN0IGNmbkxvZ0dyb3VwID0gZXhpc3Rpbmcubm9kZS5kZWZhdWx0Q2hpbGQgYXMgQ2ZuTG9nR3JvdXA7XG5cbiAgICBpZiAoXG4gICAgICAhdGhpcy5pc1NhbWVSZXNvdXJjZURlbGV0aW9uQmVoYXZpb3IoXG4gICAgICAgIHByb3BzLmRlZmF1bHRMb2dHcm91cFJlbW92YWxQb2xpY3ksXG4gICAgICAgIGNmbkxvZ0dyb3VwLmNmbk9wdGlvbnMuZGVsZXRpb25Qb2xpY3ksXG4gICAgICApIHx8XG4gICAgICBjZm5Mb2dHcm91cC5yZXRlbnRpb25JbkRheXMgIT09IHByb3BzLmRlZmF1bHRMb2dHcm91cFJldGVudGlvbkRheXNcbiAgICApIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZFdhcm5pbmdWMihcbiAgICAgICAgJ0BpbWFnZS1zY2FubmVyLXdpdGgtdHJpdnk6ZHVwbGljYXRlTGFtYmRhRGVmYXVsdExvZ0dyb3VwT3B0aW9ucycsXG4gICAgICAgIFwiWW91IGhhdmUgdG8gc2V0IHRoZSBzYW1lIHZhbHVlcyBmb3IgJ2RlZmF1bHRMb2dHcm91cFJlbW92YWxQb2xpY3knIGFuZCAnZGVmYXVsdExvZ0dyb3VwUmV0ZW50aW9uRGF5cycgZm9yIGVhY2ggSW1hZ2VTY2FubmVyV2l0aFRyaXZ5IGNvbnN0cnVjdCBpbiB0aGUgc2FtZSBzdGFjay5cIixcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGRlZmF1bHQgbG9nIGdyb3VwIGZvciBTY2FubmVyIExhbWJkYSBpZiBpdCBkb2VzIG5vdCBleGlzdC5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgY2hlY2tzIGlmIHRoZSBkZWZhdWx0IGxvZyBncm91cCBmb3IgU2Nhbm5lciBMYW1iZGEgZXhpc3RzIGluIGNoaWxkcmVuIG9mIHRoZSBzdGFjayBjb25zdHJ1Y3QuXG4gICAqIElmIGl0IGRvZXMgbm90IGV4aXN0LCBpdCBjcmVhdGVzIHRoZSBkZWZhdWx0IGxvZyBncm91cCBmb3IgU2Nhbm5lciBMYW1iZGEgYXMgYSBjaGlsZCBvZiB0aGUgc3RhY2sgY29uc3RydWN0LlxuICAgKi9cbiAgcHJpdmF0ZSBlbnN1cmVMYW1iZGFEZWZhdWx0TG9nR3JvdXAoXG4gICAgc2luZ2xldG9uRnVuY3Rpb246IFNpbmdsZXRvbkZ1bmN0aW9uLFxuICAgIGxvZ0dyb3VwQ29uc3RydWN0TmFtZTogc3RyaW5nLFxuICAgIHByb3BzOiBJbWFnZVNjYW5uZXJXaXRoVHJpdnlQcm9wcyxcbiAgKTogTG9nR3JvdXAge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gU3RhY2sub2YodGhpcykubm9kZS50cnlGaW5kQ2hpbGQobG9nR3JvdXBDb25zdHJ1Y3ROYW1lKSBhc1xuICAgICAgfCBMb2dHcm91cFxuICAgICAgfCB1bmRlZmluZWQ7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICByZXR1cm4gZXhpc3Rpbmc7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBMb2dHcm91cChTdGFjay5vZih0aGlzKSwgbG9nR3JvdXBDb25zdHJ1Y3ROYW1lLCB7XG4gICAgICBsb2dHcm91cE5hbWU6IGAvYXdzL2xhbWJkYS8ke3NpbmdsZXRvbkZ1bmN0aW9uLmZ1bmN0aW9uTmFtZX1gLFxuICAgICAgcmV0ZW50aW9uOiBwcm9wcy5kZWZhdWx0TG9nR3JvdXBSZXRlbnRpb25EYXlzLFxuICAgICAgcmVtb3ZhbFBvbGljeTogcHJvcHMuZGVmYXVsdExvZ0dyb3VwUmVtb3ZhbFBvbGljeSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgaXNTYW1lUmVzb3VyY2VEZWxldGlvbkJlaGF2aW9yKFxuICAgIHJlbW92YWxQb2xpY3k/OiBSZW1vdmFsUG9saWN5LFxuICAgIGRlbGV0aW9uUG9saWN5PzogQ2ZuRGVsZXRpb25Qb2xpY3ksXG4gICk6IGJvb2xlYW4ge1xuICAgIHN3aXRjaCAocmVtb3ZhbFBvbGljeSkge1xuICAgICAgY2FzZSBSZW1vdmFsUG9saWN5LkRFU1RST1k6XG4gICAgICAgIHJldHVybiBkZWxldGlvblBvbGljeSA9PT0gQ2ZuRGVsZXRpb25Qb2xpY3kuREVMRVRFO1xuICAgICAgY2FzZSBSZW1vdmFsUG9saWN5LlJFVEFJTjpcbiAgICAgICAgcmV0dXJuIGRlbGV0aW9uUG9saWN5ID09PSBDZm5EZWxldGlvblBvbGljeS5SRVRBSU47XG4gICAgICBjYXNlIFJlbW92YWxQb2xpY3kuU05BUFNIT1Q6XG4gICAgICAgIHJldHVybiBkZWxldGlvblBvbGljeSA9PT0gQ2ZuRGVsZXRpb25Qb2xpY3kuU05BUFNIT1Q7XG4gICAgICBjYXNlIFJlbW92YWxQb2xpY3kuUkVUQUlOX09OX1VQREFURV9PUl9ERUxFVEU6XG4gICAgICAgIHJldHVybiBkZWxldGlvblBvbGljeSA9PT0gQ2ZuRGVsZXRpb25Qb2xpY3kuUkVUQUlOX0VYQ0VQVF9PTl9DUkVBVEU7XG4gICAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgICAgcmV0dXJuIGRlbGV0aW9uUG9saWN5ID09PSB1bmRlZmluZWQ7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gcmVtb3ZhbFBvbGljeSBzYXRpc2ZpZXMgbmV2ZXI7XG4gICAgfVxuICB9XG59XG4iXX0=