cdk-encrypted-secret
Version:
CDK Construct that creates an AWS Secret Manager Secret and sets the value from an encrypted Ciphertext.
130 lines • 19.1 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.EncryptedSecret = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const crypto = require("crypto");
const path = require("path");
const util_arn_parser_1 = require("@aws-sdk/util-arn-parser");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
const aws_logs_1 = require("aws-cdk-lib/aws-logs");
const aws_secretsmanager_1 = require("aws-cdk-lib/aws-secretsmanager");
const custom_resources_1 = require("aws-cdk-lib/custom-resources");
const constructs_1 = require("constructs");
/**
* EncryptedSecret is a custom construct that creates a Secret in Secrets Manager and decrypts the ciphertext
* using the KMS Key ARN provided and stores the decrypted value in the Secret.
*
* @class EncryptedSecret
* @extends {Construct}
* @param {Construct} scope - The scope of the construct.
* @param {string} id - The id of the construct.
* @param {EncryptedSecretProps} props - The EncryptedSecretProps for the EncryptedSecret construct.
*/
class EncryptedSecret extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
// Ensure keyId is valid
if (!(0, util_arn_parser_1.validate)(props.keyId)) {
throw new Error('Invalid keyId.');
}
// Parse keyId as ARN
const kmsKey = (0, util_arn_parser_1.parse)(props.keyId);
// Ensure ciphertextBlob is non-empty
if (!props.ciphertextBlob.length) {
throw new Error('ciphertextBlob cannot be empty');
}
if (props.existingSecretObj) {
// If existingSecretObj is provided, use it
this.secret = props.existingSecretObj;
}
else {
// create a secret with the secretProps provided
this.secret = new aws_secretsmanager_1.Secret(this, 'Secrets', props.secretProps);
}
// Create the Lambda Function to decrypt the ciphertext and store the value in the Secret
const decryptSecretFunction = new aws_lambda_1.SingletonFunction(this, 'DecryptSecretFunction', {
lambdaPurpose: 'DecryptSecret',
uuid: crypto.createHash('md5').update(aws_cdk_lib_1.Stack.of(this).environment).digest('hex'),
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
architecture: aws_lambda_1.Architecture.ARM_64,
code: aws_lambda_1.Code.fromAsset(path.join(__dirname, 'lambda')),
handler: 'index.handler',
memorySize: 128,
environment: {
KMS_KEY_REGION: kmsKey.region,
},
logGroup: new aws_logs_1.LogGroup(this, 'DecryptSecretFunctionLogGroup', {
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
retention: props.logRetentionDays ?? aws_logs_1.RetentionDays.ONE_WEEK,
}),
});
// Add to the Policy Statement the ability to decrypt the cipherText with KMS against the kmsKeyArn in the props
decryptSecretFunction.addToRolePolicy(new aws_iam_1.PolicyStatement({
actions: ['kms:Decrypt'],
resources: [props.keyId],
}));
// Add to the Policy Statement the ability to put the secret value into Secrets Manager
decryptSecretFunction.addToRolePolicy(new aws_iam_1.PolicyStatement({
actions: ['secretsmanager:PutSecretValue'],
resources: [this.secret.secretArn],
}));
if (this.secret.encryptionKey) {
// Add to the Lambda Function Policy Statement the ability to encrypt using the encryption key of the secret
decryptSecretFunction.addToRolePolicy(new aws_iam_1.PolicyStatement({
actions: ['kms:Encrypt'],
resources: [this.secret.encryptionKey.keyArn],
}));
// Modify Key Policy to allow the Lambda to use the KMS Key to encrypt the Secret
this.secret.encryptionKey.grantEncrypt(decryptSecretFunction);
}
// Create the custom resource
const lambdaInvokeAwsCustomResource = new custom_resources_1.AwsCustomResource(this, 'CustomResourceSecretLambdaInvoke', {
onCreate: {
service: 'Lambda',
action: 'invoke',
parameters: {
FunctionName: decryptSecretFunction.functionName,
Payload: '{"secretArn": "' +
this.secret.secretArn +
'","keyId": "' +
props.keyId +
'", "cipherText": "' +
props.ciphertextBlob +
'"}',
},
physicalResourceId: custom_resources_1.PhysicalResourceId.of('CustomResourceSecretLambdaInvoke'),
},
onUpdate: {
service: 'Lambda',
action: 'invoke',
parameters: {
FunctionName: decryptSecretFunction.functionName,
Payload: '{"secretArn": "' +
this.secret.secretArn +
'","keyId": "' +
props.keyId +
'", "cipherText": "' +
props.ciphertextBlob +
'"}',
},
physicalResourceId: custom_resources_1.PhysicalResourceId.of('CustomResourceSecretLambdaInvoke'),
},
policy: custom_resources_1.AwsCustomResourcePolicy.fromSdkCalls({
resources: [decryptSecretFunction.functionArn],
}),
logGroup: new aws_logs_1.LogGroup(this, 'CustomResourceSecretLambdaInvokeLogGroup', {
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
retention: props.logRetentionDays ?? aws_logs_1.RetentionDays.ONE_WEEK,
}),
});
// Grant the Lambda Invoke permissions to the lambdaInvoke custom resource
decryptSecretFunction.grantInvoke(lambdaInvokeAwsCustomResource);
}
}
exports.EncryptedSecret = EncryptedSecret;
_a = JSII_RTTI_SYMBOL_1;
EncryptedSecret[_a] = { fqn: "cdk-encrypted-secret.EncryptedSecret", version: "1.3.8" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxpQ0FBaUM7QUFDakMsNkJBQTZCO0FBQzdCLDhEQUFnRTtBQUNoRSw2Q0FBbUQ7QUFDbkQsaURBQXNEO0FBQ3RELHVEQUF3RjtBQUN4RixtREFBK0Q7QUFDL0QsdUVBQXFFO0FBQ3JFLG1FQUE4RztBQUM5RywyQ0FBdUM7QUFvQnZDOzs7Ozs7Ozs7R0FTRztBQUNILE1BQWEsZUFBZ0IsU0FBUSxzQkFBUztJQUU1QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTJCO1FBQ25FLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsd0JBQXdCO1FBQ3hCLElBQUksQ0FBQyxJQUFBLDBCQUFRLEVBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDM0IsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3BDLENBQUM7UUFDRCxxQkFBcUI7UUFDckIsTUFBTSxNQUFNLEdBQVEsSUFBQSx1QkFBSyxFQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV2QyxxQ0FBcUM7UUFDckMsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDakMsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1FBQ3BELENBQUM7UUFFRCxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQzVCLDJDQUEyQztZQUMzQyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQztRQUN4QyxDQUFDO2FBQU0sQ0FBQztZQUNOLGdEQUFnRDtZQUNoRCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksMkJBQU0sQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztR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QyxTQUFTO3dCQUNyQixjQUFjO3dCQUNkLEtBQUssQ0FBQyxLQUFLO3dCQUNYLG9CQUFvQjt3QkFDcEIsS0FBSyxDQUFDLGNBQWM7d0JBQ3BCLElBQUk7aUJBQ1A7Z0JBQ0Qsa0JBQWtCLEVBQUUscUNBQWtCLENBQUMsRUFBRSxDQUFDLGtDQUFrQyxDQUFDO2FBQzlFO1lBQ0QsTUFBTSxFQUFFLDBDQUF1QixDQUFDLFlBQVksQ0FBQztnQkFDM0MsU0FBUyxFQUFFLENBQUMscUJBQXFCLENBQUMsV0FBVyxDQUFDO2FBQy9DLENBQUM7WUFDRixRQUFRLEVBQUUsSUFBSSxtQkFBUSxDQUFDLElBQUksRUFBRSwwQ0FBMEMsRUFBRTtnQkFDdkUsYUFBYSxFQUFFLDJCQUFhLENBQUMsT0FBTztnQkFDcEMsU0FBUyxFQUFFLEtBQUssQ0FBQyxnQkFBZ0IsSUFBSSx3QkFBYSxDQUFDLFFBQVE7YUFDNUQsQ0FBQztTQUNILENBQUMsQ0FBQztRQUVILDBFQUEwRTtRQUMxRSxxQkFBcUIsQ0FBQyxXQUFXLENBQUMsNkJBQTZCLENBQUMsQ0FBQztJQUNuRSxDQUFDOztBQXJISCwwQ0FzSEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnY3J5cHRvJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBBUk4sIHBhcnNlLCB2YWxpZGF0ZSB9IGZyb20gJ0Bhd3Mtc2RrL3V0aWwtYXJuLXBhcnNlcic7XG5pbXBvcnQgeyBSZW1vdmFsUG9saWN5LCBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IFBvbGljeVN0YXRlbWVudCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgQXJjaGl0ZWN0dXJlLCBDb2RlLCBSdW50aW1lLCBTaW5nbGV0b25GdW5jdGlvbiB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHsgTG9nR3JvdXAsIFJldGVudGlvbkRheXMgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG5pbXBvcnQgeyBTZWNyZXQsIFNlY3JldFByb3BzIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXNlY3JldHNtYW5hZ2VyJztcbmltcG9ydCB7IEF3c0N1c3RvbVJlc291cmNlLCBBd3NDdXN0b21SZXNvdXJjZVBvbGljeSwgUGh5c2ljYWxSZXNvdXJjZUlkIH0gZnJvbSAnYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcblxuLyoqXG4gKiBFbmNyeXB0ZWRTZWNyZXRQcm9wcyBkZWZpbmVzIHRoZSBwcm9wZXJ0aWVzIGZvciB0aGUgRW5jcnlwdGVkU2VjcmV0IGNvbnN0cnVjdC5cbiAqXG4gKiBAaW50ZXJmYWNlIEVuY3J5cHRlZFNlY3JldFByb3BzXG4gKiBAcHJvcGVydHkge1NlY3JldFByb3BzfSBbc2VjcmV0UHJvcHNdIC0gVGhlIFNlY3JldFByb3BzIGZvciB0aGUgU2VjcmV0IHRvIGJlIGNyZWF0ZWQgYW5kIHNldCB0aGUgZGVjcnlwdGVkIHZhbHVlIGluLlxuICogQHByb3BlcnR5IHtTZWNyZXR9IFtleGlzdGluZ1NlY3JldE9ial0gLSBUaGUgZXhpc3RpbmcgU2VjcmV0IHRvIGJlIHVzZWQgdG8gc2V0IHRoZSBkZWNyeXB0ZWQgdmFsdWUgaW4uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gY2lwaGVydGV4dEJsb2IgLSBUaGUgY2lwaGVydGV4dCB0byBiZSBkZWNyeXB0ZWQgYW5kIHN0b3JlZCBpbiB0aGUgU2VjcmV0LlxuICogQHByb3BlcnR5IHtzdHJpbmd9IGtleUlkIC0gVGhlIEtNUyBLZXkgQVJOIHRvIGJlIHVzZWQgdG8gZGVjcnlwdCB0aGUgY2lwaGVydGV4dC5cbiAqIEBwcm9wZXJ0eSB7UmV0ZW50aW9uRGF5c30gW2xvZ1JldGVudGlvbkRheXNdIC0gVGhlIHJldGVudGlvbiBkYXlzIGZvciB0aGUgbG9nIGdyb3VwIChvcHRpb25hbCwgZGVmYXVsdCBpcyBPTkVfV0VFSykuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRW5jcnlwdGVkU2VjcmV0UHJvcHMge1xuICByZWFkb25seSBzZWNyZXRQcm9wcz86IFNlY3JldFByb3BzO1xuICByZWFkb25seSBleGlzdGluZ1NlY3JldE9iaj86IFNlY3JldDtcbiAgcmVhZG9ubHkgY2lwaGVydGV4dEJsb2I6IHN0cmluZztcbiAgcmVhZG9ubHkga2V5SWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgbG9nUmV0ZW50aW9uRGF5cz86IFJldGVudGlvbkRheXM7XG59XG5cbi8qKlxuICogRW5jcnlwdGVkU2VjcmV0IGlzIGEgY3VzdG9tIGNvbnN0cnVjdCB0aGF0IGNyZWF0ZXMgYSBTZWNyZXQgaW4gU2VjcmV0cyBNYW5hZ2VyIGFuZCBkZWNyeXB0cyB0aGUgY2lwaGVydGV4dFxuICogdXNpbmcgdGhlIEtNUyBLZXkgQVJOIHByb3ZpZGVkIGFuZCBzdG9yZXMgdGhlIGRlY3J5cHRlZCB2YWx1ZSBpbiB0aGUgU2VjcmV0LlxuICpcbiAqIEBjbGFzcyBFbmNyeXB0ZWRTZWNyZXRcbiAqIEBleHRlbmRzIHtDb25zdHJ1Y3R9XG4gKiBAcGFyYW0ge0NvbnN0cnVjdH0gc2NvcGUgLSBUaGUgc2NvcGUgb2YgdGhlIGNvbnN0cnVjdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBpZCBvZiB0aGUgY29uc3RydWN0LlxuICogQHBhcmFtIHtFbmNyeXB0ZWRTZWNyZXRQcm9wc30gcHJvcHMgLSBUaGUgRW5jcnlwdGVkU2VjcmV0UHJvcHMgZm9yIHRoZSBFbmNyeXB0ZWRTZWNyZXQgY29uc3RydWN0LlxuICovXG5leHBvcnQgY2xhc3MgRW5jcnlwdGVkU2VjcmV0IGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcHVibGljIHNlY3JldDogU2VjcmV0O1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRW5jcnlwdGVkU2VjcmV0UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgLy8gRW5zdXJlIGtleUlkIGlzIHZhbGlkXG4gICAgaWYgKCF2YWxpZGF0ZShwcm9wcy5rZXlJZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBrZXlJZC4nKTtcbiAgICB9XG4gICAgLy8gUGFyc2Uga2V5SWQgYXMgQVJOXG4gICAgY29uc3Qga21zS2V5OiBBUk4gPSBwYXJzZShwcm9wcy5rZXlJZCk7XG5cbiAgICAvLyBFbnN1cmUgY2lwaGVydGV4dEJsb2IgaXMgbm9uLWVtcHR5XG4gICAgaWYgKCFwcm9wcy5jaXBoZXJ0ZXh0QmxvYi5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2lwaGVydGV4dEJsb2IgY2Fubm90IGJlIGVtcHR5Jyk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmV4aXN0aW5nU2VjcmV0T2JqKSB7XG4gICAgICAvLyBJZiBleGlzdGluZ1NlY3JldE9iaiBpcyBwcm92aWRlZCwgdXNlIGl0XG4gICAgICB0aGlzLnNlY3JldCA9IHByb3BzLmV4aXN0aW5nU2VjcmV0T2JqO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBjcmVhdGUgYSBzZWNyZXQgd2l0aCB0aGUgc2VjcmV0UHJvcHMgcHJvdmlkZWRcbiAgICAgIHRoaXMuc2VjcmV0ID0gbmV3IFNlY3JldCh0aGlzLCAnU2VjcmV0cycsIHByb3BzLnNlY3JldFByb3BzKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgdGhlIExhbWJkYSBGdW5jdGlvbiB0byBkZWNyeXB0IHRoZSBjaXBoZXJ0ZXh0IGFuZCBzdG9yZSB0aGUgdmFsdWUgaW4gdGhlIFNlY3JldFxuICAgIGNvbnN0IGRlY3J5cHRTZWNyZXRGdW5jdGlvbiA9IG5ldyBTaW5nbGV0b25GdW5jdGlvbih0aGlzLCAnRGVjcnlwdFNlY3JldEZ1bmN0aW9uJywge1xuICAgICAgbGFtYmRhUHVycG9zZTogJ0RlY3J5cHRTZWNyZXQnLFxuICAgICAgdXVpZDogY3J5cHRvLmNyZWF0ZUhhc2goJ21kNScpLnVwZGF0ZShTdGFjay5vZih0aGlzKS5lbnZpcm9ubWVudCkuZGlnZXN0KCdoZXgnKSxcbiAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICBhcmNoaXRlY3R1cmU6IEFyY2hpdGVjdHVyZS5BUk1fNjQsXG4gICAgICBjb2RlOiBDb2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnbGFtYmRhJykpLFxuICAgICAgaGFuZGxlcjogJ2luZGV4LmhhbmRsZXInLFxuICAgICAgbWVtb3J5U2l6ZTogMTI4LFxuICAgICAgZW52aXJvbm1lbnQ6IHtcbiAgICAgICAgS01TX0tFWV9SRUdJT046IGttc0tleS5yZWdpb24sXG4gICAgICB9LFxuICAgICAgbG9nR3JvdXA6IG5ldyBMb2dHcm91cCh0aGlzLCAnRGVjcnlwdFNlY3JldEZ1bmN0aW9uTG9nR3JvdXAnLCB7XG4gICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgICAgcmV0ZW50aW9uOiBwcm9wcy5sb2dSZXRlbnRpb25EYXlzID8/IFJldGVudGlvbkRheXMuT05FX1dFRUssXG4gICAgICB9KSxcbiAgICB9KTtcblxuICAgIC8vIEFkZCB0byB0aGUgUG9saWN5IFN0YXRlbWVudCB0aGUgYWJpbGl0eSB0byBkZWNyeXB0IHRoZSBjaXBoZXJUZXh0IHdpdGggS01TIGFnYWluc3QgdGhlIGttc0tleUFybiBpbiB0aGUgcHJvcHNcbiAgICBkZWNyeXB0U2VjcmV0RnVuY3Rpb24uYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGFjdGlvbnM6IFsna21zOkRlY3J5cHQnXSxcbiAgICAgICAgcmVzb3VyY2VzOiBbcHJvcHMua2V5SWRdLFxuICAgICAgfSksXG4gICAgKTtcblxuICAgIC8vIEFkZCB0byB0aGUgUG9saWN5IFN0YXRlbWVudCB0aGUgYWJpbGl0eSB0byBwdXQgdGhlIHNlY3JldCB2YWx1ZSBpbnRvIFNlY3JldHMgTWFuYWdlclxuICAgIGRlY3J5cHRTZWNyZXRGdW5jdGlvbi5hZGRUb1JvbGVQb2xpY3koXG4gICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgYWN0aW9uczogWydzZWNyZXRzbWFuYWdlcjpQdXRTZWNyZXRWYWx1ZSddLFxuICAgICAgICByZXNvdXJjZXM6IFt0aGlzLnNlY3JldC5zZWNyZXRBcm5dLFxuICAgICAgfSksXG4gICAgKTtcblxuICAgIGlmICh0aGlzLnNlY3JldC5lbmNyeXB0aW9uS2V5KSB7XG4gICAgICAvLyBBZGQgdG8gdGhlIExhbWJkYSBGdW5jdGlvbiBQb2xpY3kgU3RhdGVtZW50IHRoZSBhYmlsaXR5IHRvIGVuY3J5cHQgdXNpbmcgdGhlIGVuY3J5cHRpb24ga2V5IG9mIHRoZSBzZWNyZXRcbiAgICAgIGRlY3J5cHRTZWNyZXRGdW5jdGlvbi5hZGRUb1JvbGVQb2xpY3koXG4gICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFsna21zOkVuY3J5cHQnXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFt0aGlzLnNlY3JldC5lbmNyeXB0aW9uS2V5LmtleUFybl0sXG4gICAgICAgIH0pLFxuICAgICAgKTtcblxuICAgICAgLy8gTW9kaWZ5IEtleSBQb2xpY3kgdG8gYWxsb3cgdGhlIExhbWJkYSB0byB1c2UgdGhlIEtNUyBLZXkgdG8gZW5jcnlwdCB0aGUgU2VjcmV0XG4gICAgICB0aGlzLnNlY3JldC5lbmNyeXB0aW9uS2V5LmdyYW50RW5jcnlwdChkZWNyeXB0U2VjcmV0RnVuY3Rpb24pO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSB0aGUgY3VzdG9tIHJlc291cmNlXG4gICAgY29uc3QgbGFtYmRhSW52b2tlQXdzQ3VzdG9tUmVzb3VyY2UgPSBuZXcgQXdzQ3VzdG9tUmVzb3VyY2UodGhpcywgJ0N1c3RvbVJlc291cmNlU2VjcmV0TGFtYmRhSW52b2tlJywge1xuICAgICAgb25DcmVhdGU6IHtcbiAgICAgICAgc2VydmljZTogJ0xhbWJkYScsXG4gICAgICAgIGFjdGlvbjogJ2ludm9rZScsXG4gICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICBGdW5jdGlvbk5hbWU6IGRlY3J5cHRTZWNyZXRGdW5jdGlvbi5mdW5jdGlvbk5hbWUsXG4gICAgICAgICAgUGF5bG9hZDpcbiAgICAgICAgICAgICd7XCJzZWNyZXRBcm5cIjogXCInICtcbiAgICAgICAgICAgIHRoaXMuc2VjcmV0LnNlY3JldEFybiArXG4gICAgICAgICAgICAnXCIsXCJrZXlJZFwiOiBcIicgK1xuICAgICAgICAgICAgcHJvcHMua2V5SWQgK1xuICAgICAgICAgICAgJ1wiLCBcImNpcGhlclRleHRcIjogXCInICtcbiAgICAgICAgICAgIHByb3BzLmNpcGhlcnRleHRCbG9iICtcbiAgICAgICAgICAgICdcIn0nLFxuICAgICAgICB9LFxuICAgICAgICBwaHlzaWNhbFJlc291cmNlSWQ6IFBoeXNpY2FsUmVzb3VyY2VJZC5vZignQ3VzdG9tUmVzb3VyY2VTZWNyZXRMYW1iZGFJbnZva2UnKSxcbiAgICAgIH0sXG4gICAgICBvblVwZGF0ZToge1xuICAgICAgICBzZXJ2aWNlOiAnTGFtYmRhJyxcbiAgICAgICAgYWN0aW9uOiAnaW52b2tlJyxcbiAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgIEZ1bmN0aW9uTmFtZTogZGVjcnlwdFNlY3JldEZ1bmN0aW9uLmZ1bmN0aW9uTmFtZSxcbiAgICAgICAgICBQYXlsb2FkOlxuICAgICAgICAgICAgJ3tcInNlY3JldEFyblwiOiBcIicgK1xuICAgICAgICAgICAgdGhpcy5zZWNyZXQuc2VjcmV0QXJuICtcbiAgICAgICAgICAgICdcIixcImtleUlkXCI6IFwiJyArXG4gICAgICAgICAgICBwcm9wcy5rZXlJZCArXG4gICAgICAgICAgICAnXCIsIFwiY2lwaGVyVGV4dFwiOiBcIicgK1xuICAgICAgICAgICAgcHJvcHMuY2lwaGVydGV4dEJsb2IgK1xuICAgICAgICAgICAgJ1wifScsXG4gICAgICAgIH0sXG4gICAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZDogUGh5c2ljYWxSZXNvdXJjZUlkLm9mKCdDdXN0b21SZXNvdXJjZVNlY3JldExhbWJkYUludm9rZScpLFxuICAgICAgfSxcbiAgICAgIHBvbGljeTogQXdzQ3VzdG9tUmVzb3VyY2VQb2xpY3kuZnJvbVNka0NhbGxzKHtcbiAgICAgICAgcmVzb3VyY2VzOiBbZGVjcnlwdFNlY3JldEZ1bmN0aW9uLmZ1bmN0aW9uQXJuXSxcbiAgICAgIH0pLFxuICAgICAgbG9nR3JvdXA6IG5ldyBMb2dHcm91cCh0aGlzLCAnQ3VzdG9tUmVzb3VyY2VTZWNyZXRMYW1iZGFJbnZva2VMb2dHcm91cCcsIHtcbiAgICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICByZXRlbnRpb246IHByb3BzLmxvZ1JldGVudGlvbkRheXMgPz8gUmV0ZW50aW9uRGF5cy5PTkVfV0VFSyxcbiAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgLy8gR3JhbnQgdGhlIExhbWJkYSBJbnZva2UgcGVybWlzc2lvbnMgdG8gdGhlIGxhbWJkYUludm9rZSBjdXN0b20gcmVzb3VyY2VcbiAgICBkZWNyeXB0U2VjcmV0RnVuY3Rpb24uZ3JhbnRJbnZva2UobGFtYmRhSW52b2tlQXdzQ3VzdG9tUmVzb3VyY2UpO1xuICB9XG59XG4iXX0=