@k9securityio/k9-cdk
Version:
Provision strong AWS security policies easily using the AWS CDK.
141 lines • 23.5 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CloudFrontOACReadAccessGenerator = exports.SID_DENY_EVERYONE_ELSE = exports.SID_ALLOW_ROOT_AND_IDENTITY_POLICIES = void 0;
exports.makeKeyPolicy = makeKeyPolicy;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const iam = require("aws-cdk-lib/aws-iam");
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
const k9policy_1 = require("./k9policy");
let SUPPORTED_CAPABILITIES = new Array(k9policy_1.AccessCapability.ADMINISTER_RESOURCE, k9policy_1.AccessCapability.READ_CONFIG, k9policy_1.AccessCapability.READ_DATA, k9policy_1.AccessCapability.WRITE_DATA, k9policy_1.AccessCapability.DELETE_DATA);
exports.SID_ALLOW_ROOT_AND_IDENTITY_POLICIES = 'Allow Root User to Administer Key And Identity Policies';
exports.SID_DENY_EVERYONE_ELSE = 'DenyEveryoneElse';
/**
* Generate key policy statements to enable the CloudFront service to read encrypted S3 bucket object data (only)
* from within a <a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html#sse-kms">CloudFront OAC integration</a>.
*/
class CloudFrontOACReadAccessGenerator {
constructor(distributionArn) {
this.distributionArn = distributionArn;
}
makeAllowStatements() {
return [new aws_iam_1.PolicyStatement({
sid: CloudFrontOACReadAccessGenerator.SID_ALLOW_CLOUDFRONT_SVC_READ_DATA,
effect: aws_iam_1.Effect.ALLOW,
principals: [new aws_iam_1.ServicePrincipal('cloudfront.amazonaws.com')],
actions: ['kms:Decrypt'],
resources: ['*'],
conditions: {
StringEquals: { 'aws:SourceArn': this.distributionArn },
},
}),
new aws_iam_1.PolicyStatement({
sid: CloudFrontOACReadAccessGenerator.SID_ALLOW_CLOUDFRONT_IAM_ROLE_READ_DATA,
effect: aws_iam_1.Effect.ALLOW,
principals: [new aws_iam_1.AnyPrincipal()],
actions: ['kms:Decrypt'],
resources: ['*'],
conditions: {
// use ArnEquals condition instead of a plain Principal element in case
// the CloudFront service recreates the role.
// conditions bind against the principal ARN at runtime.
// the principal element binds (once) to the principal's canonical userid at policy definition time.
ArnEquals: {
'aws:PrincipalArn': 'arn:aws:iam::856369053181:role/OriginAccessControlRole',
},
},
})];
}
makeConditionsToExceptFromDenyEveryoneElse() {
// return a (TypeScript) Record of the form:
// {"Operator": { "keyInRequestContext": "value" } }
return { StringNotEqualsIfExists: { 'aws:PrincipalServiceName': 'cloudfront.amazonaws.com' } };
}
}
exports.CloudFrontOACReadAccessGenerator = CloudFrontOACReadAccessGenerator;
_a = JSII_RTTI_SYMBOL_1;
CloudFrontOACReadAccessGenerator[_a] = { fqn: "@k9securityio/k9-cdk.kms.CloudFrontOACReadAccessGenerator", version: "2.2.1" };
CloudFrontOACReadAccessGenerator.SID_ALLOW_CLOUDFRONT_SVC_READ_DATA = 'Allow CloudFront Service read-data';
CloudFrontOACReadAccessGenerator.SID_ALLOW_CLOUDFRONT_IAM_ROLE_READ_DATA = 'Allow CloudFront IAM role read-data';
function makeKeyPolicy(props) {
const policyFactory = new k9policy_1.K9PolicyFactory();
const policy = new iam.PolicyDocument();
const resourceArns = ['*'];
let accessSpecsByCapabilityRecs = policyFactory.mergeDesiredAccessSpecsByCapability(SUPPORTED_CAPABILITIES, props.k9DesiredAccess);
let accessSpecsByCapability = new Map();
for (let [capabilityStr, accessSpec] of Object.entries(accessSpecsByCapabilityRecs)) {
accessSpecsByCapability.set((0, k9policy_1.getAccessCapabilityFromValue)(capabilityStr), accessSpec);
}
if (!(0, k9policy_1.canPrincipalsManageResources)(accessSpecsByCapability)) {
throw Error('At least one principal must be able to administer and read-config for keys' +
' so encrypted data remains accessible; found:\n' +
`administer-resource: '${accessSpecsByCapability.get(k9policy_1.AccessCapability.ADMINISTER_RESOURCE)?.allowPrincipalArns}'\n` +
`read-config: '${accessSpecsByCapability.get(k9policy_1.AccessCapability.READ_CONFIG)?.allowPrincipalArns}'`);
}
const allowStatements = policyFactory.makeAllowStatements('KMS', SUPPORTED_CAPABILITIES, Array.from(accessSpecsByCapability.values()), resourceArns);
policy.addStatements(...allowStatements);
if (props.awsServiceAccessGenerators) {
for (let serviceAccessSpec of props.awsServiceAccessGenerators) {
policy.addStatements(...serviceAccessSpec.makeAllowStatements());
}
}
//console.log(`trustAccountIdentities: ${props.trustAccountIdentities}`);
// Allow root user and control access via Identity policy by aligning to Key's behavior:
if (props.trustAccountIdentities) {
//console.log('Adding Allow root and DenyEveryoneElse statements');
const denyEveryoneElseStatement = new aws_iam_1.PolicyStatement({
sid: exports.SID_DENY_EVERYONE_ELSE,
effect: aws_iam_1.Effect.DENY,
principals: policyFactory.makeDenyEveryoneElsePrincipals(),
actions: ['kms:*'],
resources: resourceArns,
});
denyEveryoneElseStatement.addCondition('Bool', {
'aws:PrincipalIsAWSService': ['false'],
'kms:GrantIsForAWSResource': ['false'],
});
const denyEveryoneElseTest = policyFactory.wasLikeUsed(props.k9DesiredAccess) ?
'ArnNotLike' :
'ArnNotEquals';
const allAllowedPrincipalArns = policyFactory.getAllowedPrincipalArns(props.k9DesiredAccess);
const accountRootPrincipal = new aws_iam_1.AccountRootPrincipal();
denyEveryoneElseStatement.addCondition(denyEveryoneElseTest, {
'aws:PrincipalArn': [
// Place Root Principal arn in stable, prominent position;
// will render as an object Fn::Join'ing Partition & AccountId
accountRootPrincipal.arn,
...allAllowedPrincipalArns,
],
});
policy.addStatements(
// add AllowRootUserToAdministerKey statement and enable access granted via Identity policies
new aws_iam_1.PolicyStatement({
sid: exports.SID_ALLOW_ROOT_AND_IDENTITY_POLICIES,
effect: aws_iam_1.Effect.ALLOW,
principals: [accountRootPrincipal],
actions: ['kms:*'],
resources: resourceArns,
}), denyEveryoneElseStatement);
}
else {
// Omit Allow Root & DenyEveryoneElse statement
//
// Instead, implement least privilege by relying on KMS' special behavior that
// enables granting access solely via a KMS key policy, *irrespective of* Identity policy.
//
// See: https://docs.aws.amazon.com/kms/latest/developerguide/control-access-overview.html#managing-access
// "To allow access to a KMS key, you must use the key policy,
// *either alone* or in combination with IAM policies or grants.
// IAM policies by themselves are not sufficient to allow access to a KMS key,
// though you can use them in combination with a key policy."
//
//console.log('Omitting Allow root and DenyEveryoneElse statements');
}
const denyUntrustedOrgsStatement = policyFactory._makeDenyUntrustedOrgsStatement('KMS', SUPPORTED_CAPABILITIES, accessSpecsByCapability, resourceArns);
if (denyUntrustedOrgsStatement) {
policy.addStatements(denyUntrustedOrgsStatement);
}
policy.validateForResourcePolicy();
return policy;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia21zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ttcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBNkZBLHNDQW9HQzs7QUFqTUQsMkNBQTJDO0FBQzNDLGlEQU82QjtBQUM3Qix5Q0FPb0I7QUFjcEIsSUFBSSxzQkFBc0IsR0FBRyxJQUFJLEtBQUssQ0FDcEMsMkJBQWdCLENBQUMsbUJBQW1CLEVBQ3BDLDJCQUFnQixDQUFDLFdBQVcsRUFDNUIsMkJBQWdCLENBQUMsU0FBUyxFQUMxQiwyQkFBZ0IsQ0FBQyxVQUFVLEVBQzNCLDJCQUFnQixDQUFDLFdBQVcsQ0FDN0IsQ0FBQztBQUVXLFFBQUEsb0NBQW9DLEdBQUcseURBQXlELENBQUM7QUFDakcsUUFBQSxzQkFBc0IsR0FBRyxrQkFBa0IsQ0FBQztBQUV6RDs7O0dBR0c7QUFDSCxNQUFhLGdDQUFnQztJQU8zQyxZQUFZLGVBQXVCO1FBQ2pDLElBQUksQ0FBQyxlQUFlLEdBQUcsZUFBZSxDQUFDO0lBQ3pDLENBQUM7SUFFRCxtQkFBbUI7UUFDakIsT0FBTyxDQUFDLElBQUkseUJBQWUsQ0FBQztnQkFDMUIsR0FBRyxFQUFFLGdDQUFnQyxDQUFDLGtDQUFrQztnQkFDeEUsTUFBTSxFQUFFLGdCQUFNLENBQUMsS0FBSztnQkFDcEIsVUFBVSxFQUFFLENBQUMsSUFBSSwwQkFBZ0IsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO2dCQUM5RCxPQUFPLEVBQUUsQ0FBQyxhQUFhLENBQUM7Z0JBQ3hCLFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQztnQkFDaEIsVUFBVSxFQUFFO29CQUNWLFlBQVksRUFBRSxFQUFFLGVBQWUsRUFBRSxJQUFJLENBQUMsZUFBZSxFQUFFO2lCQUN4RDthQUNGLENBQUM7WUFDRixJQUFJLHlCQUFlLENBQUM7Z0JBQ2xCLEdBQUcsRUFBRSxnQ0FBZ0MsQ0FBQyx1Q0FBdUM7Z0JBQzdFLE1BQU0sRUFBRSxnQkFBTSxDQUFDLEtBQUs7Z0JBQ3BCLFVBQVUsRUFB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QUFDO0lBRUQsTUFBTSwwQkFBMEIsR0FBRyxhQUFhLENBQUMsK0JBQStCLENBQzlFLEtBQUssRUFBRSxzQkFBc0IsRUFBRSx1QkFBdUIsRUFBRSxZQUFZLENBQUMsQ0FBQztJQUN4RSxJQUFJLDBCQUEwQixFQUFFLENBQUM7UUFDL0IsTUFBTSxDQUFDLGFBQWEsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBQ25ELENBQUM7SUFFRCxNQUFNLENBQUMseUJBQXlCLEVBQUUsQ0FBQztJQUVuQyxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHtcbiAgQWNjb3VudFJvb3RQcmluY2lwYWwsIEFueVByaW5jaXBhbCxcbiAgQ29uZGl0aW9ucyxcbiAgRWZmZWN0LFxuICBQb2xpY3lEb2N1bWVudCxcbiAgUG9saWN5U3RhdGVtZW50LFxuICBTZXJ2aWNlUHJpbmNpcGFsLFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7XG4gIEFjY2Vzc0NhcGFiaWxpdHksXG4gIGNhblByaW5jaXBhbHNNYW5hZ2VSZXNvdXJjZXMsXG4gIGdldEFjY2Vzc0NhcGFiaWxpdHlGcm9tVmFsdWUsXG4gIElBY2Nlc3NTcGVjLFxuICBJQVdTU2VydmljZUFjY2Vzc0dlbmVyYXRvcixcbiAgSzlQb2xpY3lGYWN0b3J5LFxufSBmcm9tICcuL2s5cG9saWN5JztcblxuZXhwb3J0IGludGVyZmFjZSBLOUtleVBvbGljeVByb3BzIHtcbiAgcmVhZG9ubHkgazlEZXNpcmVkQWNjZXNzOiBBcnJheTxJQWNjZXNzU3BlYz47XG4gIHJlYWRvbmx5IHRydXN0QWNjb3VudElkZW50aXRpZXM/OiBib29sZWFuO1xuICAvKipcbiAgICogQW4gKG9wdGlvbmFsKSBhcnJheSBvZiBJQVdTU2VydmljZUFjY2Vzc0dlbmVyYXRvciBpbnN0YW5jZXMgd2hpY2ggd2lsbCBnZW5lcmF0ZSBzdGF0ZW1lbnRzIHRvIGFsbG93IGFjY2VzcyB0byB0aGVcbiAgICoga2V5IGJ5IGFuIEFXUyBzZXJ2aWNlIGxpa2UgQ2xvdWRGcm9udCBvciBLaW5lc2lzLlxuICAgKlxuICAgKiBAZGVmYXVsdCB1bmRlZmluZWRcbiAgICovXG4gIHJlYWRvbmx5IGF3c1NlcnZpY2VBY2Nlc3NHZW5lcmF0b3JzPzogQXJyYXk8SUFXU1NlcnZpY2VBY2Nlc3NHZW5lcmF0b3I+O1xufVxuXG5sZXQgU1VQUE9SVEVEX0NBUEFCSUxJVElFUyA9IG5ldyBBcnJheTxBY2Nlc3NDYXBhYmlsaXR5PihcbiAgQWNjZXNzQ2FwYWJpbGl0eS5BRE1JTklTVEVSX1JFU09VUkNFLFxuICBBY2Nlc3NDYXBhYmlsaXR5LlJFQURfQ09ORklHLFxuICBBY2Nlc3NDYXBhYmlsaXR5LlJFQURfREFUQSxcbiAgQWNjZXNzQ2FwYWJpbGl0eS5XUklURV9EQVRBLFxuICBBY2Nlc3NDYXBhYmlsaXR5LkRFTEVURV9EQVRBLFxuKTtcblxuZXhwb3J0IGNvbnN0IFNJRF9BTExPV19ST09UX0FORF9JREVOVElUWV9QT0xJQ0lFUyA9ICdBbGxvdyBSb290IFVzZXIgdG8gQWRtaW5pc3RlciBLZXkgQW5kIElkZW50aXR5IFBvbGljaWVzJztcbmV4cG9ydCBjb25zdCBTSURfREVOWV9FVkVSWU9ORV9FTFNFID0gJ0RlbnlFdmVyeW9uZUVsc2UnO1xuXG4vKipcbiAqIEdlbmVyYXRlIGtleSBwb2xpY3kgc3RhdGVtZW50cyB0byBlbmFibGUgdGhlIENsb3VkRnJvbnQgc2VydmljZSB0byByZWFkIGVuY3J5cHRlZCBTMyBidWNrZXQgb2JqZWN0IGRhdGEgKG9ubHkpXG4gKiBmcm9tIHdpdGhpbiBhIDxhIGhyZWY9XCJodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRGcm9udC9sYXRlc3QvRGV2ZWxvcGVyR3VpZGUvcHJpdmF0ZS1jb250ZW50LXJlc3RyaWN0aW5nLWFjY2Vzcy10by1zMy5odG1sI3NzZS1rbXNcIj5DbG91ZEZyb250IE9BQyBpbnRlZ3JhdGlvbjwvYT4uXG4gKi9cbmV4cG9ydCBjbGFzcyBDbG91ZEZyb250T0FDUmVhZEFjY2Vzc0dlbmVyYXRvciBpbXBsZW1lbnRzIElBV1NTZXJ2aWNlQWNjZXNzR2VuZXJhdG9yIHtcblxuICBzdGF0aWMgcmVhZG9ubHkgU0lEX0FMTE9XX0NMT1VERlJPTlRfU1ZDX1JFQURfREFUQSA9ICdBbGxvdyBDbG91ZEZyb250IFNlcnZpY2UgcmVhZC1kYXRhJztcbiAgc3RhdGljIHJlYWRvbmx5IFNJRF9BTExPV19DTE9VREZST05UX0lBTV9ST0xFX1JFQURfREFUQSA9ICdBbGxvdyBDbG91ZEZyb250IElBTSByb2xlIHJlYWQtZGF0YSc7XG5cbiAgcmVhZG9ubHkgZGlzdHJpYnV0aW9uQXJuOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoZGlzdHJpYnV0aW9uQXJuOiBzdHJpbmcpIHtcbiAgICB0aGlzLmRpc3RyaWJ1dGlvbkFybiA9IGRpc3RyaWJ1dGlvbkFybjtcbiAgfVxuXG4gIG1ha2VBbGxvd1N0YXRlbWVudHMoKTogQXJyYXk8UG9saWN5U3RhdGVtZW50PiB7XG4gICAgcmV0dXJuIFtuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIHNpZDogQ2xvdWRGcm9udE9BQ1JlYWRBY2Nlc3NHZW5lcmF0b3IuU0lEX0FMTE9XX0NMT1VERlJPTlRfU1ZDX1JFQURfREFUQSxcbiAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgcHJpbmNpcGFsczogW25ldyBTZXJ2aWNlUHJpbmNpcGFsKCdjbG91ZGZyb250LmFtYXpvbmF3cy5jb20nKV0sXG4gICAgICBhY3Rpb25zOiBbJ2ttczpEZWNyeXB0J10sXG4gICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgY29uZGl0aW9uczoge1xuICAgICAgICBTdHJpbmdFcXVhbHM6IHsgJ2F3czpTb3VyY2VBcm4nOiB0aGlzLmRpc3RyaWJ1dGlvbkFybiB9LFxuICAgICAgfSxcbiAgICB9KSxcbiAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIHNpZDogQ2xvdWRGcm9udE9BQ1JlYWRBY2Nlc3NHZW5lcmF0b3IuU0lEX0FMTE9XX0NMT1VERlJPTlRfSUFNX1JPTEVfUkVBRF9EQVRBLFxuICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICBwcmluY2lwYWxzOiBbbmV3IEFueVByaW5jaXBhbCgpXSxcbiAgICAgIGFjdGlvbnM6IFsna21zOkRlY3J5cHQnXSxcbiAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgICBjb25kaXRpb25zOiB7XG4gICAgICAgIC8vIHVzZSBBcm5FcXVhbHMgY29uZGl0aW9uIGluc3RlYWQgb2YgYSBwbGFpbiBQcmluY2lwYWwgZWxlbWVudCBpbiBjYXNlXG4gICAgICAgIC8vIHRoZSBDbG91ZEZyb250IHNlcnZpY2UgcmVjcmVhdGVzIHRoZSByb2xlLlxuICAgICAgICAvLyBjb25kaXRpb25zIGJpbmQgYWdhaW5zdCB0aGUgcHJpbmNpcGFsIEFSTiBhdCBydW50aW1lLlxuICAgICAgICAvLyB0aGUgcHJpbmNpcGFsIGVsZW1lbnQgYmluZHMgKG9uY2UpIHRvIHRoZSBwcmluY2lwYWwncyBjYW5vbmljYWwgdXNlcmlkIGF0IHBvbGljeSBkZWZpbml0aW9uIHRpbWUuXG4gICAgICAgIEFybkVxdWFsczoge1xuICAgICAgICAgICdhd3M6UHJpbmNpcGFsQXJuJzogJ2Fybjphd3M6aWFtOjo4NTYzNjkwNTMxODE6cm9sZS9PcmlnaW5BY2Nlc3NDb250cm9sUm9sZScsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pXTtcbiAgfVxuXG4gIG1ha2VDb25kaXRpb25zVG9FeGNlcHRGcm9tRGVueUV2ZXJ5b25lRWxzZSgpOiBDb25kaXRpb25zIHtcbiAgICAvLyByZXR1cm4gYSAoVHlwZVNjcmlwdCkgUmVjb3JkIG9mIHRoZSBmb3JtOlxuICAgIC8vICAgICB7XCJPcGVyYXRvclwiOiB7IFwia2V5SW5SZXF1ZXN0Q29udGV4dFwiOiBcInZhbHVlXCIgfSB9XG4gICAgcmV0dXJuIHsgU3RyaW5nTm90RXF1YWxzSWZFeGlzdHM6IHsgJ2F3czpQcmluY2lwYWxTZXJ2aWNlTmFtZSc6ICdjbG91ZGZyb250LmFtYXpvbmF3cy5jb20nIH0gfTtcbiAgfVxufVxuXG5cbmV4cG9ydCBmdW5jdGlvbiBtYWtlS2V5UG9saWN5KHByb3BzOiBLOUtleVBvbGljeVByb3BzKTogUG9saWN5RG9jdW1lbnQge1xuICBjb25zdCBwb2xpY3lGYWN0b3J5ID0gbmV3IEs5UG9saWN5RmFjdG9yeSgpO1xuICBjb25zdCBwb2xpY3kgPSBuZXcgaWFtLlBvbGljeURvY3VtZW50KCk7XG5cbiAgY29uc3QgcmVzb3VyY2VBcm5zID0gWycqJ107XG5cbiAgbGV0IGFjY2Vzc1NwZWNzQnlDYXBhYmlsaXR5UmVjcyA9IHBvbGljeUZhY3RvcnkubWVyZ2VEZXNpcmVkQWNjZXNzU3BlY3NCeUNhcGFiaWxpdHkoU1VQUE9SVEVEX0NBUEFCSUxJVElFUywgcHJvcHMuazlEZXNpcmVkQWNjZXNzKTtcbiAgbGV0IGFjY2Vzc1NwZWNzQnlDYXBhYmlsaXR5OiBNYXA8QWNjZXNzQ2FwYWJpbGl0eSwgSUFjY2Vzc1NwZWM+ID0gbmV3IE1hcCgpO1xuXG4gIGZvciAobGV0IFtjYXBhYmlsaXR5U3RyLCBhY2Nlc3NTcGVjXSBvZiBPYmplY3QuZW50cmllcyhhY2Nlc3NTcGVjc0J5Q2FwYWJpbGl0eVJlY3MpKSB7XG4gICAgYWNjZXNzU3BlY3NCeUNhcGFiaWxpdHkuc2V0KGdldEFjY2Vzc0NhcGFiaWxpdHlGcm9tVmFsdWUoY2FwYWJpbGl0eVN0ciksIGFjY2Vzc1NwZWMpO1xuICB9XG5cbiAgaWYgKCFjYW5QcmluY2lwYWxzTWFuYWdlUmVzb3VyY2VzKGFjY2Vzc1NwZWNzQnlDYXBhYmlsaXR5KSkge1xuICAgIHRocm93IEVycm9yKCdBdCBsZWFzdCBvbmUgcHJpbmNpcGFsIG11c3QgYmUgYWJsZSB0byBhZG1pbmlzdGVyIGFuZCByZWFkLWNvbmZpZyBmb3Iga2V5cycgK1xuICAgICAgICAgICAgJyBzbyBlbmNyeXB0ZWQgZGF0YSByZW1haW5zIGFjY2Vzc2libGU7IGZvdW5kOlxcbicgK1xuICAgICAgICAgICAgYGFkbWluaXN0ZXItcmVzb3VyY2U6ICcke2FjY2Vzc1NwZWNzQnlDYXBhYmlsaXR5LmdldChBY2Nlc3NDYXBhYmlsaXR5LkFETUlOSVNURVJfUkVTT1VSQ0UpPy5hbGxvd1ByaW5jaXBhbEFybnN9J1xcbmAgK1xuICAgICAgICAgICAgYHJlYWQtY29uZmlnOiAnJHthY2Nlc3NTcGVjc0J5Q2FwYWJpbGl0eS5nZXQoQWNjZXNzQ2FwYWJpbGl0eS5SRUFEX0NPTkZJRyk/LmFsbG93UHJpbmNpcGFsQXJuc30nYCxcbiAgICApO1xuICB9XG5cbiAgY29uc3QgYWxsb3dTdGF0ZW1lbnRzID0gcG9saWN5RmFjdG9yeS5tYWtlQWxsb3dTdGF0ZW1lbnRzKCdLTVMnLFxuICAgIFNVUFBPUlRFRF9DQVBBQklMSVRJRVMsXG4gICAgQXJyYXkuZnJvbShhY2Nlc3NTcGVjc0J5Q2FwYWJpbGl0eS52YWx1ZXMoKSksXG4gICAgcmVzb3VyY2VBcm5zKTtcbiAgcG9saWN5LmFkZFN0YXRlbWVudHMoLi4uYWxsb3dTdGF0ZW1lbnRzKTtcblxuICBpZiAocHJvcHMuYXdzU2VydmljZUFjY2Vzc0dlbmVyYXRvcnMpIHtcbiAgICBmb3IgKGxldCBzZXJ2aWNlQWNjZXNzU3BlYyBvZiBwcm9wcy5hd3NTZXJ2aWNlQWNjZXNzR2VuZXJhdG9ycykge1xuICAgICAgcG9saWN5LmFkZFN0YXRlbWVudHMoLi4uc2VydmljZUFjY2Vzc1NwZWMubWFrZUFsbG93U3RhdGVtZW50cygpKTtcbiAgICB9XG4gIH1cblxuICAvL2NvbnNvbGUubG9nKGB0cnVzdEFjY291bnRJZGVudGl0aWVzOiAke3Byb3BzLnRydXN0QWNjb3VudElkZW50aXRpZXN9YCk7XG5cbiAgLy8gQWxsb3cgcm9vdCB1c2VyIGFuZCBjb250cm9sIGFjY2VzcyB2aWEgSWRlbnRpdHkgcG9saWN5IGJ5IGFsaWduaW5nIHRvIEtleSdzIGJlaGF2aW9yOlxuICBpZiAocHJvcHMudHJ1c3RBY2NvdW50SWRlbnRpdGllcykge1xuICAgIC8vY29uc29sZS5sb2coJ0FkZGluZyBBbGxvdyByb290IGFuZCBEZW55RXZlcnlvbmVFbHNlIHN0YXRlbWVudHMnKTtcbiAgICBjb25zdCBkZW55RXZlcnlvbmVFbHNlU3RhdGVtZW50ID0gbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICBzaWQ6IFNJRF9ERU5ZX0VWRVJZT05FX0VMU0UsXG4gICAgICBlZmZlY3Q6IEVmZmVjdC5ERU5ZLFxuICAgICAgcHJpbmNpcGFsczogcG9saWN5RmFjdG9yeS5tYWtlRGVueUV2ZXJ5b25lRWxzZVByaW5jaXBhbHMoKSxcbiAgICAgIGFjdGlvbnM6IFsna21zOionXSxcbiAgICAgIHJlc291cmNlczogcmVzb3VyY2VBcm5zLFxuICAgIH0pO1xuICAgIGRlbnlFdmVyeW9uZUVsc2VTdGF0ZW1lbnQuYWRkQ29uZGl0aW9uKCdCb29sJywge1xuICAgICAgJ2F3czpQcmluY2lwYWxJc0FXU1NlcnZpY2UnOiBbJ2ZhbHNlJ10sXG4gICAgICAna21zOkdyYW50SXNGb3JBV1NSZXNvdXJjZSc6IFsnZmFsc2UnXSxcbiAgICB9KTtcbiAgICBjb25zdCBkZW55RXZlcnlvbmVFbHNlVGVzdCA9IHBvbGljeUZhY3Rvcnkud2FzTGlrZVVzZWQocHJvcHMuazlEZXNpcmVkQWNjZXNzKSA/XG4gICAgICAnQXJuTm90TGlrZScgOlxuICAgICAgJ0Fybk5vdEVxdWFscyc7XG4gICAgY29uc3QgYWxsQWxsb3dlZFByaW5jaXBhbEFybnMgPSBwb2xpY3lGYWN0b3J5LmdldEFsbG93ZWRQcmluY2lwYWxBcm5zKHByb3BzLms5RGVzaXJlZEFjY2Vzcyk7XG4gICAgY29uc3QgYWNjb3VudFJvb3RQcmluY2lwYWwgPSBuZXcgQWNjb3VudFJvb3RQcmluY2lwYWwoKTtcbiAgICBkZW55RXZlcnlvbmVFbHNlU3RhdGVtZW50LmFkZENvbmRpdGlvbihkZW55RXZlcnlvbmVFbHNlVGVzdCwge1xuICAgICAgJ2F3czpQcmluY2lwYWxBcm4nOiBbXG4gICAgICAgIC8vIFBsYWNlIFJvb3QgUHJpbmNpcGFsIGFybiBpbiBzdGFibGUsIHByb21pbmVudCBwb3NpdGlvbjtcbiAgICAgICAgLy8gd2lsbCByZW5kZXIgYXMgYW4gb2JqZWN0IEZuOjpKb2luJ2luZyBQYXJ0aXRpb24gJiBBY2NvdW50SWRcbiAgICAgICAgYWNjb3VudFJvb3RQcmluY2lwYWwuYXJuLFxuICAgICAgICAuLi5hbGxBbGxvd2VkUHJpbmNpcGFsQXJucyxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICBwb2xpY3kuYWRkU3RhdGVtZW50cyhcbiAgICAgIC8vIGFkZCBBbGxvd1Jvb3RVc2VyVG9BZG1pbmlzdGVyS2V5IHN0YXRlbWVudCBhbmQgZW5hYmxlIGFjY2VzcyBncmFudGVkIHZpYSBJZGVudGl0eSBwb2xpY2llc1xuICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIHNpZDogU0lEX0FMTE9XX1JPT1RfQU5EX0lERU5USVRZX1BPTElDSUVTLFxuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgcHJpbmNpcGFsczogW2FjY291bnRSb290UHJpbmNpcGFsXSxcbiAgICAgICAgYWN0aW9uczogWydrbXM6KiddLFxuICAgICAgICByZXNvdXJjZXM6IHJlc291cmNlQXJucyxcbiAgICAgIH0pXG4gICAgICAsIGRlbnlFdmVyeW9uZUVsc2VTdGF0ZW1lbnQsXG4gICAgKTtcbiAgfSBlbHNlIHtcblxuICAgIC8vIE9taXQgQWxsb3cgUm9vdCAmIERlbnlFdmVyeW9uZUVsc2Ugc3RhdGVtZW50XG4gICAgLy9cbiAgICAvLyBJbnN0ZWFkLCBpbXBsZW1lbnQgbGVhc3QgcHJpdmlsZWdlIGJ5IHJlbHlpbmcgb24gS01TJyBzcGVjaWFsIGJlaGF2aW9yIHRoYXRcbiAgICAvLyBlbmFibGVzIGdyYW50aW5nIGFjY2VzcyBzb2xlbHkgdmlhIGEgS01TIGtleSBwb2xpY3ksICppcnJlc3BlY3RpdmUgb2YqIElkZW50aXR5IHBvbGljeS5cbiAgICAvL1xuICAgIC8vIFNlZTogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2ttcy9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvY29udHJvbC1hY2Nlc3Mtb3ZlcnZpZXcuaHRtbCNtYW5hZ2luZy1hY2Nlc3NcbiAgICAvLyBcIlRvIGFsbG93IGFjY2VzcyB0byBhIEtNUyBrZXksIHlvdSBtdXN0IHVzZSB0aGUga2V5IHBvbGljeSxcbiAgICAvLyAgKmVpdGhlciBhbG9uZSogb3IgaW4gY29tYmluYXRpb24gd2l0aCBJQU0gcG9saWNpZXMgb3IgZ3JhbnRzLlxuICAgIC8vICBJQU0gcG9saWNpZXMgYnkgdGhlbXNlbHZlcyBhcmUgbm90IHN1ZmZpY2llbnQgdG8gYWxsb3cgYWNjZXNzIHRvIGEgS01TIGtleSxcbiAgICAvLyAgdGhvdWdoIHlvdSBjYW4gdXNlIHRoZW0gaW4gY29tYmluYXRpb24gd2l0aCBhIGtleSBwb2xpY3kuXCJcbiAgICAvL1xuXG4gICAgLy9jb25zb2xlLmxvZygnT21pdHRpbmcgQWxsb3cgcm9vdCBhbmQgRGVueUV2ZXJ5b25lRWxzZSBzdGF0ZW1lbnRzJyk7XG4gIH1cblxuICBjb25zdCBkZW55VW50cnVzdGVkT3Jnc1N0YXRlbWVudCA9IHBvbGljeUZhY3RvcnkuX21ha2VEZW55VW50cnVzdGVkT3Jnc1N0YXRlbWVudChcbiAgICAnS01TJywgU1VQUE9SVEVEX0NBUEFCSUxJVElFUywgYWNjZXNzU3BlY3NCeUNhcGFiaWxpdHksIHJlc291cmNlQXJucyk7XG4gIGlmIChkZW55VW50cnVzdGVkT3Jnc1N0YXRlbWVudCkge1xuICAgIHBvbGljeS5hZGRTdGF0ZW1lbnRzKGRlbnlVbnRydXN0ZWRPcmdzU3RhdGVtZW50KTtcbiAgfVxuXG4gIHBvbGljeS52YWxpZGF0ZUZvclJlc291cmNlUG9saWN5KCk7XG5cbiAgcmV0dXJuIHBvbGljeTtcbn1cbiJdfQ==