cdk-nag
Version:
Check CDK v2 applications for best practices using a combination on available rule packs.
162 lines • 21.5 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
const path_1 = require("path");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_s3_1 = require("aws-cdk-lib/aws-s3");
const nag_rules_1 = require("../../nag-rules");
/**
* S3 Buckets and bucket policies require requests to use SSL
* @param node the CfnResource to check
*/
exports.default = Object.defineProperty((node) => {
if (node instanceof aws_s3_1.CfnBucket) {
const bucketLogicalId = nag_rules_1.NagRules.resolveResourceFromInstrinsic(node, node.ref);
const bucketName = aws_cdk_lib_1.Stack.of(node).resolve(node.bucketName);
let found = false;
for (const child of aws_cdk_lib_1.Stack.of(node).node.findAll()) {
if (child instanceof aws_s3_1.CfnBucketPolicy) {
if (isMatchingPolicy(child, bucketLogicalId, bucketName) &&
isCompliantPolicy(child, bucketLogicalId, bucketName)) {
found = true;
break;
}
}
}
if (!found) {
return nag_rules_1.NagRuleCompliance.NON_COMPLIANT;
}
return nag_rules_1.NagRuleCompliance.COMPLIANT;
}
else if (node instanceof aws_s3_1.CfnBucketPolicy) {
const bucketLogicalId = nag_rules_1.NagRules.resolveResourceFromInstrinsic(node, node.bucket);
return isCompliantPolicy(node, bucketLogicalId, node.bucket)
? nag_rules_1.NagRuleCompliance.COMPLIANT
: nag_rules_1.NagRuleCompliance.NON_COMPLIANT;
}
else {
return nag_rules_1.NagRuleCompliance.NOT_APPLICABLE;
}
}, 'name', { value: path_1.parse(__filename).name });
/**
* Helper function to check whether the Bucket Policy belongs to the given bucket
* @param node The CfnBucketPolicy to check.
* @param bucketLogicalId The Cfn Logical ID of the bucket.
* @param bucketName The name of the bucket.
* @returns Whether the CfnBucketPolicy belongs to th egiven bucket.
*/
function isMatchingPolicy(node, bucketLogicalId, bucketName) {
const bucket = nag_rules_1.NagRules.resolveResourceFromInstrinsic(node, node.bucket);
return bucket === bucketLogicalId || bucket === bucketName;
}
/**
* Helper function to check whether the Bucket Policy requires SSL on the given bucket.
* @param node The CfnBucketPolicy to check.
* @param bucketLogicalId The Cfn Logical ID of the bucket.
* @param bucketName The name of the bucket.
* @returns Whether the CfnBucketPolicy requires SSL on the given bucket.
*/
function isCompliantPolicy(node, bucketLogicalId, bucketName) {
const resolvedPolicyDocument = aws_cdk_lib_1.Stack.of(node).resolve(node.policyDocument);
for (const statement of resolvedPolicyDocument.Statement) {
const resolvedStatement = aws_cdk_lib_1.Stack.of(node).resolve(statement);
const secureTransport = resolvedStatement?.Condition?.Bool?.['aws:SecureTransport'];
if (resolvedStatement.Effect === 'Deny' &&
checkMatchingAction(resolvedStatement.Action) === true &&
checkMatchingPrincipal(resolvedStatement.Principal) === true &&
(secureTransport === 'false' || secureTransport === false) &&
checkMatchingResources(node, bucketLogicalId, bucketName, resolvedStatement.Resource) === true) {
return true;
}
}
return false;
}
/**
* Helper function to check whether the Bucket Policy applies to all actions
* @param node The CfnBucketPolicy to check
* @param actions The action in the bucket policy
* @returns Whether the CfnBucketPolicy applies to all actions
*/
function checkMatchingAction(actions) {
if (Array.isArray(actions)) {
for (const action of actions) {
if (action === '*' || action.toLowerCase() === 's3:*') {
return true;
}
}
}
else if (actions === '*' || actions.toLowerCase() === 's3:*') {
return true;
}
return false;
}
/**
* Helper function to check whether the Bucket Policy applies to all principals
* @param node The CfnBucketPolicy to check
* @param principal The principals in the bucket policy
* @returns Whether the CfnBucketPolicy applies to all principals
*/
function checkMatchingPrincipal(principals) {
if (principals === '*') {
return true;
}
const awsPrincipal = principals.AWS;
if (Array.isArray(awsPrincipal)) {
for (const account of awsPrincipal) {
if (account === '*') {
return true;
}
}
}
else if (awsPrincipal === '*') {
return true;
}
return false;
}
/**
* Helper function to check whether the Bucket Policy applies to the bucket and all of it's resources
* @param node The CfnBucketPolicy to check
* @param bucketLogicalId The Cfn Logical ID of the bucket
* @param bucketName The name of the bucket
* @param resources The resources in the bucket policy
* @returns Whether the Bucket Policy applies to the bucket and all of it's resources
*/
function checkMatchingResources(node, bucketLogicalId, bucketName, resources) {
if (!Array.isArray(resources)) {
return false;
}
const bucketResourceRegexes = Array();
const bucketObjectsRegexes = Array();
bucketResourceRegexes.push(`(${bucketLogicalId}(?![\\w\\-]))`);
bucketObjectsRegexes.push(`(${bucketLogicalId}(?![\\w\\-]).*\\/\\*)`);
if (bucketName !== undefined) {
bucketResourceRegexes.push(`(${bucketName}(?![\\w\\-]))`);
bucketObjectsRegexes.push(`(${bucketName}(?![\\w\\-]).*\\/\\*)`);
}
const fullBucketResourceRegex = new RegExp(bucketResourceRegexes.join('|'));
const fullBucketObjectsRegex = new RegExp(bucketObjectsRegexes.join('|'));
let matchedBucketResource = false;
let matchedObjectsResource = false;
for (const resource of resources) {
const resolvedResourceString = JSON.stringify(aws_cdk_lib_1.Stack.of(node).resolve(resource));
if (matchedBucketResource === false &&
fullBucketResourceRegex.test(resolvedResourceString) &&
!resolvedResourceString.includes('/')) {
matchedBucketResource = true;
}
else if (matchedObjectsResource === false &&
fullBucketObjectsRegex.test(resolvedResourceString) &&
resolvedResourceString.indexOf('/') ===
resolvedResourceString.lastIndexOf('/')) {
matchedObjectsResource = true;
}
if (matchedBucketResource === true && matchedObjectsResource === true) {
return true;
}
}
return false;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUzNCdWNrZXRTU0xSZXF1ZXN0c09ubHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcnVsZXMvczMvUzNCdWNrZXRTU0xSZXF1ZXN0c09ubHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7O0VBR0U7QUFDRiwrQkFBNkI7QUFDN0IsNkNBQWlEO0FBQ2pELCtDQUFnRTtBQUNoRSwrQ0FBOEQ7QUFFOUQ7OztHQUdHO0FBRUgsa0JBQWUsTUFBTSxDQUFDLGNBQWMsQ0FDbEMsQ0FBQyxJQUFpQixFQUFxQixFQUFFO0lBQ3ZDLElBQUksSUFBSSxZQUFZLGtCQUFTLEVBQUU7UUFDN0IsTUFBTSxlQUFlLEdBQUcsb0JBQVEsQ0FBQyw2QkFBNkIsQ0FDNUQsSUFBSSxFQUNKLElBQUksQ0FBQyxHQUFHLENBQ1QsQ0FBQztRQUNGLE1BQU0sVUFBVSxHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDM0QsSUFBSSxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ2xCLEtBQUssTUFBTSxLQUFLLElBQUksbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ2pELElBQUksS0FBSyxZQUFZLHdCQUFlLEVBQUU7Z0JBQ3BDLElBQ0UsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLGVBQWUsRUFBRSxVQUFVLENBQUM7b0JBQ3BELGlCQUFpQixDQUFDLEtBQUssRUFBRSxlQUFlLEVBQUUsVUFBVSxDQUFDLEVBQ3JEO29CQUNBLEtBQUssR0FBRyxJQUFJLENBQUM7b0JBQ2IsTUFBTTtpQkFDUDthQUNGO1NBQ0Y7UUFDRCxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1YsT0FBTyw2QkFBaUIsQ0FBQyxhQUFhLENBQUM7U0FDeEM7UUFDRCxPQUFPLDZCQUFpQixDQUFDLFNBQVMsQ0FBQztLQUNwQztTQUFNLElBQUksSUFBSSxZQUFZLHdCQUFlLEVBQUU7UUFDMUMsTUFBTSxlQUFlLEdBQUcsb0JBQVEsQ0FBQyw2QkFBNkIsQ0FDNUQsSUFBSSxFQUNKLElBQUksQ0FBQyxNQUFNLENBQ1osQ0FBQztRQUNGLE9BQU8saUJBQWlCLENBQUMsSUFBSSxFQUFFLGVBQWUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQzFELENBQUMsQ0FBQyw2QkFBaUIsQ0FBQyxTQUFTO1lBQzdCLENBQUMsQ0FBQyw2QkFBaUIsQ0FBQyxhQUFhLENBQUM7S0FDckM7U0FBTTtRQUNMLE9BQU8sNkJBQWlCLENBQUMsY0FBYyxDQUFDO0tBQ3pDO0FBQ0gsQ0FBQyxFQUNELE1BQU0sRUFDTixFQUFFLEtBQUssRUFBRSxZQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQ2xDLENBQUM7QUFFRjs7Ozs7O0dBTUc7QUFDSCxTQUFTLGdCQUFnQixDQUN2QixJQUFxQixFQUNyQixlQUF1QixFQUN2QixVQUE4QjtJQUU5QixNQUFNLE1BQU0sR0FBRyxvQkFBUSxDQUFDLDZCQUE2QixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDekUsT0FBTyxNQUFNLEtBQUssZUFBZSxJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUM7QUFDN0QsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsaUJBQWlCLENBQ3hCLElBQXFCLEVBQ3JCLGVBQXVCLEVBQ3ZCLFVBQThCO0lBRTlCLE1BQU0sc0JBQXNCLEdBQUcsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUMzRSxLQUFLLE1BQU0sU0FBUyxJQUFJLHNCQUFzQixDQUFDLFNBQVMsRUFBRTtRQUN4RCxNQUFNLGlCQUFpQixHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM1RCxNQUFNLGVBQWUsR0FDbkIsaUJBQWlCLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFDOUQsSUFDRSxpQkFBaUIsQ0FBQyxNQUFNLEtBQUssTUFBTTtZQUNuQyxtQkFBbUIsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJO1lBQ3RELHNCQUFzQixDQUFDLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxLQUFLLElBQUk7WUFDNUQsQ0FBQyxlQUFlLEtBQUssT0FBTyxJQUFJLGVBQWUsS0FBSyxLQUFLLENBQUM7WUFDMUQsc0JBQXNCLENBQ3BCLElBQUksRUFDSixlQUFlLEVBQ2YsVUFBVSxFQUNWLGlCQUFpQixDQUFDLFFBQVEsQ0FDM0IsS0FBSyxJQUFJLEVBQ1Y7WUFDQSxPQUFPLElBQUksQ0FBQztTQUNiO0tBQ0Y7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsbUJBQW1CLENBQUMsT0FBWTtJQUN2QyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUU7UUFDMUIsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUU7WUFDNUIsSUFBSSxNQUFNLEtBQUssR0FBRyxJQUFJLE1BQU0sQ0FBQyxXQUFXLEVBQUUsS0FBSyxNQUFNLEVBQUU7Z0JBQ3JELE9BQU8sSUFBSSxDQUFDO2FBQ2I7U0FDRjtLQUNGO1NBQU0sSUFBSSxPQUFPLEtBQUssR0FBRyxJQUFJLE9BQU8sQ0FBQyxXQUFXLEVBQUUsS0FBSyxNQUFNLEVBQUU7UUFDOUQsT0FBTyxJQUFJLENBQUM7S0FDYjtJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBUyxzQkFBc0IsQ0FBQyxVQUFlO0lBQzdDLElBQUksVUFBVSxLQUFLLEdBQUcsRUFBRTtRQUN0QixPQUFPLElBQUksQ0FBQztLQUNiO0lBQ0QsTUFBTSxZQUFZLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FBQztJQUNwQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUU7UUFDL0IsS0FBSyxNQUFNLE9BQU8sSUFBSSxZQUFZLEVBQUU7WUFDbEMsSUFBSSxPQUFPLEtBQUssR0FBRyxFQUFFO2dCQUNuQixPQUFPLElBQUksQ0FBQzthQUNiO1NBQ0Y7S0FDRjtTQUFNLElBQUksWUFBWSxLQUFLLEdBQUcsRUFBRTtRQUMvQixPQUFPLElBQUksQ0FBQztLQUNiO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILFNBQVMsc0JBQXNCLENBQzdCLElBQXFCLEVBQ3JCLGVBQXVCLEVBQ3ZCLFVBQThCLEVBQzlCLFNBQWM7SUFFZCxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRTtRQUM3QixPQUFPLEtBQUssQ0FBQztLQUNkO0lBQ0QsTUFBTSxxQkFBcUIsR0FBRyxLQUFLLEVBQVUsQ0FBQztJQUM5QyxNQUFNLG9CQUFvQixHQUFHLEtBQUssRUFBVSxDQUFDO0lBQzdDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxJQUFJLGVBQWUsZUFBZSxDQUFDLENBQUM7SUFDL0Qsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksZUFBZSx1QkFBdUIsQ0FBQyxDQUFDO0lBQ3RFLElBQUksVUFBVSxLQUFLLFNBQVMsRUFBRTtRQUM1QixxQkFBcUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxVQUFVLGVBQWUsQ0FBQyxDQUFDO1FBQzFELG9CQUFvQixDQUFDLElBQUksQ0FBQyxJQUFJLFVBQVUsdUJBQXVCLENBQUMsQ0FBQztLQUNsRTtJQUNELE1BQU0sdUJBQXVCLEdBQUcsSUFBSSxNQUFNLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDNUUsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMxRSxJQUFJLHFCQUFxQixHQUFHLEtBQUssQ0FBQztJQUNsQyxJQUFJLHNCQUFzQixHQUFHLEtBQUssQ0FBQztJQUNuQyxLQUFLLE1BQU0sUUFBUSxJQUFJLFNBQVMsRUFBRTtRQUNoQyxNQUFNLHNCQUFzQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQzNDLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FDakMsQ0FBQztRQUNGLElBQ0UscUJBQXFCLEtBQUssS0FBSztZQUMvQix1QkFBdUIsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUM7WUFDcEQsQ0FBQyxzQkFBc0IsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQ3JDO1lBQ0EscUJBQXFCLEdBQUcsSUFBSSxDQUFDO1NBQzlCO2FBQU0sSUFDTCxzQkFBc0IsS0FBSyxLQUFLO1lBQ2hDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQztZQUNuRCxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDO2dCQUNqQyxzQkFBc0IsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEVBQ3pDO1lBQ0Esc0JBQXNCLEdBQUcsSUFBSSxDQUFDO1NBQy9CO1FBQ0QsSUFBSSxxQkFBcUIsS0FBSyxJQUFJLElBQUksc0JBQXNCLEtBQUssSUFBSSxFQUFFO1lBQ3JFLE9BQU8sSUFBSSxDQUFDO1NBQ2I7S0FDRjtJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4qL1xuaW1wb3J0IHsgcGFyc2UgfSBmcm9tICdwYXRoJztcbmltcG9ydCB7IENmblJlc291cmNlLCBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IENmbkJ1Y2tldCwgQ2ZuQnVja2V0UG9saWN5IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCB7IE5hZ1J1bGVDb21wbGlhbmNlLCBOYWdSdWxlcyB9IGZyb20gJy4uLy4uL25hZy1ydWxlcyc7XG5cbi8qKlxuICogUzMgQnVja2V0cyBhbmQgYnVja2V0IHBvbGljaWVzIHJlcXVpcmUgcmVxdWVzdHMgdG8gdXNlIFNTTFxuICogQHBhcmFtIG5vZGUgdGhlIENmblJlc291cmNlIHRvIGNoZWNrXG4gKi9cblxuZXhwb3J0IGRlZmF1bHQgT2JqZWN0LmRlZmluZVByb3BlcnR5KFxuICAobm9kZTogQ2ZuUmVzb3VyY2UpOiBOYWdSdWxlQ29tcGxpYW5jZSA9PiB7XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDZm5CdWNrZXQpIHtcbiAgICAgIGNvbnN0IGJ1Y2tldExvZ2ljYWxJZCA9IE5hZ1J1bGVzLnJlc29sdmVSZXNvdXJjZUZyb21JbnN0cmluc2ljKFxuICAgICAgICBub2RlLFxuICAgICAgICBub2RlLnJlZlxuICAgICAgKTtcbiAgICAgIGNvbnN0IGJ1Y2tldE5hbWUgPSBTdGFjay5vZihub2RlKS5yZXNvbHZlKG5vZGUuYnVja2V0TmFtZSk7XG4gICAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2YgU3RhY2sub2Yobm9kZSkubm9kZS5maW5kQWxsKCkpIHtcbiAgICAgICAgaWYgKGNoaWxkIGluc3RhbmNlb2YgQ2ZuQnVja2V0UG9saWN5KSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgaXNNYXRjaGluZ1BvbGljeShjaGlsZCwgYnVja2V0TG9naWNhbElkLCBidWNrZXROYW1lKSAmJlxuICAgICAgICAgICAgaXNDb21wbGlhbnRQb2xpY3koY2hpbGQsIGJ1Y2tldExvZ2ljYWxJZCwgYnVja2V0TmFtZSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICByZXR1cm4gTmFnUnVsZUNvbXBsaWFuY2UuTk9OX0NPTVBMSUFOVDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBOYWdSdWxlQ29tcGxpYW5jZS5DT01QTElBTlQ7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgQ2ZuQnVja2V0UG9saWN5KSB7XG4gICAgICBjb25zdCBidWNrZXRMb2dpY2FsSWQgPSBOYWdSdWxlcy5yZXNvbHZlUmVzb3VyY2VGcm9tSW5zdHJpbnNpYyhcbiAgICAgICAgbm9kZSxcbiAgICAgICAgbm9kZS5idWNrZXRcbiAgICAgICk7XG4gICAgICByZXR1cm4gaXNDb21wbGlhbnRQb2xpY3kobm9kZSwgYnVja2V0TG9naWNhbElkLCBub2RlLmJ1Y2tldClcbiAgICAgICAgPyBOYWdSdWxlQ29tcGxpYW5jZS5DT01QTElBTlRcbiAgICAgICAgOiBOYWdSdWxlQ29tcGxpYW5jZS5OT05fQ09NUExJQU5UO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gTmFnUnVsZUNvbXBsaWFuY2UuTk9UX0FQUExJQ0FCTEU7XG4gICAgfVxuICB9LFxuICAnbmFtZScsXG4gIHsgdmFsdWU6IHBhcnNlKF9fZmlsZW5hbWUpLm5hbWUgfVxuKTtcblxuLyoqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdG8gY2hlY2sgd2hldGhlciB0aGUgQnVja2V0IFBvbGljeSBiZWxvbmdzIHRvIHRoZSBnaXZlbiBidWNrZXRcbiAqIEBwYXJhbSBub2RlIFRoZSBDZm5CdWNrZXRQb2xpY3kgdG8gY2hlY2suXG4gKiBAcGFyYW0gYnVja2V0TG9naWNhbElkIFRoZSBDZm4gTG9naWNhbCBJRCBvZiB0aGUgYnVja2V0LlxuICogQHBhcmFtIGJ1Y2tldE5hbWUgVGhlIG5hbWUgb2YgdGhlIGJ1Y2tldC5cbiAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIENmbkJ1Y2tldFBvbGljeSBiZWxvbmdzIHRvIHRoIGVnaXZlbiBidWNrZXQuXG4gKi9cbmZ1bmN0aW9uIGlzTWF0Y2hpbmdQb2xpY3koXG4gIG5vZGU6IENmbkJ1Y2tldFBvbGljeSxcbiAgYnVja2V0TG9naWNhbElkOiBzdHJpbmcsXG4gIGJ1Y2tldE5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZFxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGJ1Y2tldCA9IE5hZ1J1bGVzLnJlc29sdmVSZXNvdXJjZUZyb21JbnN0cmluc2ljKG5vZGUsIG5vZGUuYnVja2V0KTtcbiAgcmV0dXJuIGJ1Y2tldCA9PT0gYnVja2V0TG9naWNhbElkIHx8IGJ1Y2tldCA9PT0gYnVja2V0TmFtZTtcbn1cblxuLyoqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdG8gY2hlY2sgd2hldGhlciB0aGUgQnVja2V0IFBvbGljeSByZXF1aXJlcyBTU0wgb24gdGhlIGdpdmVuIGJ1Y2tldC5cbiAqIEBwYXJhbSBub2RlIFRoZSBDZm5CdWNrZXRQb2xpY3kgdG8gY2hlY2suXG4gKiBAcGFyYW0gYnVja2V0TG9naWNhbElkIFRoZSBDZm4gTG9naWNhbCBJRCBvZiB0aGUgYnVja2V0LlxuICogQHBhcmFtIGJ1Y2tldE5hbWUgVGhlIG5hbWUgb2YgdGhlIGJ1Y2tldC5cbiAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIENmbkJ1Y2tldFBvbGljeSByZXF1aXJlcyBTU0wgb24gdGhlIGdpdmVuIGJ1Y2tldC5cbiAqL1xuZnVuY3Rpb24gaXNDb21wbGlhbnRQb2xpY3koXG4gIG5vZGU6IENmbkJ1Y2tldFBvbGljeSxcbiAgYnVja2V0TG9naWNhbElkOiBzdHJpbmcsXG4gIGJ1Y2tldE5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZFxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJlc29sdmVkUG9saWN5RG9jdW1lbnQgPSBTdGFjay5vZihub2RlKS5yZXNvbHZlKG5vZGUucG9saWN5RG9jdW1lbnQpO1xuICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiByZXNvbHZlZFBvbGljeURvY3VtZW50LlN0YXRlbWVudCkge1xuICAgIGNvbnN0IHJlc29sdmVkU3RhdGVtZW50ID0gU3RhY2sub2Yobm9kZSkucmVzb2x2ZShzdGF0ZW1lbnQpO1xuICAgIGNvbnN0IHNlY3VyZVRyYW5zcG9ydCA9XG4gICAgICByZXNvbHZlZFN0YXRlbWVudD8uQ29uZGl0aW9uPy5Cb29sPy5bJ2F3czpTZWN1cmVUcmFuc3BvcnQnXTtcbiAgICBpZiAoXG4gICAgICByZXNvbHZlZFN0YXRlbWVudC5FZmZlY3QgPT09ICdEZW55JyAmJlxuICAgICAgY2hlY2tNYXRjaGluZ0FjdGlvbihyZXNvbHZlZFN0YXRlbWVudC5BY3Rpb24pID09PSB0cnVlICYmXG4gICAgICBjaGVja01hdGNoaW5nUHJpbmNpcGFsKHJlc29sdmVkU3RhdGVtZW50LlByaW5jaXBhbCkgPT09IHRydWUgJiZcbiAgICAgIChzZWN1cmVUcmFuc3BvcnQgPT09ICdmYWxzZScgfHwgc2VjdXJlVHJhbnNwb3J0ID09PSBmYWxzZSkgJiZcbiAgICAgIGNoZWNrTWF0Y2hpbmdSZXNvdXJjZXMoXG4gICAgICAgIG5vZGUsXG4gICAgICAgIGJ1Y2tldExvZ2ljYWxJZCxcbiAgICAgICAgYnVja2V0TmFtZSxcbiAgICAgICAgcmVzb2x2ZWRTdGF0ZW1lbnQuUmVzb3VyY2VcbiAgICAgICkgPT09IHRydWVcbiAgICApIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogSGVscGVyIGZ1bmN0aW9uIHRvIGNoZWNrIHdoZXRoZXIgdGhlIEJ1Y2tldCBQb2xpY3kgYXBwbGllcyB0byBhbGwgYWN0aW9uc1xuICogQHBhcmFtIG5vZGUgVGhlIENmbkJ1Y2tldFBvbGljeSB0byBjaGVja1xuICogQHBhcmFtIGFjdGlvbnMgVGhlIGFjdGlvbiBpbiB0aGUgYnVja2V0IHBvbGljeVxuICogQHJldHVybnMgV2hldGhlciB0aGUgQ2ZuQnVja2V0UG9saWN5IGFwcGxpZXMgdG8gYWxsIGFjdGlvbnNcbiAqL1xuZnVuY3Rpb24gY2hlY2tNYXRjaGluZ0FjdGlvbihhY3Rpb25zOiBhbnkpOiBib29sZWFuIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoYWN0aW9ucykpIHtcbiAgICBmb3IgKGNvbnN0IGFjdGlvbiBvZiBhY3Rpb25zKSB7XG4gICAgICBpZiAoYWN0aW9uID09PSAnKicgfHwgYWN0aW9uLnRvTG93ZXJDYXNlKCkgPT09ICdzMzoqJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSBpZiAoYWN0aW9ucyA9PT0gJyonIHx8IGFjdGlvbnMudG9Mb3dlckNhc2UoKSA9PT0gJ3MzOionKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIEhlbHBlciBmdW5jdGlvbiB0byBjaGVjayB3aGV0aGVyIHRoZSBCdWNrZXQgUG9saWN5IGFwcGxpZXMgdG8gYWxsIHByaW5jaXBhbHNcbiAqIEBwYXJhbSBub2RlIFRoZSBDZm5CdWNrZXRQb2xpY3kgdG8gY2hlY2tcbiAqIEBwYXJhbSBwcmluY2lwYWwgVGhlIHByaW5jaXBhbHMgaW4gdGhlIGJ1Y2tldCBwb2xpY3lcbiAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIENmbkJ1Y2tldFBvbGljeSBhcHBsaWVzIHRvIGFsbCBwcmluY2lwYWxzXG4gKi9cbmZ1bmN0aW9uIGNoZWNrTWF0Y2hpbmdQcmluY2lwYWwocHJpbmNpcGFsczogYW55KTogYm9vbGVhbiB7XG4gIGlmIChwcmluY2lwYWxzID09PSAnKicpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBjb25zdCBhd3NQcmluY2lwYWwgPSBwcmluY2lwYWxzLkFXUztcbiAgaWYgKEFycmF5LmlzQXJyYXkoYXdzUHJpbmNpcGFsKSkge1xuICAgIGZvciAoY29uc3QgYWNjb3VudCBvZiBhd3NQcmluY2lwYWwpIHtcbiAgICAgIGlmIChhY2NvdW50ID09PSAnKicpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2UgaWYgKGF3c1ByaW5jaXBhbCA9PT0gJyonKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIEhlbHBlciBmdW5jdGlvbiB0byBjaGVjayB3aGV0aGVyIHRoZSBCdWNrZXQgUG9saWN5IGFwcGxpZXMgdG8gdGhlIGJ1Y2tldCBhbmQgYWxsIG9mIGl0J3MgcmVzb3VyY2VzXG4gKiBAcGFyYW0gbm9kZSBUaGUgQ2ZuQnVja2V0UG9saWN5IHRvIGNoZWNrXG4gKiBAcGFyYW0gYnVja2V0TG9naWNhbElkIFRoZSBDZm4gTG9naWNhbCBJRCBvZiB0aGUgYnVja2V0XG4gKiBAcGFyYW0gYnVja2V0TmFtZSBUaGUgbmFtZSBvZiB0aGUgYnVja2V0XG4gKiBAcGFyYW0gcmVzb3VyY2VzIFRoZSByZXNvdXJjZXMgaW4gdGhlIGJ1Y2tldCBwb2xpY3lcbiAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIEJ1Y2tldCBQb2xpY3kgYXBwbGllcyB0byB0aGUgYnVja2V0IGFuZCBhbGwgb2YgaXQncyByZXNvdXJjZXNcbiAqL1xuZnVuY3Rpb24gY2hlY2tNYXRjaGluZ1Jlc291cmNlcyhcbiAgbm9kZTogQ2ZuQnVja2V0UG9saWN5LFxuICBidWNrZXRMb2dpY2FsSWQ6IHN0cmluZyxcbiAgYnVja2V0TmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICByZXNvdXJjZXM6IGFueVxuKTogYm9vbGVhbiB7XG4gIGlmICghQXJyYXkuaXNBcnJheShyZXNvdXJjZXMpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IGJ1Y2tldFJlc291cmNlUmVnZXhlcyA9IEFycmF5PHN0cmluZz4oKTtcbiAgY29uc3QgYnVja2V0T2JqZWN0c1JlZ2V4ZXMgPSBBcnJheTxzdHJpbmc+KCk7XG4gIGJ1Y2tldFJlc291cmNlUmVnZXhlcy5wdXNoKGAoJHtidWNrZXRMb2dpY2FsSWR9KD8hW1xcXFx3XFxcXC1dKSlgKTtcbiAgYnVja2V0T2JqZWN0c1JlZ2V4ZXMucHVzaChgKCR7YnVja2V0TG9naWNhbElkfSg/IVtcXFxcd1xcXFwtXSkuKlxcXFwvXFxcXCopYCk7XG4gIGlmIChidWNrZXROYW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICBidWNrZXRSZXNvdXJjZVJlZ2V4ZXMucHVzaChgKCR7YnVja2V0TmFtZX0oPyFbXFxcXHdcXFxcLV0pKWApO1xuICAgIGJ1Y2tldE9iamVjdHNSZWdleGVzLnB1c2goYCgke2J1Y2tldE5hbWV9KD8hW1xcXFx3XFxcXC1dKS4qXFxcXC9cXFxcKilgKTtcbiAgfVxuICBjb25zdCBmdWxsQnVja2V0UmVzb3VyY2VSZWdleCA9IG5ldyBSZWdFeHAoYnVja2V0UmVzb3VyY2VSZWdleGVzLmpvaW4oJ3wnKSk7XG4gIGNvbnN0IGZ1bGxCdWNrZXRPYmplY3RzUmVnZXggPSBuZXcgUmVnRXhwKGJ1Y2tldE9iamVjdHNSZWdleGVzLmpvaW4oJ3wnKSk7XG4gIGxldCBtYXRjaGVkQnVja2V0UmVzb3VyY2UgPSBmYWxzZTtcbiAgbGV0IG1hdGNoZWRPYmplY3RzUmVzb3VyY2UgPSBmYWxzZTtcbiAgZm9yIChjb25zdCByZXNvdXJjZSBvZiByZXNvdXJjZXMpIHtcbiAgICBjb25zdCByZXNvbHZlZFJlc291cmNlU3RyaW5nID0gSlNPTi5zdHJpbmdpZnkoXG4gICAgICBTdGFjay5vZihub2RlKS5yZXNvbHZlKHJlc291cmNlKVxuICAgICk7XG4gICAgaWYgKFxuICAgICAgbWF0Y2hlZEJ1Y2tldFJlc291cmNlID09PSBmYWxzZSAmJlxuICAgICAgZnVsbEJ1Y2tldFJlc291cmNlUmVnZXgudGVzdChyZXNvbHZlZFJlc291cmNlU3RyaW5nKSAmJlxuICAgICAgIXJlc29sdmVkUmVzb3VyY2VTdHJpbmcuaW5jbHVkZXMoJy8nKVxuICAgICkge1xuICAgICAgbWF0Y2hlZEJ1Y2tldFJlc291cmNlID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgbWF0Y2hlZE9iamVjdHNSZXNvdXJjZSA9PT0gZmFsc2UgJiZcbiAgICAgIGZ1bGxCdWNrZXRPYmplY3RzUmVnZXgudGVzdChyZXNvbHZlZFJlc291cmNlU3RyaW5nKSAmJlxuICAgICAgcmVzb2x2ZWRSZXNvdXJjZVN0cmluZy5pbmRleE9mKCcvJykgPT09XG4gICAgICAgIHJlc29sdmVkUmVzb3VyY2VTdHJpbmcubGFzdEluZGV4T2YoJy8nKVxuICAgICkge1xuICAgICAgbWF0Y2hlZE9iamVjdHNSZXNvdXJjZSA9IHRydWU7XG4gICAgfVxuICAgIGlmIChtYXRjaGVkQnVja2V0UmVzb3VyY2UgPT09IHRydWUgJiYgbWF0Y2hlZE9iamVjdHNSZXNvdXJjZSA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cbiJdfQ==
;