cdk-sops-secrets
Version:
CDK Constructs that syncs your sops secrets into AWS SecretsManager secrets.
324 lines • 50.7 kB
JavaScript
"use strict";
var _a, _b;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Permissions = exports.SopsSync = exports.SopsSyncProvider = exports.ResourceType = exports.UploadType = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const fs = require("fs");
const path = require("path");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
const aws_kms_1 = require("aws-cdk-lib/aws-kms");
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
const aws_s3_assets_1 = require("aws-cdk-lib/aws-s3-assets");
const constructs_1 = require("constructs");
var UploadType;
(function (UploadType) {
/**
* Pass the secret data inline (base64 encoded and compressed)
*/
UploadType["INLINE"] = "INLINE";
/**
* Uplaod the secret data as asset
*/
UploadType["ASSET"] = "ASSET";
})(UploadType || (exports.UploadType = UploadType = {}));
var ResourceType;
(function (ResourceType) {
ResourceType["SECRET"] = "SECRET";
ResourceType["SECRET_RAW"] = "SECRET_RAW";
ResourceType["SECRET_BINARY"] = "SECRET_BINARY";
ResourceType["PARAMETER"] = "PARAMETER";
ResourceType["PARAMETER_MULTI"] = "PARAMETER_MULTI";
})(ResourceType || (exports.ResourceType = ResourceType = {}));
class SopsSyncProvider extends aws_lambda_1.SingletonFunction {
constructor(scope, id, props) {
super(scope, id ?? 'SopsSyncProvider', {
code: aws_lambda_1.Code.fromAsset(scope.node.tryGetContext('sops_sync_provider_asset_path') ||
path.join(__dirname, '../assets/cdk-sops-lambda.zip')),
runtime: aws_lambda_1.Runtime.PROVIDED_AL2,
handler: 'bootstrap',
uuid: 'SopsSyncProvider',
role: props?.role,
timeout: aws_cdk_lib_1.Duration.seconds(60),
environment: {
SOPS_AGE_KEY: aws_cdk_lib_1.Lazy.string({
produce: () => (this.sopsAgeKeys.map((secret) => secret.toString()) ?? []).join('\n'),
}),
},
vpc: props?.vpc,
vpcSubnets: props?.vpcSubnets,
securityGroups: props?.securityGroups,
logRetention: props?.logRetention,
logGroup: props?.logGroup,
});
this.sopsAgeKeys = [];
}
addAgeKey(key) {
this.sopsAgeKeys.push(key);
}
}
exports.SopsSyncProvider = SopsSyncProvider;
_a = JSII_RTTI_SYMBOL_1;
SopsSyncProvider[_a] = { fqn: "cdk-sops-secrets.SopsSyncProvider", version: "2.2.4" };
/**
* The custom resource, that is syncing the content from a sops file to a secret.
*/
class SopsSync extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
const provider = props.sopsProvider ?? new SopsSyncProvider(scope);
let uploadType = props.uploadType ?? UploadType.INLINE;
let sopsFileFormat = props.sopsFileFormat;
let sopsAsset = undefined;
let sopsInline = undefined;
let sopsS3File = undefined;
if ((props.sopsFilePath == undefined &&
(props.sopsS3Bucket == undefined || props.sopsS3Key == undefined)) ||
(props.sopsFilePath !== undefined &&
props.sopsS3Bucket !== undefined &&
props.sopsS3Key !== undefined)) {
throw new Error('You can either specify sopsFilePath or sopsS3Bucket and sopsS3Key!');
}
if (props.sopsFilePath !== undefined) {
if (sopsFileFormat === undefined) {
const _sopsFileFormat = props.sopsFilePath.split('.').pop();
switch (_sopsFileFormat) {
case 'json': {
sopsFileFormat = 'json';
break;
}
case 'yaml': {
sopsFileFormat = 'yaml';
break;
}
case 'yml': {
sopsFileFormat = 'yaml';
break;
}
case 'dotenv': {
sopsFileFormat = 'dotenv';
break;
}
case 'env': {
sopsFileFormat = 'dotenv';
break;
}
case 'binary': {
sopsFileFormat = 'binary';
break;
}
default: {
aws_cdk_lib_1.Annotations.of(this).addError("Failed to determine sops file format. Please specify 'sopsFileFormat'!");
}
}
}
if (!fs.existsSync(props.sopsFilePath)) {
throw new Error(`File ${props.sopsFilePath} does not exist!`);
}
const sopsFileContent = fs.readFileSync(props.sopsFilePath);
switch (uploadType) {
case UploadType.INLINE: {
sopsInline = {
Content: sopsFileContent.toString('base64'),
// We calculate the hash the same way as it would be done by new Asset(..) - so we can ensure stable version names even if switching from INLINE to ASSET and viceversa.
Hash: aws_cdk_lib_1.FileSystem.fingerprint(props.sopsFilePath),
};
break;
}
case UploadType.ASSET: {
sopsAsset = new aws_s3_assets_1.Asset(this, 'Asset', {
path: props.sopsFilePath,
});
sopsS3File = {
Bucket: sopsAsset.bucket.bucketName,
Key: sopsAsset.s3ObjectKey,
};
break;
}
}
if (
// Is allways true, but to satisfy TS we check explicitly
provider.role !== undefined &&
// Check if user has disabled automatic generation
props.autoGenerateIamPermissions !== false) {
Permissions.sopsKeys(this, {
userDefinedKeys: props.sopsKmsKey,
role: provider.role,
sopsFileContent: sopsFileContent.toString(),
});
Permissions.assetBucket(this, sopsAsset, provider.role, props.assetEncryptionKey);
Permissions.encryptionKey(props.encryptionKey, provider.role);
Permissions.secret(props.secret, provider.role);
Permissions.parameters(this, props.parameterNames, provider.role);
}
else {
aws_cdk_lib_1.Annotations.of(this).addWarning([
'Please ensure proper permissions for the passed lambda function:',
' - write Access to the secret/parameters',
' - encrypt with the sopsKmsKey',
' - download from asset bucket',
].join('\n'));
}
if (props.sopsAgeKey !== undefined) {
provider.addAgeKey(props.sopsAgeKey);
}
}
else if (props.sopsS3Bucket !== undefined &&
props.sopsS3Key !== undefined) {
sopsS3File = {
Bucket: props.sopsS3Bucket,
Key: props.sopsS3Key,
};
uploadType = UploadType.ASSET;
aws_cdk_lib_1.Annotations.of(this).addWarning('You have to manually add permissions to the sops provider to (permission to download file, to decrypt sops file)!');
}
if (sopsFileFormat === undefined) {
throw new Error('You have to specify sopsFileFormat!');
}
const cr = new aws_cdk_lib_1.CustomResource(this, 'Resource', {
serviceToken: provider.functionArn,
resourceType: 'Custom::SopsSync',
properties: {
SopsS3File: sopsS3File,
SopsInline: sopsInline,
FlattenSeparator: props.flattenSeparator,
Format: sopsFileFormat,
EncryptionKey: props.encryptionKey?.keyId,
ResourceType: props.resourceType,
Target: props.target,
},
});
this.versionId = cr.getAttString('VersionId');
}
}
exports.SopsSync = SopsSync;
_b = JSII_RTTI_SYMBOL_1;
SopsSync[_b] = { fqn: "cdk-sops-secrets.SopsSync", version: "2.2.4" };
var Permissions;
(function (Permissions) {
/**
* Grants the necessary permissions for encrypt/decrypt on the customer managed encryption key
* for the secrets / parameters.
*/
function encryptionKey(key, target) {
if (key === undefined) {
return;
}
key.grantEncryptDecrypt(target);
}
Permissions.encryptionKey = encryptionKey;
function keysFromSopsContent(ctx, c) {
const regexKey = /arn:aws:kms:[a-z0-9-]+:[\d]+:key\/[a-z0-9-]+/g;
const resultsKey = c.match(regexKey);
if (resultsKey !== null) {
return resultsKey.map((result, index) => aws_kms_1.Key.fromKeyArn(ctx, `SopsKey${index}`, result));
}
return [];
}
Permissions.keysFromSopsContent = keysFromSopsContent;
function keysFromSopsContentAlias(ctx, c) {
const regexAlias = /arn:aws:kms:[a-z0-9-]+:[\d]+:alias\/[a-z0-9-A-Z\/]+/g;
const resultsAlias = c.match(regexAlias);
if (resultsAlias !== null) {
return resultsAlias.map((result, index) => aws_kms_1.Key.fromLookup(ctx, `SopsAlias${index}`, {
aliasName: `alias/${result.split('/').slice(1).join('/')}`,
}));
}
return [];
}
Permissions.keysFromSopsContentAlias = keysFromSopsContentAlias;
/**
* Grants the necessary permissions to decrypt the given sops file content.
* Takes user defined keys, and searches the sops file for keys and aliases.
*/
function sopsKeys(ctx, props) {
(props.userDefinedKeys ?? [])
.concat(keysFromSopsContent(ctx, props.sopsFileContent), keysFromSopsContentAlias(ctx, props.sopsFileContent))
.forEach((key) => key.grantDecrypt(props.role));
}
Permissions.sopsKeys = sopsKeys;
/**
* Grants the necessary permissions to write the given secrets.
*/
function secret(targetSecret, target) {
if (targetSecret === undefined) {
return;
}
targetSecret.grantWrite(target);
}
Permissions.secret = secret;
function sliceParameters(params) {
const result = [];
/**
* The maximum size of a managed policy is 6.144 bytes -> 1 character = 1 byte
* bout 300 characters are reserved for the policy apart from resource arns
* with some buffer, we end with an upper limit of 5750 bytes
*/
const limit = 5750;
/**
* Content for "arn:aws:ssm:ap-southeast-3:<accountnumer>:parameter/
*/
const prefix = 55;
let currentSize = 0;
let currentChunk = [];
for (const param of params) {
const paramLength = param.length + prefix;
if (currentSize + paramLength > limit) {
result.push(currentChunk);
currentChunk = [];
currentSize = 0;
}
currentChunk.push(param);
currentSize += paramLength;
}
if (currentChunk.length > 0) {
result.push(currentChunk);
}
return result;
}
/**
* Grants the necessary permissions to write the given parameters.
*/
function parameters(ctx, targetParameters, role) {
if (targetParameters === undefined) {
return;
}
const paramSlices = sliceParameters(targetParameters);
for (let i = 0; i < paramSlices.length; i++) {
const putPolicy = new aws_iam_1.ManagedPolicy(ctx, `SopsSecretParameterProviderManagedPolicyParameterAccess${i}`, {
description: 'Policy to grant parameter provider permissions to put parameter',
});
putPolicy.addStatements(new aws_iam_1.PolicyStatement({
actions: ['ssm:PutParameter'],
resources: paramSlices[i].map((param) => `arn:aws:ssm:${aws_cdk_lib_1.Stack.of(ctx).region}:${aws_cdk_lib_1.Stack.of(ctx).account}:parameter${param.startsWith('/') ? param : `/${param}`}`),
}));
role.addManagedPolicy(putPolicy);
}
}
Permissions.parameters = parameters;
/**
* Grants the necessary permissions to read the given asset from S3.
*/
function assetBucket(context, asset, target, assetKey) {
if (asset === undefined) {
return;
}
asset.bucket.grantRead(target);
if (assetKey) {
assetKey.grantDecrypt(target);
}
else {
try {
const qualifier = aws_cdk_lib_1.Stack.of(context).synthesizer.bootstrapQualifier ?? 'hnb659fds'; // hnb659fds is the AWS global default qualifier
aws_kms_1.Key.fromLookup(context, 'AssetBucketKey', {
aliasName: `alias/cdk-bootstrap/${qualifier}`,
}).grantDecrypt(target);
}
catch (error) {
aws_cdk_lib_1.Annotations.of(context).addWarningV2('no-asset-kms-key', `An error occured while retreving the KMS-Key for the Asset S3-Bucket from CDK Bootstrap. Set encryption key manually by using props.assetEncryptionKey. ${error}`);
}
}
}
Permissions.assetBucket = assetBucket;
})(Permissions || (exports.Permissions = Permissions = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU29wc1N5bmMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvU29wc1N5bmMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLDZDQVFxQjtBQUVyQixpREFLNkI7QUFDN0IsaURBQWdEO0FBQ2hELHVEQUEwRTtBQUUxRSw2REFBa0Q7QUFFbEQsMkNBQXVDO0FBR3ZDLElBQVksVUFTWDtBQVRELFdBQVksVUFBVTtJQUNwQjs7T0FFRztJQUNILCtCQUFpQixDQUFBO0lBQ2pCOztPQUVHO0lBQ0gsNkJBQWUsQ0FBQTtBQUNqQixDQUFDLEVBVFcsVUFBVSwwQkFBVixVQUFVLFFBU3JCO0FBRUQsSUFBWSxZQU1YO0FBTkQsV0FBWSxZQUFZO0lBQ3RCLGlDQUFpQixDQUFBO0lBQ2pCLHlDQUF5QixDQUFBO0lBQ3pCLCtDQUErQixDQUFBO0lBQy9CLHVDQUF1QixDQUFBO0lBQ3ZCLG1EQUFtQyxDQUFBO0FBQ3JDLENBQUMsRUFOVyxZQUFZLDRCQUFaLFlBQVksUUFNdkI7QUE4S0QsTUFBYSxnQkFBaUIsU0FBUSw4QkFBaUI7SUFHckQsWUFBWSxLQUFnQixFQUFFLEVBQVcsRUFBRSxLQUE2QjtRQUN0RSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsSUFBSSxrQkFBa0IsRUFBRTtZQUNyQyxJQUFJLEVBQUUsaUJBQUksQ0FBQyxTQUFTLENBQ2xCLEtBQUssQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLCtCQUErQixDQUFDO2dCQUN2RCxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSwrQkFBK0IsQ0FBQyxDQUN4RDtZQUNELE9BQU8sRUFBRSxvQkFBTyxDQUFDLFlBQVk7WUFDN0IsT0FBTyxFQUFFLFdBQVc7WUFDcEIsSUFBSSxFQUFFLGtCQUFrQjtZQUN4QixJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUk7WUFDakIsT0FBTyxFQUFFLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FB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QztZQUNKLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQTNCZSx1QkFBVyxjQTJCMUIsQ0FBQTtBQUNILENBQUMsRUEzS2dCLFdBQVcsMkJBQVgsV0FBVyxRQTJLM0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHtcbiAgQW5ub3RhdGlvbnMsXG4gIEN1c3RvbVJlc291cmNlLFxuICBEdXJhdGlvbixcbiAgRmlsZVN5c3RlbSxcbiAgTGF6eSxcbiAgU2VjcmV0VmFsdWUsXG4gIFN0YWNrLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBJU2VjdXJpdHlHcm91cCwgSVZwYywgU3VibmV0U2VsZWN0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQge1xuICBJR3JhbnRhYmxlLFxuICBJUm9sZSxcbiAgTWFuYWdlZFBvbGljeSxcbiAgUG9saWN5U3RhdGVtZW50LFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IElLZXksIEtleSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1rbXMnO1xuaW1wb3J0IHsgQ29kZSwgUnVudGltZSwgU2luZ2xldG9uRnVuY3Rpb24gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IFJldGVudGlvbkRheXMsIElMb2dHcm91cCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sb2dzJztcbmltcG9ydCB7IEFzc2V0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzLWFzc2V0cyc7XG5pbXBvcnQgeyBJU2VjcmV0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXNlY3JldHNtYW5hZ2VyJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgU29wc1N5bmNSZXNvdXJjZVByb3BlcnR5cyB9IGZyb20gJy4vTGFtYmRhSW50ZXJmYWNlJztcblxuZXhwb3J0IGVudW0gVXBsb2FkVHlwZSB7XG4gIC8qKlxuICAgKiBQYXNzIHRoZSBzZWNyZXQgZGF0YSBpbmxpbmUgKGJhc2U2NCBlbmNvZGVkIGFuZCBjb21wcmVzc2VkKVxuICAgKi9cbiAgSU5MSU5FID0gJ0lOTElORScsXG4gIC8qKlxuICAgKiBVcGxhb2QgdGhlIHNlY3JldCBkYXRhIGFzIGFzc2V0XG4gICAqL1xuICBBU1NFVCA9ICdBU1NFVCcsXG59XG5cbmV4cG9ydCBlbnVtIFJlc291cmNlVHlwZSB7XG4gIFNFQ1JFVCA9ICdTRUNSRVQnLFxuICBTRUNSRVRfUkFXID0gJ1NFQ1JFVF9SQVcnLFxuICBTRUNSRVRfQklOQVJZID0gJ1NFQ1JFVF9CSU5BUlknLFxuICBQQVJBTUVURVIgPSAnUEFSQU1FVEVSJyxcbiAgUEFSQU1FVEVSX01VTFRJID0gJ1BBUkFNRVRFUl9NVUxUSScsXG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciB0aGUgU29wc1N5bmNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTb3BzU3luY09wdGlvbnMge1xuICAvKipcbiAgICogVGhlIGN1c3RvbSByZXNvdXJjZSBwcm92aWRlciB0byB1c2UuIElmIHlvdSBkb24ndCBzcGVjaWZ5IGFueSwgYSBuZXdcbiAgICogcHJvdmlkZXIgd2lsbCBiZSBjcmVhdGVkIC0gb3IgaWYgYWxyZWFkeSBleGlzdHMgd2l0aGluIHRoaXMgc3RhY2sgLSByZXVzZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQSBuZXcgc2luZ2xldG9uIHByb3ZpZGVyIHdpbGwgYmUgY3JlYXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgc29wc1Byb3ZpZGVyPzogU29wc1N5bmNQcm92aWRlcjtcblxuICAvKipcbiAgICogVGhlIGZpbGVwYXRoIHRvIHRoZSBzb3BzIGZpbGVcbiAgICovXG4gIHJlYWRvbmx5IHNvcHNGaWxlUGF0aD86IHN0cmluZztcblxuICAvKipcbiAgICogSWYgeW91IHdhbnQgdG8gcGFzcyB0aGUgc29wcyBmaWxlIHZpYSBzMywgeW91IGNhbiBzcGVjaWZ5IHRoZSBidWNrZXRcbiAgICogeW91IGNhbiB1c2UgY2ZuIHBhcmFtZXRlciBoZXJlXG4gICAqIEJvdGgsIHNvcHNTM0J1Y2tldCBhbmQgc29wc1MzS2V5IGhhdmUgdG8gYmUgc3BlY2lmaWVkXG4gICAqL1xuICByZWFkb25seSBzb3BzUzNCdWNrZXQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIElmIHlvdSB3YW50IHRvIHBhc3MgdGhlIHNvcHMgZmlsZSB2aWEgczMsIHlvdSBjYW4gc3BlY2lmeSB0aGUga2V5IGluc2lkZSB0aGUgYnVja2V0XG4gICAqIHlvdSBjYW4gdXNlIGNmbiBwYXJhbWV0ZXIgaGVyZVxuICAgKiBCb3RoLCBzb3BzUzNCdWNrZXQgYW5kIHNvcHNTM0tleSBoYXZlIHRvIGJlIHNwZWNpZmllZFxuICAgKi9cbiAgcmVhZG9ubHkgc29wc1MzS2V5Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBIb3cgc2hvdWxkIHRoZSBzZWNyZXQgYmUgcGFzc2VkIHRvIHRoZSBDdXN0b21SZXNvdXJjZT9cbiAgICogQGRlZmF1bHQgSU5MSU5FXG4gICAqL1xuICByZWFkb25seSB1cGxvYWRUeXBlPzogVXBsb2FkVHlwZTtcblxuICAvKipcbiAgICogVGhlIGZvcm1hdCBvZiB0aGUgc29wcyBmaWxlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRoZSBmaWxlZm9ybWF0IHdpbGwgYmUgZGVyaXZlZCBmcm9tIHRoZSBmaWxlIGVuZGluZ1xuICAgKi9cbiAgcmVhZG9ubHkgc29wc0ZpbGVGb3JtYXQ/OiB1bmRlZmluZWQgfCAnanNvbicgfCAneWFtbCcgfCAnZG90ZW52JyB8ICdiaW5hcnknO1xuXG4gIC8qKlxuICAgKiBUaGUga21zS2V5IHVzZWQgdG8gZW5jcnlwdCB0aGUgc29wcyBmaWxlLiBFbmNyeXB0IHBlcm1pc3Npb25zXG4gICAqIHdpbGwgYmUgZ3JhbnRlZCB0byB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRoZSBrZXkgd2lsbCBiZSBkZXJpdmVkIGZyb20gdGhlIHNvcHMgZmlsZVxuICAgKi9cbiAgcmVhZG9ubHkgc29wc0ttc0tleT86IElLZXlbXTtcblxuICAvKipcbiAgICogVGhlIGFnZSBrZXkgdGhhdCBzaG91bGQgYmUgdXNlZCBmb3IgZW5jcnlwdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IHNvcHNBZ2VLZXk/OiBTZWNyZXRWYWx1ZTtcblxuICAvKipcbiAgICogU2hvdWxkIHRoaXMgY29uc3RydWN0IGF1dG9tYXRpY2FsbHkgY3JlYXRlIElBTSBwZXJtaXNzaW9ucz9cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgYXV0b0dlbmVyYXRlSWFtUGVybWlzc2lvbnM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgZW5jcnlwdGlvbiBrZXkgdXNlZCBieSB0aGUgQ0RLIGRlZmF1bHQgQXNzZXQgUzMgQnVja2V0LlxuICAgKiBAZGVmYXVsdCAtIFRyeWluZyB0byBnZXQgdGhlIGtleSB1c2luZyB0aGUgQ0RLIEJvb3RzdHJhcCBjb250ZXh0LlxuICAgKi9cbiAgcmVhZG9ubHkgYXNzZXRFbmNyeXB0aW9uS2V5PzogSUtleTtcbn1cblxuLyoqXG4gKiBUaGUgY29uZmlndXJhdGlvbiBvcHRpb25zIGV4dGVuZGVkIGJ5IHRoZSB0YXJnZXQgU2VjcmV0IC8gUGFyYW1ldGVyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU29wc1N5bmNQcm9wcyBleHRlbmRzIFNvcHNTeW5jT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgdGFyZ2V0IHRvIHBvcHVsYXRlIHdpdGggdGhlIHNvcHMgZmlsZSBjb250ZW50LlxuICAgKiAtIGZvciBzZWNyZXQsIGl0J3MgdGhlIG5hbWUgb3IgYXJuIG9mIHRoZSBzZWNyZXRcbiAgICogLSBmb3IgcGFyYW1ldGVyLCBpdCdzIHRoZSBuYW1lIG9mIHRoZSBwYXJhbWV0ZXJcbiAgICogLSBmb3IgcGFyYW1ldGVyIG11bHRpLCBpdCdzIHRoZSBwcmVmaXggb2YgdGhlIHBhcmFtZXRlcnNcbiAgICovXG4gIHJlYWRvbmx5IHRhcmdldDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBJZiB0aGUgc3RydWN0dXJlIHNob3VsZCBiZSBmbGF0dGVuZWQgdXNlIHRoZSBwcm92aWRlZCBzZXBhcmF0b3IgYmV0d2VlbiBrZXlzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHVuZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgZmxhdHRlblNlcGFyYXRvcj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGVuY3J5cHRpb24ga2V5IHVzZWQgZm9yIGVuY3J5cHRpbmcgdGhlIHNzbSBwYXJhbWV0ZXIgaWYgYHBhcmFtZXRlck5hbWVgIGlzIHNldC5cbiAgICovXG4gIHJlYWRvbmx5IGVuY3J5cHRpb25LZXk/OiBJS2V5O1xuXG4gIC8qKlxuICAgKiBXaWxsIHRoaXMgU3luYyBkZXBsb3kgYSBTZWNyZXQgb3IgUGFyYW1ldGVyKHMpXG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZVR5cGU6IFJlc291cmNlVHlwZTtcblxuICByZWFkb25seSBzZWNyZXQ/OiBJU2VjcmV0O1xuICByZWFkb25seSBwYXJhbWV0ZXJOYW1lcz86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgYSBjdXN0b20gU29wc1N5bmNQcm92aWRlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTb3BzU3luY1Byb3ZpZGVyUHJvcHMge1xuICAvKipcbiAgICogVlBDIG5ldHdvcmsgdG8gcGxhY2UgTGFtYmRhIG5ldHdvcmsgaW50ZXJmYWNlcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBMYW1iZGEgZnVuY3Rpb24gaXMgbm90IHBsYWNlZCB3aXRoaW4gYSBWUEMuXG4gICAqL1xuICByZWFkb25seSB2cGM/OiBJVnBjO1xuICAvKipcbiAgICogV2hlcmUgdG8gcGxhY2UgdGhlIG5ldHdvcmsgaW50ZXJmYWNlcyB3aXRoaW4gdGhlIFZQQy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBTdWJuZXRzIHdpbGwgYmUgY2hvc2VuIGF1dG9tYXRpY2FsbHkuXG4gICAqL1xuICByZWFkb25seSB2cGNTdWJuZXRzPzogU3VibmV0U2VsZWN0aW9uO1xuICAvKipcbiAgICogT25seSBpZiBgdnBjYCBpcyBzdXBwbGllZDogVGhlIGxpc3Qgb2Ygc2VjdXJpdHkgZ3JvdXBzIHRvIGFzc29jaWF0ZSB3aXRoIHRoZSBMYW1iZGEncyBuZXR3b3JrIGludGVyZmFjZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQSBkZWRpY2F0ZWQgc2VjdXJpdHkgZ3JvdXAgd2lsbCBiZSBjcmVhdGVkIGZvciB0aGUgbGFtYmRhIGZ1bmN0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgc2VjdXJpdHlHcm91cHM/OiBJU2VjdXJpdHlHcm91cFtdO1xuXG4gIC8qKlxuICAgKiBUaGUgcm9sZSB0aGF0IHNob3VsZCBiZSB1c2VkIGZvciB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyLlxuICAgKiBJZiB5b3UgZG9uJ3Qgc3BlY2lmeSBhbnksIGEgbmV3IHJvbGUgd2lsbCBiZSBjcmVhdGVkIHdpdGggYWxsIHJlcXVpcmVkIHBlcm1pc3Npb25zXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYSBuZXcgcm9sZSB3aWxsIGJlIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IHJvbGU/OiBJUm9sZTtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgZGF5cyBsb2cgZXZlbnRzIGFyZSBrZXB0IGluIENsb3VkV2F0Y2ggTG9ncy4gV2hlbiB1cGRhdGluZ1xuICAgKiB0aGlzIHByb3BlcnR5LCB1bnNldHRpbmcgaXQgZG9lc24ndCByZW1vdmUgdGhlIGxvZyByZXRlbnRpb24gcG9saWN5LiBUb1xuICAgKiByZW1vdmUgdGhlIHJldGVudGlvbiBwb2xpY3ksIHNldCB0aGUgdmFsdWUgdG8gYElORklOSVRFYC5cbiAgICpcbiAgICogVGhpcyBpcyBhIGxlZ2FjeSBBUEkgYW5kIHdlIHN0cm9uZ2x5IHJlY29tbWVuZCB5b3UgbW92ZSBhd2F5IGZyb20gaXQgaWYgeW91IGNhbi5cbiAgICogSW5zdGVhZCBjcmVhdGUgYSBmdWxseSBjdXN0b21pemFibGUgbG9nIGdyb3VwIHdpdGggYGxvZ3MuTG9nR3JvdXBgIGFuZCB1c2UgdGhlIGBsb2dHcm91cGAgcHJvcGVydHlcbiAgICogdG8gaW5zdHJ1Y3QgdGhlIExhbWJkYSBmdW5jdGlvbiB0byBzZW5kIGxvZ3MgdG8gaXQuXG4gICAqIE1pZ3JhdGluZyBmcm9tIGBsb2dSZXRlbnRpb25gIHRvIGBsb2dHcm91cGAgd2lsbCBjYXVzZSB0aGUgbmFtZSBvZiB0aGUgbG9nIGdyb3VwIHRvIGNoYW5nZS5cbiAgICogVXNlcnMgYW5kIGNvZGUgYW5kIHJlZmVyZW5jaW5nIHRoZSBuYW1lIHZlcmJhdGltIHdpbGwgaGF2ZSB0byBhZGp1c3QuXG4gICAqXG4gICAqIEluIEFXUyBDREsgY29kZSwgeW91IGNhbiBhY2Nlc3MgdGhlIGxvZyBncm91cCBuYW1lIGRpcmVjdGx5IGZyb20gdGhlIExvZ0dyb3VwIGNvbnN0cnVjdDpcbiAgICogYGBgdHNcbiAgICogaW1wb3J0ICogYXMgbG9ncyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG4gICAqXG4gICAqIGRlY2xhcmUgY29uc3QgbXlMb2dHcm91cDogbG9ncy5Mb2dHcm91cDtcbiAgICogbXlMb2dHcm91cC5sb2dHcm91cE5hbWU7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAZGVmYXVsdCBsb2dzLlJldGVudGlvbkRheXMuSU5GSU5JVEVcbiAgICovXG4gIHJlYWRvbmx5IGxvZ1JldGVudGlvbj86IFJldGVudGlvbkRheXM7XG4gIC8qKlxuICAgKiBUaGUgbG9nIGdyb3VwIHRoZSBmdW5jdGlvbiBzZW5kcyBsb2dzIHRvLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCBMYW1iZGEgZnVuY3Rpb25zIHNlbmQgbG9ncyB0byBhbiBhdXRvbWF0aWNhbGx5IGNyZWF0ZWQgZGVmYXVsdCBsb2cgZ3JvdXAgbmFtZWQgL2F3cy9sYW1iZGEvXFw8ZnVuY3Rpb24gbmFtZVxcPi5cbiAgICogSG93ZXZlciB5b3UgY2Fubm90IGNoYW5nZSB0aGUgcHJvcGVydGllcyBvZiB0aGlzIGF1dG8tY3JlYXRlZCBsb2cgZ3JvdXAgdXNpbmcgdGhlIEFXUyBDREssIGUuZy4geW91IGNhbm5vdCBzZXQgYSBkaWZmZXJlbnQgbG9nIHJldGVudGlvbi5cbiAgICpcbiAgICogVXNlIHRoZSBgbG9nR3JvdXBgIHByb3BlcnR5IHRvIGNyZWF0ZSBhIGZ1bGx5IGN1c3RvbWl6YWJsZSBMb2dHcm91cCBhaGVhZCBvZiB0aW1lLCBhbmQgaW5zdHJ1Y3QgdGhlIExhbWJkYSBmdW5jdGlvbiB0byBzZW5kIGxvZ3MgdG8gaXQuXG4gICAqXG4gICAqIFByb3ZpZGluZyBhIHVzZXItY29udHJvbGxlZCBsb2cgZ3JvdXAgd2FzIHJvbGxlZCBvdXQgdG8gY29tbWVyY2lhbCByZWdpb25zIG9uIDIwMjMtMTEtMTYuXG4gICAqIElmIHlvdSBhcmUgZGVwbG95aW5nIHRvIGFub3RoZXIgdHlwZSBvZiByZWdpb24sIHBsZWFzZSBjaGVjayByZWdpb25hbCBhdmFpbGFiaWxpdHkgZmlyc3QuXG4gICAqXG4gICAqIEBkZWZhdWx0IGAvYXdzL2xhbWJkYS8ke3RoaXMuZnVuY3Rpb25OYW1lfWAgLSBkZWZhdWx0IGxvZyBncm91cCBjcmVhdGVkIGJ5IExhbWJkYVxuICAgKi9cbiAgcmVhZG9ubHkgbG9nR3JvdXA/OiBJTG9nR3JvdXA7XG59XG5cbmV4cG9ydCBjbGFzcyBTb3BzU3luY1Byb3ZpZGVyIGV4dGVuZHMgU2luZ2xldG9uRnVuY3Rpb24gaW1wbGVtZW50cyBJR3JhbnRhYmxlIHtcbiAgcHJpdmF0ZSBzb3BzQWdlS2V5czogU2VjcmV0VmFsdWVbXTtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZD86IHN0cmluZywgcHJvcHM/OiBTb3BzU3luY1Byb3ZpZGVyUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQgPz8gJ1NvcHNTeW5jUHJvdmlkZXInLCB7XG4gICAgICBjb2RlOiBDb2RlLmZyb21Bc3NldChcbiAgICAgICAgc2NvcGUubm9kZS50cnlHZXRDb250ZXh0KCdzb3BzX3N5bmNfcHJvdmlkZXJfYXNzZXRfcGF0aCcpIHx8XG4gICAgICAgICAgcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL2Fzc2V0cy9jZGstc29wcy1sYW1iZGEuemlwJyksXG4gICAgICApLFxuICAgICAgcnVudGltZTogUnVudGltZS5QUk9WSURFRF9BTDIsXG4gICAgICBoYW5kbGVyOiAnYm9vdHN0cmFwJyxcbiAgICAgIHV1aWQ6ICdTb3BzU3luY1Byb3ZpZGVyJyxcbiAgICAgIHJvbGU6IHByb3BzPy5yb2xlLFxuICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcyg2MCksXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBTT1BTX0FHRV9LRVk6IExhenkuc3RyaW5nKHtcbiAgICAgICAgICBwcm9kdWNlOiAoKSA9PlxuICAgICAgICAgICAgKHRoaXMuc29wc0FnZUtleXMubWFwKChzZWNyZXQpID0+IHNlY3JldC50b1N0cmluZygpKSA/PyBbXSkuam9pbihcbiAgICAgICAgICAgICAgJ1xcbicsXG4gICAgICAgICAgICApLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgICB2cGM6IHByb3BzPy52cGMsXG4gICAgICB2cGNTdWJuZXRzOiBwcm9wcz8udnBjU3VibmV0cyxcbiAgICAgIHNlY3VyaXR5R3JvdXBzOiBwcm9wcz8uc2VjdXJpdHlHcm91cHMsXG4gICAgICBsb2dSZXRlbnRpb246IHByb3BzPy5sb2dSZXRlbnRpb24sXG4gICAgICBsb2dHcm91cDogcHJvcHM/LmxvZ0dyb3VwLFxuICAgIH0pO1xuICAgIHRoaXMuc29wc0FnZUtleXMgPSBbXTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRBZ2VLZXkoa2V5OiBTZWNyZXRWYWx1ZSkge1xuICAgIHRoaXMuc29wc0FnZUtleXMucHVzaChrZXkpO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGN1c3RvbSByZXNvdXJjZSwgdGhhdCBpcyBzeW5jaW5nIHRoZSBjb250ZW50IGZyb20gYSBzb3BzIGZpbGUgdG8gYSBzZWNyZXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBTb3BzU3luYyBleHRlbmRzIENvbnN0cnVjdCB7XG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCB2ZXJzaW9uSWQgb2YgdGhlIHNlY3JldCBwb3B1bGF0ZWQgdmlhIHRoaXMgcmVzb3VyY2VcbiAgICovXG4gIHJlYWRvbmx5IHZlcnNpb25JZDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBTb3BzU3luY1Byb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGNvbnN0IHByb3ZpZGVyID0gcHJvcHMuc29wc1Byb3ZpZGVyID8/IG5ldyBTb3BzU3luY1Byb3ZpZGVyKHNjb3BlKTtcblxuICAgIGxldCB1cGxvYWRUeXBlID0gcHJvcHMudXBsb2FkVHlwZSA/PyBVcGxvYWRUeXBlLklOTElORTtcbiAgICBsZXQgc29wc0ZpbGVGb3JtYXQ6ICdqc29uJyB8ICd5YW1sJyB8ICdkb3RlbnYnIHwgJ2JpbmFyeScgfCB1bmRlZmluZWQgPVxuICAgICAgcHJvcHMuc29wc0ZpbGVGb3JtYXQ7XG4gICAgbGV0IHNvcHNBc3NldDogQXNzZXQgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgbGV0IHNvcHNJbmxpbmU6IHsgQ29udGVudDogc3RyaW5nOyBIYXNoOiBzdHJpbmcgfSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICBsZXQgc29wc1MzRmlsZTogeyBCdWNrZXQ6IHN0cmluZzsgS2V5OiBzdHJpbmcgfSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICAgIGlmIChcbiAgICAgIChwcm9wcy5zb3BzRmlsZVBhdGggPT0gdW5kZWZpbmVkICYmXG4gICAgICAgIChwcm9wcy5zb3BzUzNCdWNrZXQgPT0gdW5kZWZpbmVkIHx8IHByb3BzLnNvcHNTM0tleSA9PSB1bmRlZmluZWQpKSB8fFxuICAgICAgKHByb3BzLnNvcHNGaWxlUGF0aCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgIHByb3BzLnNvcHNTM0J1Y2tldCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgIHByb3BzLnNvcHNTM0tleSAhPT0gdW5kZWZpbmVkKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnWW91IGNhbiBlaXRoZXIgc3BlY2lmeSBzb3BzRmlsZVBhdGggb3Igc29wc1MzQnVja2V0IGFuZCBzb3BzUzNLZXkhJyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLnNvcHNGaWxlUGF0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoc29wc0ZpbGVGb3JtYXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zdCBfc29wc0ZpbGVGb3JtYXQgPSBwcm9wcy5zb3BzRmlsZVBhdGguc3BsaXQoJy4nKS5wb3AoKTtcbiAgICAgICAgc3dpdGNoIChfc29wc0ZpbGVGb3JtYXQpIHtcbiAgICAgICAgICBjYXNlICdqc29uJzoge1xuICAgICAgICAgICAgc29wc0ZpbGVGb3JtYXQgPSAnanNvbic7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY2FzZSAneWFtbCc6IHtcbiAgICAgICAgICAgIHNvcHNGaWxlRm9ybWF0ID0gJ3lhbWwnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNhc2UgJ3ltbCc6IHtcbiAgICAgICAgICAgIHNvcHNGaWxlRm9ybWF0ID0gJ3lhbWwnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNhc2UgJ2RvdGVudic6IHtcbiAgICAgICAgICAgIHNvcHNGaWxlRm9ybWF0ID0gJ2RvdGVudic7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY2FzZSAnZW52Jzoge1xuICAgICAgICAgICAgc29wc0ZpbGVGb3JtYXQgPSAnZG90ZW52JztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjYXNlICdiaW5hcnknOiB7XG4gICAgICAgICAgICBzb3BzRmlsZUZvcm1hdCA9ICdiaW5hcnknO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZEVycm9yKFxuICAgICAgICAgICAgICBcIkZhaWxlZCB0byBkZXRlcm1pbmUgc29wcyBmaWxlIGZvcm1hdC4gUGxlYXNlIHNwZWNpZnkgJ3NvcHNGaWxlRm9ybWF0JyFcIixcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhwcm9wcy5zb3BzRmlsZVBhdGgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmlsZSAke3Byb3BzLnNvcHNGaWxlUGF0aH0gZG9lcyBub3QgZXhpc3QhYCk7XG4gICAgICB9XG4gICAgICBjb25zdCBzb3BzRmlsZUNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMocHJvcHMuc29wc0ZpbGVQYXRoKTtcblxuICAgICAgc3dpdGNoICh1cGxvYWRUeXBlKSB7XG4gICAgICAgIGNhc2UgVXBsb2FkVHlwZS5JTkxJTkU6IHtcbiAgICAgICAgICBzb3BzSW5saW5lID0ge1xuICAgICAgICAgICAgQ29udGVudDogc29wc0ZpbGVDb250ZW50LnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgICAgICAgIC8vIFdlIGNhbGN1bGF0ZSB0aGUgaGFzaCB0aGUgc2FtZSB3YXkgYXMgaXQgd291bGQgYmUgZG9uZSBieSBuZXcgQXNzZXQoLi4pIC0gc28gd2UgY2FuIGVuc3VyZSBzdGFibGUgdmVyc2lvbiBuYW1lcyBldmVuIGlmIHN3aXRjaGluZyBmcm9tIElOTElORSB0byBBU1NFVCBhbmQgdmljZXZlcnNhLlxuICAgICAgICAgICAgSGFzaDogRmlsZVN5c3RlbS5maW5nZXJwcmludChwcm9wcy5zb3BzRmlsZVBhdGgpLFxuICAgICAgICAgIH07XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSBVcGxvYWRUeXBlLkFTU0VUOiB7XG4gICAgICAgICAgc29wc0Fzc2V0ID0gbmV3IEFzc2V0KHRoaXMsICdBc3NldCcsIHtcbiAgICAgICAgICAgIHBhdGg6IHByb3BzLnNvcHNGaWxlUGF0aCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBzb3BzUzNGaWxlID0ge1xuICAgICAgICAgICAgQnVja2V0OiBzb3BzQXNzZXQuYnVja2V0LmJ1Y2tldE5hbWUsXG4gICAgICAgICAgICBLZXk6IHNvcHNBc3NldC5zM09iamVjdEtleSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgLy8gSXMgYWxsd2F5cyB0cnVlLCBidXQgdG8gc2F0aXNmeSBUUyB3ZSBjaGVjayBleHBsaWNpdGx5XG4gICAgICAgIHByb3ZpZGVyLnJvbGUgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAvLyBDaGVjayBpZiB1c2VyIGhhcyBkaXNhYmxlZCBhdXRvbWF0aWMgZ2VuZXJhdGlvblxuICAgICAgICBwcm9wcy5hdXRvR2VuZXJhdGVJYW1QZXJtaXNzaW9ucyAhPT0gZmFsc2VcbiAgICAgICkge1xuICAgICAgICBQZXJtaXNzaW9ucy5zb3BzS2V5cyh0aGlzLCB7XG4gICAgICAgICAgdXNlckRlZmluZWRLZXlzOiBwcm9wcy5zb3BzS21zS2V5LFxuICAgICAgICAgIHJvbGU6IHByb3ZpZGVyLnJvbGUsXG4gICAgICAgICAgc29wc0ZpbGVDb250ZW50OiBzb3BzRmlsZUNvbnRlbnQudG9TdHJpbmcoKSxcbiAgICAgICAgfSk7XG4gICAgICAgIFBlcm1pc3Npb25zLmFzc2V0QnVja2V0KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgc29wc0Fzc2V0LFxuICAgICAgICAgIHByb3ZpZGVyLnJvbGUsXG4gICAgICAgICAgcHJvcHMuYXNzZXRFbmNyeXB0aW9uS2V5LFxuICAgICAgICApO1xuICAgICAgICBQZXJtaXNzaW9ucy5lbmNyeXB0aW9uS2V5KHByb3BzLmVuY3J5cHRpb25LZXksIHByb3ZpZGVyLnJvbGUpO1xuICAgICAgICBQZXJtaXNzaW9ucy5zZWNyZXQocHJvcHMuc2VjcmV0LCBwcm92aWRlci5yb2xlKTtcbiAgICAgICAgUGVybWlzc2lvbnMucGFyYW1ldGVycyh0aGlzLCBwcm9wcy5wYXJhbWV0ZXJOYW1lcywgcHJvdmlkZXIucm9sZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBBbm5vdGF0aW9ucy5vZih0aGlzKS5hZGRXYXJuaW5nKFxuICAgICAgICAgIFtcbiAgICAgICAgICAgICdQbGVhc2UgZW5zdXJlIHByb3BlciBwZXJtaXNzaW9ucyBmb3IgdGhlIHBhc3NlZCBsYW1iZGEgZnVuY3Rpb246JyxcbiAgICAgICAgICAgICcgIC0gd3JpdGUgQWNjZXNzIHRvIHRoZSBzZWNyZXQvcGFyYW1ldGVycycsXG4gICAgICAgICAgICAnICAtIGVuY3J5cHQgd2l0aCB0aGUgc29wc0ttc0tleScsXG4gICAgICAgICAgICAnICAtIGRvd25sb2FkIGZyb20gYXNzZXQgYnVja2V0JyxcbiAgICAgICAgICBdLmpvaW4oJ1xcbicpLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKHByb3BzLnNvcHNBZ2VLZXkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBwcm92aWRlci5hZGRBZ2VLZXkocHJvcHMuc29wc0FnZUtleSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIHByb3BzLnNvcHNTM0J1Y2tldCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICBwcm9wcy5zb3BzUzNLZXkgIT09IHVuZGVmaW5lZFxuICAgICkge1xuICAgICAgc29wc1MzRmlsZSA9IHtcbiAgICAgICAgQnVja2V0OiBwcm9wcy5zb3BzUzNCdWNrZXQsXG4gICAgICAgIEtleTogcHJvcHMuc29wc1MzS2V5LFxuICAgICAgfTtcbiAgICAgIHVwbG9hZFR5cGUgPSBVcGxvYWRUeXBlLkFTU0VUO1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkV2FybmluZyhcbiAgICAgICAgJ1lvdSBoYXZlIHRvIG1hbnVhbGx5IGFkZCBwZXJtaXNzaW9ucyB0byB0aGUgc29wcyBwcm92aWRlciB0byAocGVybWlzc2lvbiB0byBkb3dubG9hZCBmaWxlLCB0byBkZWNyeXB0IHNvcHMgZmlsZSkhJyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKHNvcHNGaWxlRm9ybWF0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignWW91IGhhdmUgdG8gc3BlY2lmeSBzb3BzRmlsZUZvcm1hdCEnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjciA9IG5ldyBDdXN0b21SZXNvdXJjZSh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IHByb3ZpZGVyLmZ1bmN0aW9uQXJuLFxuICAgICAgcmVzb3VyY2VUeXBlOiAnQ3VzdG9tOjpTb3BzU3luYycsXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIFNvcHNTM0ZpbGU6IHNvcHNTM0ZpbGUsXG4gICAgICAgIFNvcHNJbmxpbmU6IHNvcHNJbmxpbmUsXG4gICAgICAgIEZsYXR0ZW5TZXBhcmF0b3I6IHByb3BzLmZsYXR0ZW5TZXBhcmF0b3IsXG4gICAgICAgIEZvcm1hdDogc29wc0ZpbGVGb3JtYXQsXG4gICAgICAgIEVuY3J5cHRpb25LZXk6IHByb3BzLmVuY3J5cHRpb25LZXk/LmtleUlkLFxuICAgICAgICBSZXNvdXJjZVR5cGU6IHByb3BzLnJlc291cmNlVHlwZSxcbiAgICAgICAgVGFyZ2V0OiBwcm9wcy50YXJnZXQsXG4gICAgICB9IHNhdGlzZmllcyBTb3BzU3luY1Jlc291cmNlUHJvcGVydHlzLFxuICAgIH0pO1xuICAgIHRoaXMudmVyc2lvbklkID0gY3IuZ2V0QXR0U3RyaW5nKCdWZXJzaW9uSWQnKTtcbiAgfVxufVxuXG5leHBvcnQgbmFtZXNwYWNlIFBlcm1pc3Npb25zIHtcbiAgLyoqXG4gICAqIEdyYW50cyB0aGUgbmVjZXNzYXJ5IHBlcm1pc3Npb25zIGZvciBlbmNyeXB0L2RlY3J5cHQgb24gdGhlIGN1c3RvbWVyIG1hbmFnZWQgZW5jcnlwdGlvbiBrZXlcbiAgICogZm9yIHRoZSBzZWNyZXRzIC8gcGFyYW1ldGVycy5cbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBlbmNyeXB0aW9uS2V5KGtleTogSUtleSB8IHVuZGVmaW5lZCwgdGFyZ2V0OiBJR3JhbnRhYmxlKSB7XG4gICAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGtleS5ncmFudEVuY3J5cHREZWNyeXB0KHRhcmdldCk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24ga2V5c0Zyb21Tb3BzQ29udGVudChjdHg6IENvbnN0cnVjdCwgYzogc3RyaW5nKTogSUtleVtdIHtcbiAgICBjb25zdCByZWdleEtleSA9IC9hcm46YXdzOmttczpbYS16MC05LV0rOltcXGRdKzprZXlcXC9bYS16MC05LV0rL2c7XG4gICAgY29uc3QgcmVzdWx0c0tleSA9IGMubWF0Y2gocmVnZXhLZXkpO1xuICAgIGlmIChyZXN1bHRzS2V5ICE9PSBudWxsKSB7XG4gICAgICByZXR1cm4gcmVzdWx0c0tleS5tYXAoKHJlc3VsdCwgaW5kZXgpID0+XG4gICAgICAgIEtleS5mcm9tS2V5QXJuKGN0eCwgYFNvcHNLZXkke2luZGV4fWAsIHJlc3VsdCksXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24ga2V5c0Zyb21Tb3BzQ29udGVudEFsaWFzKGN0eDogQ29uc3RydWN0LCBjOiBzdHJpbmcpOiBJS2V5W10ge1xuICAgIGNvbnN0IHJlZ2V4QWxpYXMgPSAvYXJuOmF3czprbXM6W2EtejAtOS1dKzpbXFxkXSs6YWxpYXNcXC9bYS16MC05LUEtWlxcL10rL2c7XG4gICAgY29uc3QgcmVzdWx0c0FsaWFzID0gYy5tYXRjaChyZWdleEFsaWFzKTtcbiAgICBpZiAocmVzdWx0c0FsaWFzICE9PSBudWxsKSB7XG4gICAgICByZXR1cm4gcmVzdWx0c0FsaWFzLm1hcCgocmVzdWx0LCBpbmRleCkgPT5cbiAgICAgICAgS2V5LmZyb21Mb29rdXAoY3R4LCBgU29wc0FsaWFzJHtpbmRleH1gLCB7XG4gICAgICAgICAgYWxpYXNOYW1lOiBgYWxpYXMvJHtyZXN1bHQuc3BsaXQoJy8nKS5zbGljZSgxKS5qb2luKCcvJyl9YCxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHRoZSBuZWNlc3NhcnkgcGVybWlzc2lvbnMgdG8gZGVjcnlwdCB0aGUgZ2l2ZW4gc29wcyBmaWxlIGNvbnRlbnQuXG4gICAqIFRha2VzIHVzZXIgZGVmaW5lZCBrZXlzLCBhbmQgc2VhcmNoZXMgdGhlIHNvcHMgZmlsZSBmb3Iga2V5cyBhbmQgYWxpYXNlcy5cbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBzb3BzS2V5cyhcbiAgICBjdHg6IENvbnN0cnVjdCxcbiAgICBwcm9wczoge1xuICAgICAgdXNlckRlZmluZWRLZXlzPzogSUtleVtdO1xuICAgICAgc29wc0ZpbGVDb250ZW50OiBzdHJpbmc7XG4gICAgICByb2xlOiBJUm9sZTtcbiAgICB9LFxuICApIHtcbiAgICAocHJvcHMudXNlckRlZmluZWRLZXlzID8/IFtdKVxuICAgICAgLmNvbmNhdChcbiAgICAgICAga2V5c0Zyb21Tb3BzQ29udGVudChjdHgsIHByb3BzLnNvcHNGaWxlQ29udGVudCksXG4gICAgICAgIGtleXNGcm9tU29wc0NvbnRlbnRBbGlhcyhjdHgsIHByb3BzLnNvcHNGaWxlQ29udGVudCksXG4gICAgICApXG4gICAgICAuZm9yRWFjaCgoa2V5KSA9PiBrZXkuZ3JhbnREZWNyeXB0KHByb3BzLnJvbGUpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgdGhlIG5lY2Vzc2FyeSBwZXJtaXNzaW9ucyB0byB3cml0ZSB0aGUgZ2l2ZW4gc2VjcmV0cy5cbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBzZWNyZXQoXG4gICAgdGFyZ2V0U2VjcmV0OiBJU2VjcmV0IHwgdW5kZWZpbmVkLFxuICAgIHRhcmdldDogSUdyYW50YWJsZSxcbiAgKSB7XG4gICAgaWYgKHRhcmdldFNlY3JldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRhcmdldFNlY3JldC5ncmFudFdyaXRlKHRhcmdldCk7XG4gIH1cblxuICBmdW5jdGlvbiBzbGljZVBhcmFtZXRlcnMocGFyYW1zOiBzdHJpbmdbXSk6IHN0cmluZ1tdW10ge1xuICAgIGNvbnN0IHJlc3VsdDogc3RyaW5nW11bXSA9IFtdO1xuICAgIC8qKlxuICAgICAqIFRoZSBtYXhpbXVtIHNpemUgb2YgYSBtYW5hZ2VkIHBvbGljeSBpcyA2LjE0NCBieXRlcyAtPiAxIGNoYXJhY3RlciA9IDEgYnl0ZVxuICAgICAqIGJvdXQgMzAwIGNoYXJhY3RlcnMgYXJlIHJlc2VydmVkIGZvciB0aGUgcG9saWN5IGFwYXJ0IGZyb20gcmVzb3VyY2UgYXJuc1xuICAgICAqIHdpdGggc29tZSBidWZmZXIsIHdlIGVuZCB3aXRoIGFuIHVwcGVyIGxpbWl0IG9mIDU3NTAgYnl0ZXNcbiAgICAgKi9cbiAgICBjb25zdCBsaW1pdCA9IDU3NTA7XG5cbiAgICAvKipcbiAgICAgKiBDb250ZW50IGZvciBcImFybjphd3M6c3NtOmFwLXNvdXRoZWFzdC0zOjxhY2NvdW50bnVtZXI+OnBhcmFtZXRlci9cbiAgICAgKi9cbiAgICBjb25zdCBwcmVmaXggPSA1NTtcblxuICAgIGxldCBjdXJyZW50U2l6ZSA9IDA7XG4gICAgbGV0IGN1cnJlbnRDaHVuazogc3RyaW5nW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHBhcmFtIG9mIHBhcmFtcykge1xuICAgICAgY29uc3QgcGFyYW1MZW5ndGggPSBwYXJhbS5sZW5ndGggKyBwcmVmaXg7XG4gICAgICBpZiAoY3VycmVudFNpemUgKyBwYXJhbUxlbmd0aCA+IGxpbWl0KSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGN1cnJlbnRDaHVuayk7XG4gICAgICAgIGN1cnJlbnRDaHVuayA9IFtdO1xuICAgICAgICBjdXJyZW50U2l6ZSA9IDA7XG4gICAgICB9XG4gICAgICBjdXJyZW50Q2h1bmsucHVzaChwYXJhbSk7XG4gICAgICBjdXJyZW50U2l6ZSArPSBwYXJhbUxlbmd0aDtcbiAgICB9XG5cbiAgICBpZiAoY3VycmVudENodW5rLmxlbmd0aCA+IDApIHtcbiAgICAgIHJlc3VsdC5wdXNoKGN1cnJlbnRDaHVuayk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHRoZSBuZWNlc3NhcnkgcGVybWlzc2lvbnMgdG8gd3JpdGUgdGhlIGdpdmVuIHBhcmFtZXRlcnMuXG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gcGFyYW1ldGVycyhcbiAgICBjdHg6IENvbnN0cnVjdCxcbiAgICB0YXJnZXRQYXJhbWV0ZXJzOiBzdHJpbmdbXSB8IHVuZGVmaW5lZCxcbiAgICByb2xlOiBJUm9sZSxcbiAgKSB7XG4gICAgaWYgKHRhcmdldFBhcmFtZXRlcnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcmFtU2xpY2VzID0gc2xpY2VQYXJhbWV0ZXJzKHRhcmdldFBhcmFtZXRlcnMpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJhbVNsaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgcHV0UG9saWN5ID0gbmV3IE1hbmFnZWRQb2xpY3koXG4gICAgICAgIGN0eCxcbiAgICAgICAgYFNvcHNTZWNyZXRQYXJhbWV0ZXJQcm92aWRlck1hbmFnZWRQb2xpY3lQYXJhbWV0ZXJBY2Nlc3Mke2l9YCxcbiAgICAgICAge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgJ1BvbGljeSB0byBncmFudCBwYXJhbWV0ZXIgcHJvdmlkZXIgcGVybWlzc2lvbnMgdG8gcHV0IHBhcmFtZXRlcicsXG4gICAgICAgIH0sXG4gICAgICApO1xuICAgICAgcHV0UG9saWN5LmFkZFN0YXRlbWVudHMoXG4gICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFsnc3NtOlB1dFBhcmFtZXRlciddLFxuICAgICAgICAgIHJlc291cmNlczogcGFyYW1TbGljZXNbaV0ubWFwKFxuICAgICAgICAgICAgKHBhcmFtKSA9PlxuICAgICAgICAgICAgICBgYXJuOmF3czpzc206JHtTdGFjay5vZihjdHgpLnJlZ2lvbn06JHtcbiAgICAgICAgICAgICAgICBTdGFjay5vZihjdHgpLmFjY291bnRcbiAgICAgICAgICAgICAgfTpwYXJhbWV0ZXIke3BhcmFtLnN0YXJ0c1dpdGgoJy8nKSA/IHBhcmFtIDogYC8ke3BhcmFtfWB9YCxcbiAgICAgICAgICApLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgICByb2xlLmFkZE1hbmFnZWRQb2xpY3kocHV0UG9saWN5KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHRoZSBuZWNlc3NhcnkgcGVybWlzc2lvbnMgdG8gcmVhZCB0aGUgZ2l2ZW4gYXNzZXQgZnJvbSBTMy5cbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBhc3NldEJ1Y2tldChcbiAgICBjb250ZXh0OiBDb25zdHJ1Y3QsXG4gICAgYXNzZXQ6IEFzc2V0IHwgdW5kZWZpbmVkLFxuICAgIHRhcmdldDogSUdyYW50YWJsZSxcbiAgICBhc3NldEtleTogSUtleSB8IHVuZGVmaW5lZCxcbiAgKSB7XG4gICAgaWYgKGFzc2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXNzZXQuYnVja2V0LmdyYW50UmVhZCh0YXJnZXQpO1xuXG4gICAgaWYgKGFzc2V0S2V5KSB7XG4gICAgICBhc3NldEtleS5ncmFudERlY3J5cHQodGFyZ2V0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcXVhbGlmaWVyID1cbiAgICAgICAgICBTdGFjay5vZihjb250ZXh0KS5zeW50aGVzaXplci5ib290