aws-cdk
Version:
AWS CDK CLI, the command line tool for CDK apps
117 lines • 17.5 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.isHotswappableS3BucketDeploymentChange = isHotswappableS3BucketDeploymentChange;
exports.skipChangeForS3DeployCustomResourcePolicy = skipChangeForS3DeployCustomResourcePolicy;
/**
* This means that the value is required to exist by CloudFormation's Custom Resource API (or our S3 Bucket Deployment Lambda's API)
* but the actual value specified is irrelevant
*/
const REQUIRED_BY_CFN = 'required-to-be-present-by-cfn';
const CDK_BUCKET_DEPLOYMENT_CFN_TYPE = 'Custom::CDKBucketDeployment';
async function isHotswappableS3BucketDeploymentChange(logicalId, change, evaluateCfnTemplate) {
// In old-style synthesis, the policy used by the lambda to copy assets Ref's the assets directly,
// meaning that the changes made to the Policy are artifacts that can be safely ignored
const ret = [];
if (change.newValue.Type !== CDK_BUCKET_DEPLOYMENT_CFN_TYPE) {
return [];
}
// no classification to be done here; all the properties of this custom resource thing are hotswappable
const customResourceProperties = await evaluateCfnTemplate.evaluateCfnExpression({
...change.newValue.Properties,
ServiceToken: undefined,
});
// note that this gives the ARN of the lambda, not the name. This is fine though, the invoke() sdk call will take either
const functionName = await evaluateCfnTemplate.evaluateCfnExpression(change.newValue.Properties?.ServiceToken);
if (!functionName) {
return ret;
}
ret.push({
change: {
cause: change,
resources: [{
logicalId,
physicalName: customResourceProperties.DestinationBucketName,
resourceType: CDK_BUCKET_DEPLOYMENT_CFN_TYPE,
description: `Contents of AWS::S3::Bucket '${customResourceProperties.DestinationBucketName}'`,
metadata: evaluateCfnTemplate.metadataFor(logicalId),
}],
},
hotswappable: true,
service: 'custom-s3-deployment',
apply: async (sdk) => {
await sdk.lambda().invokeCommand({
FunctionName: functionName,
// Lambda refuses to take a direct JSON object and requires it to be stringify()'d
Payload: JSON.stringify({
RequestType: 'Update',
ResponseURL: REQUIRED_BY_CFN,
PhysicalResourceId: REQUIRED_BY_CFN,
StackId: REQUIRED_BY_CFN,
RequestId: REQUIRED_BY_CFN,
LogicalResourceId: REQUIRED_BY_CFN,
ResourceProperties: stringifyObject(customResourceProperties), // JSON.stringify() doesn't turn the actual objects to strings, but the lambda expects strings
}),
});
},
});
return ret;
}
async function skipChangeForS3DeployCustomResourcePolicy(iamPolicyLogicalId, change, evaluateCfnTemplate) {
if (change.newValue.Type !== 'AWS::IAM::Policy') {
return false;
}
const roles = change.newValue.Properties?.Roles;
// If no roles are referenced, the policy is definitely not used for a S3Deployment
if (!roles || !roles.length) {
return false;
}
// Check if every role this policy is referenced by is only used for a S3Deployment
for (const role of roles) {
const roleArn = await evaluateCfnTemplate.evaluateCfnExpression(role);
const roleLogicalId = await evaluateCfnTemplate.findLogicalIdForPhysicalName(roleArn);
// We must assume this role is used for something else, because we can't check it
if (!roleLogicalId) {
return false;
}
// Find all interesting reference to the role
const roleRefs = evaluateCfnTemplate
.findReferencesTo(roleLogicalId)
// we are not interested in the reference from the original policy - it always exists
.filter((roleRef) => !(roleRef.Type == 'AWS::IAM::Policy' && roleRef.LogicalId === iamPolicyLogicalId));
// Check if the role is only used for S3Deployment
// We know this is the case, if S3Deployment -> Lambda -> Role is satisfied for every reference
// And we have at least one reference.
const isRoleOnlyForS3Deployment = roleRefs.length >= 1 &&
roleRefs.every((roleRef) => {
if (roleRef.Type === 'AWS::Lambda::Function') {
const lambdaRefs = evaluateCfnTemplate.findReferencesTo(roleRef.LogicalId);
// Every reference must be to the custom resource and at least one reference must be present
return (lambdaRefs.length >= 1 && lambdaRefs.every((lambdaRef) => lambdaRef.Type === 'Custom::CDKBucketDeployment'));
}
return false;
});
// We have determined this role is used for something else, so we can't skip the change
if (!isRoleOnlyForS3Deployment) {
return false;
}
}
// We have checked that any use of this policy is only for S3Deployment and we can safely skip it
return true;
}
function stringifyObject(obj) {
if (obj == null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(stringifyObject);
}
if (typeof obj !== 'object') {
return obj.toString();
}
const ret = {};
for (const [k, v] of Object.entries(obj)) {
ret[k] = stringifyObject(v);
}
return ret;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiczMtYnVja2V0LWRlcGxveW1lbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiczMtYnVja2V0LWRlcGxveW1lbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBYUEsd0ZBd0RDO0FBRUQsOEZBdURDO0FBekhEOzs7R0FHRztBQUNILE1BQU0sZUFBZSxHQUFHLCtCQUErQixDQUFDO0FBRXhELE1BQU0sOEJBQThCLEdBQUcsNkJBQTZCLENBQUM7QUFFOUQsS0FBSyxVQUFVLHNDQUFzQyxDQUMxRCxTQUFpQixFQUNqQixNQUFzQixFQUN0QixtQkFBbUQ7SUFFbkQsa0dBQWtHO0lBQ2xHLHVGQUF1RjtJQUN2RixNQUFNLEdBQUcsR0FBb0IsRUFBRSxDQUFDO0lBRWhDLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssOEJBQThCLEVBQUUsQ0FBQztRQUM1RCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCx1R0FBdUc7SUFDdkcsTUFBTSx3QkFBd0IsR0FBRyxNQUFNLG1CQUFtQixDQUFDLHFCQUFxQixDQUFDO1FBQy9FLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxVQUFVO1FBQzdCLFlBQVksRUFBRSxTQUFTO0tBQ3hCLENBQUMsQ0FBQztJQUVILHdIQUF3SDtJQUN4SCxNQUFNLFlBQVksR0FBRyxNQUFNLG1CQUFtQixDQUFDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQy9HLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNsQixPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRCxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ1AsTUFBTSxFQUFFO1lBQ04sS0FBSyxFQUFFLE1BQU07WUFDYixTQUFTLEVBQUUsQ0FBQztvQkFDVixTQUFTO29CQUNULFlBQVksRUFBRSx3QkFBd0IsQ0FBQyxxQkFBcUI7b0JBQzVELFlBQVksRUFBRSw4QkFBOEI7b0JBQzVD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Q0FBQyxDQUFDO1FBRUwsdUZBQXVGO1FBQ3ZGLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1lBQy9CLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7SUFFRCxpR0FBaUc7SUFDakcsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsR0FBUTtJQUMvQixJQUFJLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNoQixPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFDRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN2QixPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUNELElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDNUIsT0FBTyxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDeEIsQ0FBQztJQUVELE1BQU0sR0FBRyxHQUF5QixFQUFFLENBQUM7SUFDckMsS0FBSyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN6QyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IEhvdHN3YXBDaGFuZ2UgfSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQgdHlwZSB7IFJlc291cmNlQ2hhbmdlIH0gZnJvbSAnLi4vLi4vLi4vLi4vQGF3cy1jZGsvdG1wLXRvb2xraXQtaGVscGVycy9zcmMvYXBpL2lvL3BheWxvYWRzL2hvdHN3YXAnO1xuaW1wb3J0IHR5cGUgeyBTREsgfSBmcm9tICcuLi9hd3MtYXV0aCc7XG5pbXBvcnQgdHlwZSB7IEV2YWx1YXRlQ2xvdWRGb3JtYXRpb25UZW1wbGF0ZSB9IGZyb20gJy4uL2Nsb3VkZm9ybWF0aW9uJztcblxuLyoqXG4gKiBUaGlzIG1lYW5zIHRoYXQgdGhlIHZhbHVlIGlzIHJlcXVpcmVkIHRvIGV4aXN0IGJ5IENsb3VkRm9ybWF0aW9uJ3MgQ3VzdG9tIFJlc291cmNlIEFQSSAob3Igb3VyIFMzIEJ1Y2tldCBEZXBsb3ltZW50IExhbWJkYSdzIEFQSSlcbiAqIGJ1dCB0aGUgYWN0dWFsIHZhbHVlIHNwZWNpZmllZCBpcyBpcnJlbGV2YW50XG4gKi9cbmNvbnN0IFJFUVVJUkVEX0JZX0NGTiA9ICdyZXF1aXJlZC10by1iZS1wcmVzZW50LWJ5LWNmbic7XG5cbmNvbnN0IENES19CVUNLRVRfREVQTE9ZTUVOVF9DRk5fVFlQRSA9ICdDdXN0b206OkNES0J1Y2tldERlcGxveW1lbnQnO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaXNIb3Rzd2FwcGFibGVTM0J1Y2tldERlcGxveW1lbnRDaGFuZ2UoXG4gIGxvZ2ljYWxJZDogc3RyaW5nLFxuICBjaGFuZ2U6IFJlc291cmNlQ2hhbmdlLFxuICBldmFsdWF0ZUNmblRlbXBsYXRlOiBFdmFsdWF0ZUNsb3VkRm9ybWF0aW9uVGVtcGxhdGUsXG4pOiBQcm9taXNlPEhvdHN3YXBDaGFuZ2VbXT4ge1xuICAvLyBJbiBvbGQtc3R5bGUgc3ludGhlc2lzLCB0aGUgcG9saWN5IHVzZWQgYnkgdGhlIGxhbWJkYSB0byBjb3B5IGFzc2V0cyBSZWYncyB0aGUgYXNzZXRzIGRpcmVjdGx5LFxuICAvLyBtZWFuaW5nIHRoYXQgdGhlIGNoYW5nZXMgbWFkZSB0byB0aGUgUG9saWN5IGFyZSBhcnRpZmFjdHMgdGhhdCBjYW4gYmUgc2FmZWx5IGlnbm9yZWRcbiAgY29uc3QgcmV0OiBIb3Rzd2FwQ2hhbmdlW10gPSBbXTtcblxuICBpZiAoY2hhbmdlLm5ld1ZhbHVlLlR5cGUgIT09IENES19CVUNLRVRfREVQTE9ZTUVOVF9DRk5fVFlQRSkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8vIG5vIGNsYXNzaWZpY2F0aW9uIHRvIGJlIGRvbmUgaGVyZTsgYWxsIHRoZSBwcm9wZXJ0aWVzIG9mIHRoaXMgY3VzdG9tIHJlc291cmNlIHRoaW5nIGFyZSBob3Rzd2FwcGFibGVcbiAgY29uc3QgY3VzdG9tUmVzb3VyY2VQcm9wZXJ0aWVzID0gYXdhaXQgZXZhbHVhdGVDZm5UZW1wbGF0ZS5ldmFsdWF0ZUNmbkV4cHJlc3Npb24oe1xuICAgIC4uLmNoYW5nZS5uZXdWYWx1ZS5Qcm9wZXJ0aWVzLFxuICAgIFNlcnZpY2VUb2tlbjogdW5kZWZpbmVkLFxuICB9KTtcblxuICAvLyBub3RlIHRoYXQgdGhpcyBnaXZlcyB0aGUgQVJOIG9mIHRoZSBsYW1iZGEsIG5vdCB0aGUgbmFtZS4gVGhpcyBpcyBmaW5lIHRob3VnaCwgdGhlIGludm9rZSgpIHNkayBjYWxsIHdpbGwgdGFrZSBlaXRoZXJcbiAgY29uc3QgZnVuY3Rpb25OYW1lID0gYXdhaXQgZXZhbHVhdGVDZm5UZW1wbGF0ZS5ldmFsdWF0ZUNmbkV4cHJlc3Npb24oY2hhbmdlLm5ld1ZhbHVlLlByb3BlcnRpZXM/LlNlcnZpY2VUb2tlbik7XG4gIGlmICghZnVuY3Rpb25OYW1lKSB7XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIHJldC5wdXNoKHtcbiAgICBjaGFuZ2U6IHtcbiAgICAgIGNhdXNlOiBjaGFuZ2UsXG4gICAgICByZXNvdXJjZXM6IFt7XG4gICAgICAgIGxvZ2ljYWxJZCxcbiAgICAgICAgcGh5c2ljYWxOYW1lOiBjdXN0b21SZXNvdXJjZVByb3BlcnRpZXMuRGVzdGluYXRpb25CdWNrZXROYW1lLFxuICAgICAgICByZXNvdXJjZVR5cGU6IENES19CVUNLRVRfREVQTE9ZTUVOVF9DRk5fVFlQRSxcbiAgICAgICAgZGVzY3JpcHRpb246IGBDb250ZW50cyBvZiBBV1M6OlMzOjpCdWNrZXQgJyR7Y3VzdG9tUmVzb3VyY2VQcm9wZXJ0aWVzLkRlc3RpbmF0aW9uQnVja2V0TmFtZX0nYCxcbiAgICAgICAgbWV0YWRhdGE6IGV2YWx1YXRlQ2ZuVGVtcGxhdGUubWV0YWRhdGFGb3IobG9naWNhbElkKSxcbiAgICAgIH1dLFxuICAgIH0sXG4gICAgaG90c3dhcHBhYmxlOiB0cnVlLFxuICAgIHNlcnZpY2U6ICdjdXN0b20tczMtZGVwbG95bWVudCcsXG4gICAgYXBwbHk6IGFzeW5jIChzZGs6IFNESykgPT4ge1xuICAgICAgYXdhaXQgc2RrLmxhbWJkYSgpLmludm9rZUNvbW1hbmQoe1xuICAgICAgICBGdW5jdGlvbk5hbWU6IGZ1bmN0aW9uTmFtZSxcbiAgICAgICAgLy8gTGFtYmRhIHJlZnVzZXMgdG8gdGFrZSBhIGRpcmVjdCBKU09OIG9iamVjdCBhbmQgcmVxdWlyZXMgaXQgdG8gYmUgc3RyaW5naWZ5KCknZFxuICAgICAgICBQYXlsb2FkOiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgUmVxdWVzdFR5cGU6ICdVcGRhdGUnLFxuICAgICAgICAgIFJlc3BvbnNlVVJMOiBSRVFVSVJFRF9CWV9DRk4sXG4gICAgICAgICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBSRVFVSVJFRF9CWV9DRk4sXG4gICAgICAgICAgU3RhY2tJZDogUkVRVUlSRURfQllfQ0ZOLFxuICAgICAgICAgIFJlcXVlc3RJZDogUkVRVUlSRURfQllfQ0ZOLFxuICAgICAgICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBSRVFVSVJFRF9CWV9DRk4sXG4gICAgICAgICAgUmVzb3VyY2VQcm9wZXJ0aWVzOiBzdHJpbmdpZnlPYmplY3QoY3VzdG9tUmVzb3VyY2VQcm9wZXJ0aWVzKSwgLy8gSlNPTi5zdHJpbmdpZnkoKSBkb2Vzbid0IHR1cm4gdGhlIGFjdHVhbCBvYmplY3RzIHRvIHN0cmluZ3MsIGJ1dCB0aGUgbGFtYmRhIGV4cGVjdHMgc3RyaW5nc1xuICAgICAgICB9KSxcbiAgICAgIH0pO1xuICAgIH0sXG4gIH0pO1xuXG4gIHJldHVybiByZXQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBza2lwQ2hhbmdlRm9yUzNEZXBsb3lDdXN0b21SZXNvdXJjZVBvbGljeShcbiAgaWFtUG9saWN5TG9naWNhbElkOiBzdHJpbmcsXG4gIGNoYW5nZTogUmVzb3VyY2VDaGFuZ2UsXG4gIGV2YWx1YXRlQ2ZuVGVtcGxhdGU6IEV2YWx1YXRlQ2xvdWRGb3JtYXRpb25UZW1wbGF0ZSxcbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBpZiAoY2hhbmdlLm5ld1ZhbHVlLlR5cGUgIT09ICdBV1M6OklBTTo6UG9saWN5Jykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBjb25zdCByb2xlczogc3RyaW5nW10gPSBjaGFuZ2UubmV3VmFsdWUuUHJvcGVydGllcz8uUm9sZXM7XG5cbiAgLy8gSWYgbm8gcm9sZXMgYXJlIHJlZmVyZW5jZWQsIHRoZSBwb2xpY3kgaXMgZGVmaW5pdGVseSBub3QgdXNlZCBmb3IgYSBTM0RlcGxveW1lbnRcbiAgaWYgKCFyb2xlcyB8fCAhcm9sZXMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLy8gQ2hlY2sgaWYgZXZlcnkgcm9sZSB0aGlzIHBvbGljeSBpcyByZWZlcmVuY2VkIGJ5IGlzIG9ubHkgdXNlZCBmb3IgYSBTM0RlcGxveW1lbnRcbiAgZm9yIChjb25zdCByb2xlIG9mIHJvbGVzKSB7XG4gICAgY29uc3Qgcm9sZUFybiA9IGF3YWl0IGV2YWx1YXRlQ2ZuVGVtcGxhdGUuZXZhbHVhdGVDZm5FeHByZXNzaW9uKHJvbGUpO1xuICAgIGNvbnN0IHJvbGVMb2dpY2FsSWQgPSBhd2FpdCBldmFsdWF0ZUNmblRlbXBsYXRlLmZpbmRMb2dpY2FsSWRGb3JQaHlzaWNhbE5hbWUocm9sZUFybik7XG5cbiAgICAvLyBXZSBtdXN0IGFzc3VtZSB0aGlzIHJvbGUgaXMgdXNlZCBmb3Igc29tZXRoaW5nIGVsc2UsIGJlY2F1c2Ugd2UgY2FuJ3QgY2hlY2sgaXRcbiAgICBpZiAoIXJvbGVMb2dpY2FsSWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBGaW5kIGFsbCBpbnRlcmVzdGluZyByZWZlcmVuY2UgdG8gdGhlIHJvbGVcbiAgICBjb25zdCByb2xlUmVmcyA9IGV2YWx1YXRlQ2ZuVGVtcGxhdGVcbiAgICAgIC5maW5kUmVmZXJlbmNlc1RvKHJvbGVMb2dpY2FsSWQpXG4gICAgICAvLyB3ZSBhcmUgbm90IGludGVyZXN0ZWQgaW4gdGhlIHJlZmVyZW5jZSBmcm9tIHRoZSBvcmlnaW5hbCBwb2xpY3kgLSBpdCBhbHdheXMgZXhpc3RzXG4gICAgICAuZmlsdGVyKChyb2xlUmVmKSA9PiAhKHJvbGVSZWYuVHlwZSA9PSAnQVdTOjpJQU06OlBvbGljeScgJiYgcm9sZVJlZi5Mb2dpY2FsSWQgPT09IGlhbVBvbGljeUxvZ2ljYWxJZCkpO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHJvbGUgaXMgb25seSB1c2VkIGZvciBTM0RlcGxveW1lbnRcbiAgICAvLyBXZSBrbm93IHRoaXMgaXMgdGhlIGNhc2UsIGlmIFMzRGVwbG95bWVudCAtPiBMYW1iZGEgLT4gUm9sZSBpcyBzYXRpc2ZpZWQgZm9yIGV2ZXJ5IHJlZmVyZW5jZVxuICAgIC8vIEFuZCB3ZSBoYXZlIGF0IGxlYXN0IG9uZSByZWZlcmVuY2UuXG4gICAgY29uc3QgaXNSb2xlT25seUZvclMzRGVwbG95bWVudCA9XG4gICAgICByb2xlUmVmcy5sZW5ndGggPj0gMSAmJlxuICAgICAgcm9sZVJlZnMuZXZlcnkoKHJvbGVSZWYpID0+IHtcbiAgICAgICAgaWYgKHJvbGVSZWYuVHlwZSA9PT0gJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicpIHtcbiAgICAgICAgICBjb25zdCBsYW1iZGFSZWZzID0gZXZhbHVhdGVDZm5UZW1wbGF0ZS5maW5kUmVmZXJlbmNlc1RvKHJvbGVSZWYuTG9naWNhbElkKTtcbiAgICAgICAgICAvLyBFdmVyeSByZWZlcmVuY2UgbXVzdCBiZSB0byB0aGUgY3VzdG9tIHJlc291cmNlIGFuZCBhdCBsZWFzdCBvbmUgcmVmZXJlbmNlIG11c3QgYmUgcHJlc2VudFxuICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBsYW1iZGFSZWZzLmxlbmd0aCA+PSAxICYmIGxhbWJkYVJlZnMuZXZlcnkoKGxhbWJkYVJlZikgPT4gbGFtYmRhUmVmLlR5cGUgPT09ICdDdXN0b206OkNES0J1Y2tldERlcGxveW1lbnQnKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSk7XG5cbiAgICAvLyBXZSBoYXZlIGRldGVybWluZWQgdGhpcyByb2xlIGlzIHVzZWQgZm9yIHNvbWV0aGluZyBlbHNlLCBzbyB3ZSBjYW4ndCBza2lwIHRoZSBjaGFuZ2VcbiAgICBpZiAoIWlzUm9sZU9ubHlGb3JTM0RlcGxveW1lbnQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvLyBXZSBoYXZlIGNoZWNrZWQgdGhhdCBhbnkgdXNlIG9mIHRoaXMgcG9saWN5IGlzIG9ubHkgZm9yIFMzRGVwbG95bWVudCBhbmQgd2UgY2FuIHNhZmVseSBza2lwIGl0XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBzdHJpbmdpZnlPYmplY3Qob2JqOiBhbnkpOiBhbnkge1xuICBpZiAob2JqID09IG51bGwpIHtcbiAgICByZXR1cm4gb2JqO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICByZXR1cm4gb2JqLm1hcChzdHJpbmdpZnlPYmplY3QpO1xuICB9XG4gIGlmICh0eXBlb2Ygb2JqICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiBvYmoudG9TdHJpbmcoKTtcbiAgfVxuXG4gIGNvbnN0IHJldDogeyBbazogc3RyaW5nXTogYW55IH0gPSB7fTtcbiAgZm9yIChjb25zdCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXMob2JqKSkge1xuICAgIHJldFtrXSA9IHN0cmluZ2lmeU9iamVjdCh2KTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuIl19
;