@darren-valent/cdk-ec2-key-pair
Version:
CDK Construct for managing EC2 key pairs
238 lines • 35 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.KeyPair = exports.PublicKeyFormat = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const constructs_1 = require("constructs");
const path = require("path");
const resourceType = 'Custom::EC2-Key-Pair';
const ID = `CFN::Resource::${resourceType}`;
const createdByTag = 'CreatedByCfnCustomResource';
const cleanID = ID.replace(/:+/g, '-');
const lambdaTimeout = 3; // minutes
var PublicKeyFormat;
(function (PublicKeyFormat) {
PublicKeyFormat["OPENSSH"] = "OPENSSH";
PublicKeyFormat["PEM"] = "PEM";
})(PublicKeyFormat || (exports.PublicKeyFormat = PublicKeyFormat = {}));
/**
* An EC2 Key Pair
*/
class KeyPair extends constructs_1.Construct {
/**
* Defines a new EC2 Key Pair. The private key will be stored in AWS Secrets Manager
*/
constructor(scope, id, props) {
super(scope, id);
/**
* ARN of the private key in AWS Secrets Manager
*/
this.privateKeyArn = '';
/**
* ARN of the public key in AWS Secrets Manager
*/
this.publicKeyArn = '';
/**
* The public key.
*
* Only filled, when `exposePublicKey = true`
*/
this.publicKeyValue = '';
/**
* Name of the Key Pair
*/
this.keyPairName = '';
/**
* ID of the Key Pair
*/
this.keyPairID = '';
this.prefix = '';
if (props.removeKeySecretsAfterDays &&
(props.removeKeySecretsAfterDays < 0 ||
(props.removeKeySecretsAfterDays > 0 &&
props.removeKeySecretsAfterDays < 7) ||
props.removeKeySecretsAfterDays > 30)) {
aws_cdk_lib_1.Annotations.of(this).addError(`Parameter removeKeySecretsAfterDays must be 0 or between 7 and 30. Got ${props.removeKeySecretsAfterDays}`);
}
if (props.publicKey?.length &&
props.publicKeyFormat !== undefined &&
props.publicKeyFormat !== PublicKeyFormat.OPENSSH) {
aws_cdk_lib_1.Annotations.of(this).addError('When importing a key, the format has to be of type OpenSSH');
}
const stack = aws_cdk_lib_1.Stack.of(this).stackName;
this.lambda = this.ensureLambda();
this.tags = new aws_cdk_lib_1.TagManager(aws_cdk_lib_1.TagType.MAP, 'Custom::EC2-Key-Pair');
this.tags.setTag(createdByTag, ID);
const kmsPrivate = props.kmsPrivateKey || props.kms;
const kmsPublic = props.kmsPublicKey || props.kms;
const key = new aws_cdk_lib_1.CustomResource(this, `EC2-Key-Pair-${props.name}`, {
serviceToken: this.lambda.functionArn,
resourceType: resourceType,
properties: {
Name: props.name,
Description: props.description || '',
KmsPrivate: kmsPrivate?.keyArn || 'alias/aws/secretsmanager',
KmsPublic: kmsPublic?.keyArn || 'alias/aws/secretsmanager',
PublicKey: props.publicKey || '',
StorePublicKey: props.storePublicKey || false,
ExposePublicKey: props.exposePublicKey || false,
PublicKeyFormat: props.publicKeyFormat || PublicKeyFormat.OPENSSH,
RemoveKeySecretsAfterDays: props.removeKeySecretsAfterDays || 0,
SecretPrefix: props.secretPrefix || 'ec2-ssh-key/',
StackName: stack,
Tags: aws_cdk_lib_1.Lazy.any({
produce: () => this.tags.renderTags(),
}),
},
});
if (typeof props.kms !== 'undefined') {
props.kms.grantEncryptDecrypt(this.lambda.role);
key.node.addDependency(props.kms);
key.node.addDependency(this.lambda.role);
}
if (typeof props.kmsPrivateKey !== 'undefined') {
props.kmsPrivateKey.grantEncryptDecrypt(this.lambda.role);
key.node.addDependency(props.kmsPrivateKey);
key.node.addDependency(this.lambda.role);
}
if (typeof props.kmsPublicKey !== 'undefined') {
props.kmsPublicKey.grantEncryptDecrypt(this.lambda.role);
key.node.addDependency(props.kmsPublicKey);
key.node.addDependency(this.lambda.role);
}
this.privateKeyArn = key.getAttString('PrivateKeyARN');
this.publicKeyArn = key.getAttString('PublicKeyARN');
this.publicKeyValue = key.getAttString('PublicKeyValue');
this.keyPairName = key.getAttString('KeyPairName');
this.keyPairID = key.getAttString('KeyPairID');
}
ensureLambda() {
const stack = aws_cdk_lib_1.Stack.of(this);
const constructName = 'EC2-Key-Name-Manager-Lambda';
const existing = stack.node.tryFindChild(constructName);
if (existing) {
return existing;
}
const resources = [`arn:${stack.partition}:ec2:*:*:key-pair/*`];
const policy = new aws_cdk_lib_1.aws_iam.ManagedPolicy(stack, 'EC2-Key-Pair-Manager-Policy', {
description: `Used by Lambda ${cleanID}, which is a custom CFN resource, managing EC2 Key Pairs`,
statements: [
new aws_cdk_lib_1.aws_iam.PolicyStatement({
actions: ['ec2:DescribeKeyPairs'],
resources: ['*'],
}),
new aws_cdk_lib_1.aws_iam.PolicyStatement({
actions: [
'ec2:CreateKeyPair',
'ec2:CreateTags',
'ec2:ImportKeyPair',
],
conditions: {
StringLike: {
'aws:RequestTag/CreatedByCfnCustomResource': ID,
},
},
resources,
}),
new aws_cdk_lib_1.aws_iam.PolicyStatement({
// allow delete/update, only if createdByTag is set
actions: ['ec2:CreateTags', 'ec2:DeleteKeyPair', 'ec2:DeleteTags'],
conditions: {
StringLike: {
'ec2:ResourceTag/CreatedByCfnCustomResource': ID,
},
},
resources,
}),
new aws_cdk_lib_1.aws_iam.PolicyStatement({
// we need this to check if a secret exists before attempting to delete it
actions: ['secretsmanager:ListSecrets'],
resources: ['*'],
}),
new aws_cdk_lib_1.aws_iam.PolicyStatement({
actions: [
'secretsmanager:CreateSecret',
'secretsmanager:TagResource',
],
conditions: {
StringLike: {
'aws:RequestTag/CreatedByCfnCustomResource': ID,
},
},
resources: ['*'],
}),
new aws_cdk_lib_1.aws_iam.PolicyStatement({
// allow delete/update, only if createdByTag is set
actions: [
'secretsmanager:DeleteResourcePolicy',
'secretsmanager:DeleteSecret',
'secretsmanager:DescribeSecret',
'secretsmanager:GetResourcePolicy',
'secretsmanager:GetSecretValue',
'secretsmanager:ListSecretVersionIds',
'secretsmanager:PutResourcePolicy',
'secretsmanager:PutSecretValue',
'secretsmanager:RestoreSecret',
'secretsmanager:UntagResource',
'secretsmanager:UpdateSecret',
'secretsmanager:UpdateSecretVersionStage',
],
conditions: {
StringLike: {
'secretsmanager:ResourceTag/CreatedByCfnCustomResource': ID,
},
},
resources: ['*'],
}),
],
});
const role = new aws_cdk_lib_1.aws_iam.Role(stack, 'EC2-Key-Pair-Manager-Role', {
description: `Used by Lambda ${cleanID}, which is a custom CFN resource, managing EC2 Key Pairs`,
assumedBy: new aws_cdk_lib_1.aws_iam.ServicePrincipal('lambda.amazonaws.com'),
managedPolicies: [
policy,
aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
],
});
const fn = new aws_cdk_lib_1.aws_lambda.Function(stack, constructName, {
role,
description: `${this.prefix}-${cleanID} Custom CFN resource: Manage EC2 Key Pairs`,
runtime: aws_cdk_lib_1.aws_lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
code: aws_cdk_lib_1.aws_lambda.Code.fromAsset(path.join(__dirname, '../lambda/code.zip')),
timeout: aws_cdk_lib_1.Duration.minutes(lambdaTimeout),
});
return fn;
}
/**
* Grants read access to the private key in AWS Secrets Manager
*/
grantReadOnPrivateKey(grantee) {
return this.grantRead(this.privateKeyArn, grantee);
}
/**
* Grants read access to the public key in AWS Secrets Manager
*/
grantReadOnPublicKey(grantee) {
return this.grantRead(this.publicKeyArn, grantee);
}
grantRead(arn, grantee) {
const result = aws_cdk_lib_1.aws_iam.Grant.addToPrincipal({
grantee,
actions: [
'secretsmanager:DescribeSecret',
'secretsmanager:GetResourcePolicy',
'secretsmanager:GetSecretValue',
'secretsmanager:ListSecretVersionIds',
],
resourceArns: [arn],
scope: this,
});
return result;
}
}
exports.KeyPair = KeyPair;
_a = JSII_RTTI_SYMBOL_1;
KeyPair[_a] = { fqn: "cdk-ec2-key-pair.KeyPair", version: "0.0.0" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQWFxQjtBQUNyQiwyQ0FBdUM7QUFDdkMsNkJBQTZCO0FBRTdCLE1BQU0sWUFBWSxHQUFHLHNCQUFzQixDQUFDO0FBQzVDLE1BQU0sRUFBRSxHQUFHLGtCQUFrQixZQUFZLEVBQUUsQ0FBQztBQUM1QyxNQUFNLFlBQVksR0FBRyw0QkFBNEIsQ0FBQztBQUNsRCxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztBQUN2QyxNQUFNLGFBQWEsR0FBRyxDQUFDLENBQUMsQ0FBQyxVQUFVO0FBRW5DLElBQVksZUFHWDtBQUhELFdBQVksZUFBZTtJQUN6QixzQ0FBbUIsQ0FBQTtJQUNuQiw4QkFBVyxDQUFBO0FBQ2IsQ0FBQyxFQUhXLGVBQWUsK0JBQWYsZUFBZSxRQUcxQjtBQTRHRDs7R0FFRztBQUNILE1BQWEsT0FBUSxTQUFRLHNCQUFTO0lBd0NwQzs7T0FFRztJQUNILFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBbUI7UUFDM0QsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQXRDbkI7O1dBRUc7UUFDYSxrQkFBYSxHQUFXLEVBQUUsQ0FBQztRQUUzQzs7V0FFRztRQUNhLGlCQUFZLEdBQVcsRUFBRSxDQUFDO1FBRTFDOzs7O1dBSUc7UUFDYSxtQkFBYyxHQUFXLEVBQUUsQ0FBQztRQUU1Qzs7V0FFRztRQUNhLGdCQUFXLEdBQVcsRUFBRSxDQUFDO1FBRXpDOztXQUVHO1FBQ2EsY0FBUyxHQUFXLEVBQUUsQ0FBQztRQU92QixXQUFNLEdBQVcsRUFBRSxDQUFDO1FBUWxDLElBQ0UsS0FBSyxDQUFDLHlCQUF5QjtZQUMvQixDQUFDLEtBQUssQ0FBQyx5QkFBeUIsR0FBRyxDQUFDO2dCQUNsQyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsR0FBRyxDQUFDO29CQUNsQyxLQUFLLENBQUMseUJBQXlCLEdBQUcsQ0FBQyxDQUFDO2dCQUN0QyxLQUFLLENBQUMseUJBQXlCLEdBQUcsRUFBRSxDQUFDLEVBQ3ZDO1lBQ0EseUJBQVcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUMzQiwwRUFBMEUsS0FBSyxDQUFDLHlCQUF5QixFQUFFLENBQzVHLENBQUM7U0FDSDtRQUVELElBQ0UsS0FBSyxDQUFDLFNBQVMsRUFBRSxNQUFNO1lBQ3ZCLEtBQUssQ0FBQyxlQUFlLEtBQUssU0FBUztZQUNuQyxLQUFLLENBQUMsZUFBZSxLQUFLLGVBQWUsQ0FBQyxPQUFPLEVBQ2pEO1lBQ0EseUJBQVcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUMzQiw0REFBNEQsQ0FDN0QsQ0FBQztTQUNIO1FBRUQsTUFBTSxLQUFLLEdBQUcsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBRWxDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSx3QkFBVSxDQUFDLHFCQUFPLENBQUMsR0FBRyxFQUFFLHNCQUFzQixDQUFDLENBQUM7UUFDaEUsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRW5DLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxhQUFhLElBQUksS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUNwRCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsWUFBWSxJQUFJLEtBQUssQ0FBQyxHQUFHLENBQUM7UUFFbEQsTUFBTSxHQUFHLEdBQUcsSUFBSSw0QkFBYyxDQUFDLElBQUksRUFBRSxnQkFBZ0IsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ2pFLFlBQVksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVc7WUFDckMsWUFBWSxFQUFFLFlBQVk7WUFDMUIsVUFBVSxFQUFFO2dCQUNWLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtnQkFDaEIsV0FBVyxFQUFFLEtBQUssQ0FBQyxXQUFXLElBQUksRUFBRTtnQkFDcEMsVUFBVSxFQUFFLFVBQVUsRUFBRSxNQUFNLElBQUksMEJBQTBCO2dCQUM1RCxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sSUFBSSwwQkFBMEI7Z0JBQzFELFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUyxJQUFJLEVBQUU7Z0JBQ2hDLGNBQWMsRUFBRSxLQUFLLENBQUMsY0FBYyxJQUFJLEtBQUs7Z0JBQzdDLGVBQWUsRUFBRSxLQUFLLENBQUMsZUFBZSxJQUFJLEtBQUs7Z0JBQy9DLGVBQWUsRUFBRSxLQUFLLENBQUMsZUFBZSxJQUFJLGVBQWUsQ0FBQyxPQUFPO2dCQUNqRSx5QkFBeUIsRUFBRSxLQUFLLENBQUMseUJBQXlCLElBQUksQ0FBQztnQkFDL0QsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZLElBQUksY0FBYztnQkFDbEQsU0FBUyxFQUFFLEtBQUs7Z0JBQ2hCLElBQUksRUFBRSxrQkFBSSxDQUFDLEdBQUcsQ0FBQztvQkFDYixPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7aUJBQ3RDLENBQUM7YUFDSDtTQUNGLENBQUMsQ0FBQztRQUVILElBQUksT0FBTyxLQUFLLENBQUMsR0FBRyxLQUFLLFdBQVcsRUFBRTtZQUNwQyxLQUFLLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSyxDQUFDLENBQUM7WUFDakQsR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2xDLEdBQUcsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSyxDQUFDLENBQUM7U0FDM0M7UUFFRCxJQUFJLE9BQU8sS0FBSyxDQUFDLGFBQWEsS0FBSyxXQUFXLEVBQUU7WUFDOUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUssQ0FBQyxDQUFDO1lBQzNELEdBQUcsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUM1QyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUssQ0FBQyxDQUFDO1NBQzNDO1FBRUQsSUFBSSxPQUFPLEtBQUssQ0FBQyxZQUFZLEtBQUssV0FBVyxFQUFFO1lBQzdDLEtBQUssQ0FBQyxZQUFZLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFLLENBQUMsQ0FBQztZQUMxRCxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDM0MsR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFLLENBQUMsQ0FBQztTQUMzQztRQUVELElBQUksQ0FBQyxhQUFhLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUN2RCxJQUFJLENBQUMsWUFBWSxHQUFHLEdBQUcsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLGNBQWMsR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLFdBQVcsR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRU8sWUFBWTtRQUNsQixNQUFNLEtBQUssR0FBRyxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QixNQUFNLGFBQWEsR0FBRyw2QkFBNkIsQ0FBQztRQUNwRCxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN4RCxJQUFJLFFBQVEsRUFBRTtZQUNaLE9BQU8sUUFBK0IsQ0FBQztTQUN4QztRQUVELE1BQU0sU0FBUyxHQUFHLENBQUMsT0FBTyxLQUFLLENBQUMsU0FBUyxxQkFBcUIsQ0FBQyxDQUFDO1FBRWhFLE1BQU0sTUFBTSxHQUFHLElBQUkscUJBQU8sQ0FBQyxhQUFhLENBQ3RDLEtBQUssRUFDTCw2QkFBNkIsRUFDN0I7WUFDRSxXQUFXLEVBQUUsa0JBQWtCLE9BQU8sMERBQTBEO1lBQ2hHLFVBQVUsRUFBRTtnQkFDVixJQUFJLHFCQUFPLENBQUMsZUFBZSxDQUFDO29CQUMxQixPQUFPLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQztvQkFDakMsU0FBUyxFQUFFLENBQUMsR0FBRyxDQUFDO2lCQUNqQixDQUFDO2dCQUNGLElBQUkscUJBQU8sQ0FBQyxlQUFlLENBQUM7b0JBQzFCLE9BQU8sRUFBRTt3QkFDUCxtQkFBbUI7d0JBQ25CLGdCQUFnQjt3QkFDaEIsbUJBQW1CO3FCQUNwQjtvQkFDRCxVQUFVLEVBQUU7d0JBQ1YsVUFBVSxFQUFFOzRCQUNWLDJDQUEyQyxFQUFFLEVBQUU7eUJBQ2hEO3FCQUNGO29CQUNELFNBQVM7aUJBQ1YsQ0FBQztnQkFDRixJQUFJLHFCQUFPLENBQUMsZUFBZSxDQUFDO29CQUMxQixtREFBbUQ7b0JBQ25ELE9BQU8sRUFBRSxDQUFDLGdCQUFnQixFQUFFLG1CQUFtQixFQUFFLGdCQUFnQixDQUFDO29CQUNsRSxVQUFVLEVBQUU7d0JBQ1YsVUFBVSxFQUFFOzRCQUNWLDRDQUE0QyxFQUFFLEVBQUU7eUJBQ2pEO3FCQUNGO29CQUNELFNBQVM7aUJBQ1YsQ0FBQztnQkFFRixJQUFJLHFCQUFPLENBQUMsZUFBZSxDQUFDO29CQUMxQiwwRUFBMEU7b0JBQzFFLE9BQU8sRUFBRSxDQUFDLDRCQUE0QixDQUFDO29CQUN2QyxTQUFTLEVBQUUsQ0FBQyxHQUFHLENBQUM7aUJBQ2pCLENBQUM7Z0JBQ0YsSUFBSSxxQkFBTyxDQUFDLGVBQWUsQ0FBQztvQkFDMUIsT0FBTyxFQUFFO3dCQUNQLDZCQUE2Qjt3QkFDN0IsNEJBQTRCO3FCQUM3QjtvQkFDRCxVQUFVLEVBQUU7d0JBQ1YsVUFBVSxFQUFFOzRCQUNWLDJDQUEyQyxFQUFFLEVBQUU7eUJBQ2hEO3FCQUNGO29CQUNELFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQztpQkFDakIsQ0FBQztnQkFDRixJQUFJLHFCQUFPLENBQUMsZUFBZSxDQUFDO29CQUMxQixtREFBbUQ7b0JBQ25ELE9BQU8sRUFBRTt3QkFDUCxxQ0FBcUM7d0JBQ3JDLDZCQUE2Qjt3QkFDN0IsK0JBQStCO3dCQUMvQixrQ0FBa0M7d0JBQ2xDLCtCQUErQjt3QkFDL0IscUNBQXFDO3dCQUNyQyxrQ0FBa0M7d0JBQ2xDLCtCQUErQjt3QkFDL0IsOEJBQThCO3dCQUM5Qiw4QkFBOEI7d0JBQzlCLDZCQUE2Qjt3QkFDN0IseUNBQXlDO3FCQUMxQztvQkFDRCxVQUFVLEVBQUU7d0JBQ1YsVUFBVSxFQUFFOzRCQUNWLHVEQUF1RCxFQUFFLEVBQUU7eUJBQzVEO3FCQUNGO29CQUNELFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQztpQkFDakIsQ0FBQzthQUNIO1NBQ0YsQ0FDRixDQUFDO1FBRUYsTUFBTSxJQUFJLEdBQUcsSUFBSSxxQkFBTyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsMkJBQTJCLEVBQUU7WUFDaEUsV0FBVyxFQUFFLGtCQUFrQixPQUFPLDBEQUEwRDtZQUNoRyxTQUFTLEVBQUUsSUFBSSxxQkFBTyxDQUFDLGdCQUFnQixDQUFDLHNCQUFzQixDQUFDO1lBQy9ELGVBQWUsRUFBRTtnQkFDZixNQUFNO2dCQUNOLHFCQUFPLENBQUMsYUFBYSxDQUFDLHdCQUF3QixDQUM1QywwQ0FBMEMsQ0FDM0M7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUVILE1BQU0sRUFBRSxHQUFHLElBQUksd0JBQVUsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLGFBQWEsRUFBRTtZQUN2RCxJQUFJO1lBQ0osV0FBVyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxPQUFPLDRDQUE0QztZQUNsRixPQUFPLEVBQUUsd0JBQVUsQ0FBQyxPQUFPLENBQUMsV0FBVztZQUN2QyxPQUFPLEVBQUUsZUFBZTtZQUN4QixJQUFJLEVBQUUsd0JBQVUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUM3QixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxvQkFBb0IsQ0FBQyxDQUMzQztZQUNELE9BQU8sRUFBRSxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUM7U0FDekMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQ7O09BRUc7SUFDSCxxQkFBcUIsQ0FBQyxPQUEyQjtRQUMvQyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxvQkFBb0IsQ0FBQyxPQUEyQjtRQUM5QyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRU8sU0FBUyxDQUFDLEdBQVcsRUFBRSxPQUEyQjtRQUN4RCxNQUFNLE1BQU0sR0FBRyxxQkFBTyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUM7WUFDMUMsT0FBTztZQUNQLE9BQU8sRUFBRTtnQkFDUCwrQkFBK0I7Z0JBQy9CLGtDQUFrQztnQkFDbEMsK0JBQStCO2dCQUMvQixxQ0FBcUM7YUFDdEM7WUFDRCxZQUFZLEVBQUUsQ0FBQyxHQUFHLENBQUM7WUFDbkIsS0FBSyxFQUFFLElBQUk7U0FDWixDQUFDLENBQUM7UUFDSCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDOztBQXZRSCwwQkF3UUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBbm5vdGF0aW9ucyxcbiAgYXdzX2lhbSxcbiAgYXdzX2ttcyxcbiAgYXdzX2xhbWJkYSxcbiAgQ3VzdG9tUmVzb3VyY2UsXG4gIER1cmF0aW9uLFxuICBJVGFnZ2FibGUsXG4gIExhenksXG4gIFJlc291cmNlUHJvcHMsXG4gIFN0YWNrLFxuICBUYWdNYW5hZ2VyLFxuICBUYWdUeXBlLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5cbmNvbnN0IHJlc291cmNlVHlwZSA9ICdDdXN0b206OkVDMi1LZXktUGFpcic7XG5jb25zdCBJRCA9IGBDRk46OlJlc291cmNlOjoke3Jlc291cmNlVHlwZX1gO1xuY29uc3QgY3JlYXRlZEJ5VGFnID0gJ0NyZWF0ZWRCeUNmbkN1c3RvbVJlc291cmNlJztcbmNvbnN0IGNsZWFuSUQgPSBJRC5yZXBsYWNlKC86Ky9nLCAnLScpO1xuY29uc3QgbGFtYmRhVGltZW91dCA9IDM7IC8vIG1pbnV0ZXNcblxuZXhwb3J0IGVudW0gUHVibGljS2V5Rm9ybWF0IHtcbiAgT1BFTlNTSCA9ICdPUEVOU1NIJyxcbiAgUEVNID0gJ1BFTScsXG59XG5cbi8qKlxuICogRGVmaW5pdGlvbiBvZiBFQzIgS2V5IFBhaXJcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBLZXlQYWlyUHJvcHMgZXh0ZW5kcyBSZXNvdXJjZVByb3BzIHtcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIEtleSBQYWlyXG4gICAqXG4gICAqIEluIEFXUyBTZWNyZXRzIE1hbmFnZXIgdGhlIGtleSB3aWxsIGJlIHByZWZpeGVkIHdpdGggYGVjMi1zc2gta2V5L2AuXG4gICAqXG4gICAqIFRoZSBuYW1lIGNhbiBiZSB1cCB0byAyNTUgY2hhcmFjdGVycyBsb25nLiBWYWxpZCBjaGFyYWN0ZXJzIGluY2x1ZGUgXywgLSwgYS16LCBBLVosIGFuZCAwLTkuXG4gICAqL1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBkZXNjcmlwdGlvbiBmb3IgdGhlIGtleSBpbiBBV1MgU2VjcmV0cyBNYW5hZ2VyXG4gICAqIEBkZWZhdWx0IC0gJydcbiAgICovXG4gIHJlYWRvbmx5IGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgS01TIGtleSB1c2VkIHRvIGVuY3J5cHQgdGhlIFNlY3JldHMgTWFuYWdlciBzZWNyZXRzIHdpdGhcbiAgICpcbiAgICogVGhpcyBuZWVkcyB0byBiZSBhIGtleSBjcmVhdGVkIGluIHRoZSBzYW1lIHN0YWNrLiBZb3UgY2Fubm90IHVzZSBhIGtleSBpbXBvcnRlZCB2aWEgQVJOLCBiZWNhdXNlIHRoZSBrZXlzIGFjY2VzcyBwb2xpY3kgd2lsbCBuZWVkIHRvIGJlIG1vZGlmaWVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGBhbGlhcy9hd3Mvc2VjcmV0c21hbmFnZXJgXG4gICAqL1xuICByZWFkb25seSBrbXM/OiBhd3Nfa21zLktleTtcblxuICAvKipcbiAgICogVGhlIEtNUyBrZXkgdG8gdXNlIHRvIGVuY3J5cHQgdGhlIHByaXZhdGUga2V5IHdpdGhcbiAgICpcbiAgICogVGhpcyBuZWVkcyB0byBiZSBhIGtleSBjcmVhdGVkIGluIHRoZSBzYW1lIHN0YWNrLiBZb3UgY2Fubm90IHVzZSBhIGtleSBpbXBvcnRlZCB2aWEgQVJOLCBiZWNhdXNlIHRoZSBrZXlzIGFjY2VzcyBwb2xpY3kgd2lsbCBuZWVkIHRvIGJlIG1vZGlmaWVkLlxuICAgKlxuICAgKiBJZiBubyB2YWx1ZSBpcyBwcm92aWRlZCwgdGhlIHByb3BlcnR5IGBrbXNgIHdpbGwgYmUgdXNlZCBpbnN0ZWFkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGB0aGlzLmttc2BcbiAgICovXG4gIHJlYWRvbmx5IGttc1ByaXZhdGVLZXk/OiBhd3Nfa21zLktleTtcblxuICAvKipcbiAgICogVGhlIEtNUyBrZXkgdG8gdXNlIHRvIGVuY3J5cHQgdGhlIHB1YmxpYyBrZXkgd2l0aFxuICAgKlxuICAgKiBUaGlzIG5lZWRzIHRvIGJlIGEga2V5IGNyZWF0ZWQgaW4gdGhlIHNhbWUgc3RhY2suIFlvdSBjYW5ub3QgdXNlIGEga2V5IGltcG9ydGVkIHZpYSBBUk4sIGJlY2F1c2UgdGhlIGtleXMgYWNjZXNzIHBvbGljeSB3aWxsIG5lZWQgdG8gYmUgbW9kaWZpZWQuXG4gICAqXG4gICAqIElmIG5vIHZhbHVlIGlzIHByb3ZpZGVkLCB0aGUgcHJvcGVydHkgYGttc2Agd2lsbCBiZSB1c2VkIGluc3RlYWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYHRoaXMua21zYFxuICAgKi9cbiAgcmVhZG9ubHkga21zUHVibGljS2V5PzogYXdzX2ttcy5LZXk7XG5cbiAgLyoqXG4gICAqIEltcG9ydCBhIHB1YmxpYyBrZXkgaW5zdGVhZCBvZiBjcmVhdGluZyBpdFxuICAgKlxuICAgKiBJZiBubyBwdWJsaWMga2V5IGlzIHByb3ZpZGVkLCBhIG5ldyBrZXkgcGFpciB3aWxsIGJlIGNyZWF0ZWQuXG4gICAqL1xuICByZWFkb25seSBwdWJsaWNLZXk/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSBwdWJsaWMga2V5IGFzIGEgc2VjcmV0XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHN0b3JlUHVibGljS2V5PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRXhwb3NlIHRoZSBwdWJsaWMga2V5IGFzIHByb3BlcnR5IGBwdWJsaWNLZXlWYWx1ZWBcbiAgICpcbiAgICogQGRlZmF1bHQgLSBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgZXhwb3NlUHVibGljS2V5PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRm9ybWF0IGZvciBwdWJsaWMga2V5LlxuICAgKlxuICAgKiBSZWxldmFudCBvbmx5IGlmIHRoZSBwdWJsaWMga2V5IGlzIHN0b3JlZCBhbmQvb3IgZXhwb3NlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBPUEVOU1NIXG4gICAqL1xuICByZWFkb25seSBwdWJsaWNLZXlGb3JtYXQ/OiBQdWJsaWNLZXlGb3JtYXQ7XG5cbiAgLyoqXG4gICAqIFdoZW4gdGhlIHJlc291cmNlIGlzIGRlc3Ryb3llZCwgYWZ0ZXIgaG93IG1hbnkgZGF5cyB0aGUgcHJpdmF0ZSBhbmQgcHVibGljIGtleSBpbiB0aGUgQVdTIFNlY3JldHMgTWFuYWdlciBzaG91bGQgYmUgZGVsZXRlZC5cbiAgICpcbiAgICogVmFsaWQgdmFsdWVzIGFyZSAwIGFuZCA3IHRvIDMwXG4gICAqXG4gICAqIEBkZWZhdWx0IDBcbiAgICovXG4gIHJlYWRvbmx5IHJlbW92ZUtleVNlY3JldHNBZnRlckRheXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFByZWZpeCBmb3IgdGhlIHNlY3JldCBpbiBBV1MgU2VjcmV0cyBNYW5hZ2VyLlxuICAgKlxuICAgKiBAZGVmYXVsdCBgZWMyLXNzaC1rZXkvYFxuICAgKi9cbiAgcmVhZG9ubHkgc2VjcmV0UHJlZml4Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIHByZWZpeCBmb3IgYWxsIHJlc291cmNlIG5hbWVzLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0IGFsbCByZXNvdXJjZXMgYXJlIHByZWZpeGVkIHdpdGggdGhlIHN0YWNrIG5hbWUgdG8gYXZvaWQgY29sbGlzaW9ucyB3aXRoIG90aGVyIHN0YWNrcy4gVGhpcyBtaWdodCBjYXVzZSBwcm9ibGVtcyB3aGVuIHlvdSB3b3JrIHdpdGggbG9uZyBzdGFjayBuYW1lcyBhbmQgY2FuIGJlIG92ZXJyaWRkZW4gdGhyb3VnaCB0aGlzIHBhcmFtZXRlci5cbiAgICpcbiAgICogQGRlZmF1bHQgTmFtZSBvZiB0aGUgc3RhY2tcbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlUHJlZml4Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEFuIEVDMiBLZXkgUGFpclxuICovXG5leHBvcnQgY2xhc3MgS2V5UGFpciBleHRlbmRzIENvbnN0cnVjdCBpbXBsZW1lbnRzIElUYWdnYWJsZSB7XG4gIC8qKlxuICAgKiBUaGUgbGFtYmRhIGZ1bmN0aW9uIHRoYXQgaXMgY3JlYXRlZFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGxhbWJkYTogYXdzX2xhbWJkYS5JRnVuY3Rpb247XG5cbiAgLyoqXG4gICAqIEFSTiBvZiB0aGUgcHJpdmF0ZSBrZXkgaW4gQVdTIFNlY3JldHMgTWFuYWdlclxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHByaXZhdGVLZXlBcm46IHN0cmluZyA9ICcnO1xuXG4gIC8qKlxuICAgKiBBUk4gb2YgdGhlIHB1YmxpYyBrZXkgaW4gQVdTIFNlY3JldHMgTWFuYWdlclxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHB1YmxpY0tleUFybjogc3RyaW5nID0gJyc7XG5cbiAgLyoqXG4gICAqIFRoZSBwdWJsaWMga2V5LlxuICAgKlxuICAgKiBPbmx5IGZpbGxlZCwgd2hlbiBgZXhwb3NlUHVibGljS2V5ID0gdHJ1ZWBcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBwdWJsaWNLZXlWYWx1ZTogc3RyaW5nID0gJyc7XG5cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIEtleSBQYWlyXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkga2V5UGFpck5hbWU6IHN0cmluZyA9ICcnO1xuXG4gIC8qKlxuICAgKiBJRCBvZiB0aGUgS2V5IFBhaXJcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBrZXlQYWlySUQ6IHN0cmluZyA9ICcnO1xuXG4gIC8qKlxuICAgKiBSZXNvdXJjZSB0YWdzXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdGFnczogVGFnTWFuYWdlcjtcblxuICBwdWJsaWMgcmVhZG9ubHkgcHJlZml4OiBzdHJpbmcgPSAnJztcblxuICAvKipcbiAgICogRGVmaW5lcyBhIG5ldyBFQzIgS2V5IFBhaXIuIFRoZSBwcml2YXRlIGtleSB3aWxsIGJlIHN0b3JlZCBpbiBBV1MgU2VjcmV0cyBNYW5hZ2VyXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogS2V5UGFpclByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGlmIChcbiAgICAgIHByb3BzLnJlbW92ZUtleVNlY3JldHNBZnRlckRheXMgJiZcbiAgICAgIChwcm9wcy5yZW1vdmVLZXlTZWNyZXRzQWZ0ZXJEYXlzIDwgMCB8fFxuICAgICAgICAocHJvcHMucmVtb3ZlS2V5U2VjcmV0c0FmdGVyRGF5cyA+IDAgJiZcbiAgICAgICAgICBwcm9wcy5yZW1vdmVLZXlTZWNyZXRzQWZ0ZXJEYXlzIDwgNykgfHxcbiAgICAgICAgcHJvcHMucmVtb3ZlS2V5U2VjcmV0c0FmdGVyRGF5cyA+IDMwKVxuICAgICkge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkRXJyb3IoXG4gICAgICAgIGBQYXJhbWV0ZXIgcmVtb3ZlS2V5U2VjcmV0c0FmdGVyRGF5cyBtdXN0IGJlIDAgb3IgYmV0d2VlbiA3IGFuZCAzMC4gR290ICR7cHJvcHMucmVtb3ZlS2V5U2VjcmV0c0FmdGVyRGF5c31gXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIHByb3BzLnB1YmxpY0tleT8ubGVuZ3RoICYmXG4gICAgICBwcm9wcy5wdWJsaWNLZXlGb3JtYXQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgcHJvcHMucHVibGljS2V5Rm9ybWF0ICE9PSBQdWJsaWNLZXlGb3JtYXQuT1BFTlNTSFxuICAgICkge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkRXJyb3IoXG4gICAgICAgICdXaGVuIGltcG9ydGluZyBhIGtleSwgdGhlIGZvcm1hdCBoYXMgdG8gYmUgb2YgdHlwZSBPcGVuU1NIJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZTtcbiAgICB0aGlzLmxhbWJkYSA9IHRoaXMuZW5zdXJlTGFtYmRhKCk7XG5cbiAgICB0aGlzLnRhZ3MgPSBuZXcgVGFnTWFuYWdlcihUYWdUeXBlLk1BUCwgJ0N1c3RvbTo6RUMyLUtleS1QYWlyJyk7XG4gICAgdGhpcy50YWdzLnNldFRhZyhjcmVhdGVkQnlUYWcsIElEKTtcblxuICAgIGNvbnN0IGttc1ByaXZhdGUgPSBwcm9wcy5rbXNQcml2YXRlS2V5IHx8IHByb3BzLmttcztcbiAgICBjb25zdCBrbXNQdWJsaWMgPSBwcm9wcy5rbXNQdWJsaWNLZXkgfHwgcHJvcHMua21zO1xuXG4gICAgY29uc3Qga2V5ID0gbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsIGBFQzItS2V5LVBhaXItJHtwcm9wcy5uYW1lfWAsIHtcbiAgICAgIHNlcnZpY2VUb2tlbjogdGhpcy5sYW1iZGEuZnVuY3Rpb25Bcm4sXG4gICAgICByZXNvdXJjZVR5cGU6IHJlc291cmNlVHlwZSxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgTmFtZTogcHJvcHMubmFtZSxcbiAgICAgICAgRGVzY3JpcHRpb246IHByb3BzLmRlc2NyaXB0aW9uIHx8ICcnLFxuICAgICAgICBLbXNQcml2YXRlOiBrbXNQcml2YXRlPy5rZXlBcm4gfHwgJ2FsaWFzL2F3cy9zZWNyZXRzbWFuYWdlcicsXG4gICAgICAgIEttc1B1YmxpYzoga21zUHVibGljPy5rZXlBcm4gfHwgJ2FsaWFzL2F3cy9zZWNyZXRzbWFuYWdlcicsXG4gICAgICAgIFB1YmxpY0tleTogcHJvcHMucHVibGljS2V5IHx8ICcnLFxuICAgICAgICBTdG9yZVB1YmxpY0tleTogcHJvcHMuc3RvcmVQdWJsaWNLZXkgfHwgZmFsc2UsXG4gICAgICAgIEV4cG9zZVB1YmxpY0tleTogcHJvcHMuZXhwb3NlUHVibGljS2V5IHx8IGZhbHNlLFxuICAgICAgICBQdWJsaWNLZXlGb3JtYXQ6IHByb3BzLnB1YmxpY0tleUZvcm1hdCB8fCBQdWJsaWNLZXlGb3JtYXQuT1BFTlNTSCxcbiAgICAgICAgUmVtb3ZlS2V5U2VjcmV0c0FmdGVyRGF5czogcHJvcHMucmVtb3ZlS2V5U2VjcmV0c0FmdGVyRGF5cyB8fCAwLFxuICAgICAgICBTZWNyZXRQcmVmaXg6IHByb3BzLnNlY3JldFByZWZpeCB8fCAnZWMyLXNzaC1rZXkvJyxcbiAgICAgICAgU3RhY2tOYW1lOiBzdGFjayxcbiAgICAgICAgVGFnczogTGF6eS5hbnkoe1xuICAgICAgICAgIHByb2R1Y2U6ICgpID0+IHRoaXMudGFncy5yZW5kZXJUYWdzKCksXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2YgcHJvcHMua21zICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcHJvcHMua21zLmdyYW50RW5jcnlwdERlY3J5cHQodGhpcy5sYW1iZGEucm9sZSEpO1xuICAgICAga2V5Lm5vZGUuYWRkRGVwZW5kZW5jeShwcm9wcy5rbXMpO1xuICAgICAga2V5Lm5vZGUuYWRkRGVwZW5kZW5jeSh0aGlzLmxhbWJkYS5yb2xlISk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBwcm9wcy5rbXNQcml2YXRlS2V5ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcHJvcHMua21zUHJpdmF0ZUtleS5ncmFudEVuY3J5cHREZWNyeXB0KHRoaXMubGFtYmRhLnJvbGUhKTtcbiAgICAgIGtleS5ub2RlLmFkZERlcGVuZGVuY3kocHJvcHMua21zUHJpdmF0ZUtleSk7XG4gICAgICBrZXkubm9kZS5hZGREZXBlbmRlbmN5KHRoaXMubGFtYmRhLnJvbGUhKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIHByb3BzLmttc1B1YmxpY0tleSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHByb3BzLmttc1B1YmxpY0tleS5ncmFudEVuY3J5cHREZWNyeXB0KHRoaXMubGFtYmRhLnJvbGUhKTtcbiAgICAgIGtleS5ub2RlLmFkZERlcGVuZGVuY3kocHJvcHMua21zUHVibGljS2V5KTtcbiAgICAgIGtleS5ub2RlLmFkZERlcGVuZGVuY3kodGhpcy5sYW1iZGEucm9sZSEpO1xuICAgIH1cblxuICAgIHRoaXMucHJpdmF0ZUtleUFybiA9IGtleS5nZXRBdHRTdHJpbmcoJ1ByaXZhdGVLZXlBUk4nKTtcbiAgICB0aGlzLnB1YmxpY0tleUFybiA9IGtleS5nZXRBdHRTdHJpbmcoJ1B1YmxpY0tleUFSTicpO1xuICAgIHRoaXMucHVibGljS2V5VmFsdWUgPSBrZXkuZ2V0QXR0U3RyaW5nKCdQdWJsaWNLZXlWYWx1ZScpO1xuICAgIHRoaXMua2V5UGFpck5hbWUgPSBrZXkuZ2V0QXR0U3RyaW5nKCdLZXlQYWlyTmFtZScpO1xuICAgIHRoaXMua2V5UGFpcklEID0ga2V5LmdldEF0dFN0cmluZygnS2V5UGFpcklEJyk7XG4gIH1cblxuICBwcml2YXRlIGVuc3VyZUxhbWJkYSgpOiBhd3NfbGFtYmRhLkZ1bmN0aW9uIHtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIGNvbnN0IGNvbnN0cnVjdE5hbWUgPSAnRUMyLUtleS1OYW1lLU1hbmFnZXItTGFtYmRhJztcbiAgICBjb25zdCBleGlzdGluZyA9IHN0YWNrLm5vZGUudHJ5RmluZENoaWxkKGNvbnN0cnVjdE5hbWUpO1xuICAgIGlmIChleGlzdGluZykge1xuICAgICAgcmV0dXJuIGV4aXN0aW5nIGFzIGF3c19sYW1iZGEuRnVuY3Rpb247XG4gICAgfVxuXG4gICAgY29uc3QgcmVzb3VyY2VzID0gW2Bhcm46JHtzdGFjay5wYXJ0aXRpb259OmVjMjoqOio6a2V5LXBhaXIvKmBdO1xuXG4gICAgY29uc3QgcG9saWN5ID0gbmV3IGF3c19pYW0uTWFuYWdlZFBvbGljeShcbiAgICAgIHN0YWNrLFxuICAgICAgJ0VDMi1LZXktUGFpci1NYW5hZ2VyLVBvbGljeScsXG4gICAgICB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiBgVXNlZCBieSBMYW1iZGEgJHtjbGVhbklEfSwgd2hpY2ggaXMgYSBjdXN0b20gQ0ZOIHJlc291cmNlLCBtYW5hZ2luZyBFQzIgS2V5IFBhaXJzYCxcbiAgICAgICAgc3RhdGVtZW50czogW1xuICAgICAgICAgIG5ldyBhd3NfaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICBhY3Rpb25zOiBbJ2VjMjpEZXNjcmliZUtleVBhaXJzJ10sXG4gICAgICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIG5ldyBhd3NfaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgICAgICdlYzI6Q3JlYXRlS2V5UGFpcicsXG4gICAgICAgICAgICAgICdlYzI6Q3JlYXRlVGFncycsXG4gICAgICAgICAgICAgICdlYzI6SW1wb3J0S2V5UGFpcicsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY29uZGl0aW9uczoge1xuICAgICAgICAgICAgICBTdHJpbmdMaWtlOiB7XG4gICAgICAgICAgICAgICAgJ2F3czpSZXF1ZXN0VGFnL0NyZWF0ZWRCeUNmbkN1c3RvbVJlc291cmNlJzogSUQsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVzb3VyY2VzLFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIG5ldyBhd3NfaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICAvLyBhbGxvdyBkZWxldGUvdXBkYXRlLCBvbmx5IGlmIGNyZWF0ZWRCeVRhZyBpcyBzZXRcbiAgICAgICAgICAgIGFjdGlvbnM6IFsnZWMyOkNyZWF0ZVRhZ3MnLCAnZWMyOkRlbGV0ZUtleVBhaXInLCAnZWMyOkRlbGV0ZVRhZ3MnXSxcbiAgICAgICAgICAgIGNvbmRpdGlvbnM6IHtcbiAgICAgICAgICAgICAgU3RyaW5nTGlrZToge1xuICAgICAgICAgICAgICAgICdlYzI6UmVzb3VyY2VUYWcvQ3JlYXRlZEJ5Q2ZuQ3VzdG9tUmVzb3VyY2UnOiBJRCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZXNvdXJjZXMsXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgICBuZXcgYXdzX2lhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgLy8gd2UgbmVlZCB0aGlzIHRvIGNoZWNrIGlmIGEgc2VjcmV0IGV4aXN0cyBiZWZvcmUgYXR0ZW1wdGluZyB0byBkZWxldGUgaXRcbiAgICAgICAgICAgIGFjdGlvbnM6IFsnc2VjcmV0c21hbmFnZXI6TGlzdFNlY3JldHMnXSxcbiAgICAgICAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgICAgICAgfSksXG4gICAgICAgICAgbmV3IGF3c19pYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgICAgJ3NlY3JldHNtYW5hZ2VyOkNyZWF0ZVNlY3JldCcsXG4gICAgICAgICAgICAgICdzZWNyZXRzbWFuYWdlcjpUYWdSZXNvdXJjZScsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY29uZGl0aW9uczoge1xuICAgICAgICAgICAgICBTdHJpbmdMaWtlOiB7XG4gICAgICAgICAgICAgICAgJ2F3czpSZXF1ZXN0VGFnL0NyZWF0ZWRCeUNmbkN1c3RvbVJlc291cmNlJzogSUQsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBuZXcgYXdzX2lhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgLy8gYWxsb3cgZGVsZXRlL3VwZGF0ZSwgb25seSBpZiBjcmVhdGVkQnlUYWcgaXMgc2V0XG4gICAgICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgICAgICdzZWNyZXRzbWFuYWdlcjpEZWxldGVSZXNvdXJjZVBvbGljeScsXG4gICAgICAgICAgICAgICdzZWNyZXRzbWFuYWdlcjpEZWxldGVTZWNyZXQnLFxuICAgICAgICAgICAgICAnc2VjcmV0c21hbmFnZXI6RGVzY3JpYmVTZWNyZXQnLFxuICAgICAgICAgICAgICAnc2VjcmV0c21hbmFnZXI6R2V0UmVzb3VyY2VQb2xpY3knLFxuICAgICAgICAgICAgICAnc2VjcmV0c21hbmFnZXI6R2V0U2VjcmV0VmFsdWUnLFxuICAgICAgICAgICAgICAnc2VjcmV0c21hbmFnZXI6TGlzdFNlY3JldFZlcnNpb25JZHMnLFxuICAgICAgICAgICAgICAnc2VjcmV0c21hbmFnZXI6UHV0UmVzb3VyY2VQb2xpY3knLFxuICAgICAgICAgICAgICAnc2VjcmV0c21hbmFnZXI6UHV0U2VjcmV0VmFsdWUnLFxuICAgICAgICAgICAgICAnc2VjcmV0c21hbmFnZXI6UmVzdG9yZVNlY3JldCcsXG4gICAgICAgICAgICAgICdzZWNyZXRzbWFuYWdlcjpVbnRhZ1Jlc291cmNlJyxcbiAgICAgICAgICAgICAgJ3NlY3JldHNtYW5hZ2VyOlVwZGF0ZVNlY3JldCcsXG4gICAgICAgICAgICAgICdzZWNyZXRzbWFuYWdlcjpVcGRhdGVTZWNyZXRWZXJzaW9uU3RhZ2UnLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGNvbmRpdGlvbnM6IHtcbiAgICAgICAgICAgICAgU3RyaW5nTGlrZToge1xuICAgICAgICAgICAgICAgICdzZWNyZXRzbWFuYWdlcjpSZXNvdXJjZVRhZy9DcmVhdGVkQnlDZm5DdXN0b21SZXNvdXJjZSc6IElELFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgICAgICAgfSksXG4gICAgICAgIF0sXG4gICAgICB9XG4gICAgKTtcblxuICAgIGNvbnN0IHJvbGUgPSBuZXcgYXdzX2lhbS5Sb2xlKHN0YWNrLCAnRUMyLUtleS1QYWlyLU1hbmFnZXItUm9sZScsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBgVXNlZCBieSBMYW1iZGEgJHtjbGVhbklEfSwgd2hpY2ggaXMgYSBjdXN0b20gQ0ZOIHJlc291cmNlLCBtYW5hZ2luZyBFQzIgS2V5IFBhaXJzYCxcbiAgICAgIGFzc3VtZWRCeTogbmV3IGF3c19pYW0uU2VydmljZVByaW5jaXBhbCgnbGFtYmRhLmFtYXpvbmF3cy5jb20nKSxcbiAgICAgIG1hbmFnZWRQb2xpY2llczogW1xuICAgICAgICBwb2xpY3ksXG4gICAgICAgIGF3c19pYW0uTWFuYWdlZFBvbGljeS5mcm9tQXdzTWFuYWdlZFBvbGljeU5hbWUoXG4gICAgICAgICAgJ3NlcnZpY2Utcm9sZS9BV1NMYW1iZGFCYXNpY0V4ZWN1dGlvblJvbGUnXG4gICAgICAgICksXG4gICAgICBdLFxuICAgIH0pO1xuXG4gICAgY29uc3QgZm4gPSBuZXcgYXdzX2xhbWJkYS5GdW5jdGlvbihzdGFjaywgY29uc3RydWN0TmFtZSwge1xuICAgICAgcm9sZSxcbiAgICAgIGRlc2NyaXB0aW9uOiBgJHt0aGlzLnByZWZpeH0tJHtjbGVhbklEfSBDdXN0b20gQ0ZOIHJlc291cmNlOiBNYW5hZ2UgRUMyIEtleSBQYWlyc2AsXG4gICAgICBydW50aW1lOiBhd3NfbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzE4X1gsXG4gICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICBjb2RlOiBhd3NfbGFtYmRhLkNvZGUuZnJvbUFzc2V0KFxuICAgICAgICBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vbGFtYmRhL2NvZGUuemlwJylcbiAgICAgICksXG4gICAgICB0aW1lb3V0OiBEdXJhdGlvbi5taW51dGVzKGxhbWJkYVRpbWVvdXQpLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGZuO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyByZWFkIGFjY2VzcyB0byB0aGUgcHJpdmF0ZSBrZXkgaW4gQVdTIFNlY3JldHMgTWFuYWdlclxuICAgKi9cbiAgZ3JhbnRSZWFkT25Qcml2YXRlS2V5KGdyYW50ZWU6IGF3c19pYW0uSUdyYW50YWJsZSkge1xuICAgIHJldHVybiB0aGlzLmdyYW50UmVhZCh0aGlzLnByaXZhdGVLZXlBcm4sIGdyYW50ZWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyByZWFkIGFjY2VzcyB0byB0aGUgcHVibGljIGtleSBpbiBBV1MgU2VjcmV0cyBNYW5hZ2VyXG4gICAqL1xuICBncmFudFJlYWRPblB1YmxpY0tleShncmFudGVlOiBhd3NfaWFtLklHcmFudGFibGUpIHtcbiAgICByZXR1cm4gdGhpcy5ncmFudFJlYWQodGhpcy5wdWJsaWNLZXlBcm4sIGdyYW50ZWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBncmFudFJlYWQoYXJuOiBzdHJpbmcsIGdyYW50ZWU6IGF3c19pYW0uSUdyYW50YWJsZSkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3c19pYW0uR3JhbnQuYWRkVG9QcmluY2lwYWwoe1xuICAgICAgZ3JhbnRlZSxcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgJ3NlY3JldHNtYW5hZ2VyOkRlc2NyaWJlU2VjcmV0JyxcbiAgICAgICAgJ3NlY3JldHNtYW5hZ2VyOkdldFJlc291cmNlUG9saWN5JyxcbiAgICAgICAgJ3NlY3JldHNtYW5hZ2VyOkdldFNlY3JldFZhbHVlJyxcbiAgICAgICAgJ3NlY3JldHNtYW5hZ2VyOkxpc3RTZWNyZXRWZXJzaW9uSWRzJyxcbiAgICAgIF0sXG4gICAgICByZXNvdXJjZUFybnM6IFthcm5dLFxuICAgICAgc2NvcGU6IHRoaXMsXG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuIl19