@aws-cdk/aws-kms
Version:
The CDK Construct Library for AWS::KMS
534 lines • 71.6 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Key = exports.KeyUsage = exports.KeySpec = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const iam = require("@aws-cdk/aws-iam");
const cxschema = require("@aws-cdk/cloud-assembly-schema");
const core_1 = require("@aws-cdk/core");
const cxapi = require("@aws-cdk/cx-api");
const constructs_1 = require("constructs");
const alias_1 = require("./alias");
const kms_generated_1 = require("./kms.generated");
const perms = require("./private/perms");
class KeyBase extends core_1.Resource {
constructor() {
super(...arguments);
/**
* Collection of aliases added to the key
*
* Tracked to determine whether or not the aliasName should be added to the end of its ID
*/
this.aliases = [];
}
/**
* Defines a new alias for the key.
*/
addAlias(aliasName) {
const aliasId = this.aliases.length > 0 ? `Alias${aliasName}` : 'Alias';
const alias = new alias_1.Alias(this, aliasId, { aliasName, targetKey: this });
this.aliases.push(alias);
return alias;
}
/**
* Adds a statement to the KMS key resource policy.
* @param statement The policy statement to add
* @param allowNoOp If this is set to `false` and there is no policy
* defined (i.e. external key), the operation will fail. Otherwise, it will
* no-op.
*/
addToResourcePolicy(statement, allowNoOp = true) {
const stack = core_1.Stack.of(this);
if (!this.policy) {
if (allowNoOp) {
return { statementAdded: false };
}
throw new Error(`Unable to add statement to IAM resource policy for KMS key: ${JSON.stringify(stack.resolve(this.keyArn))}`);
}
this.policy.addStatements(statement);
return { statementAdded: true, policyDependable: this.policy };
}
validate() {
const errors = super.validate();
errors.push(...this.policy?.validateForResourcePolicy() || []);
return errors;
}
/**
* Grant the indicated permissions on this key to the given principal
*
* This modifies both the principal's policy as well as the resource policy,
* since the default CloudFormation setup for KMS keys is that the policy
* must not be empty and so default grants won't work.
*/
grant(grantee, ...actions) {
// KMS verifies whether the principals included in its key policy actually exist.
// This is a problem if the stack the grantee is part of depends on the key stack
// (as it won't exist before the key policy is attempted to be created).
// In that case, make the account the resource policy principal
const granteeStackDependsOnKeyStack = this.granteeStackDependsOnKeyStack(grantee);
const principal = granteeStackDependsOnKeyStack
? new iam.AccountPrincipal(granteeStackDependsOnKeyStack)
: grantee.grantPrincipal;
const crossAccountAccess = this.isGranteeFromAnotherAccount(grantee);
const crossRegionAccess = this.isGranteeFromAnotherRegion(grantee);
const crossEnvironment = crossAccountAccess || crossRegionAccess;
const grantOptions = {
grantee,
actions,
resource: this,
resourceArns: [this.keyArn],
resourceSelfArns: crossEnvironment ? undefined : ['*'],
};
if (this.trustAccountIdentities && !crossEnvironment) {
return iam.Grant.addToPrincipalOrResource(grantOptions);
}
else {
return iam.Grant.addToPrincipalAndResource({
...grantOptions,
// if the key is used in a cross-environment matter,
// we can't access the Key ARN (they don't have physical names),
// so fall back to using '*'. ToDo we need to make this better... somehow
resourceArns: crossEnvironment ? ['*'] : [this.keyArn],
resourcePolicyPrincipal: principal,
});
}
}
/**
* Grant decryption permissions using this key to the given principal
*/
grantDecrypt(grantee) {
return this.grant(grantee, ...perms.DECRYPT_ACTIONS);
}
/**
* Grant encryption permissions using this key to the given principal
*/
grantEncrypt(grantee) {
return this.grant(grantee, ...perms.ENCRYPT_ACTIONS);
}
/**
* Grant encryption and decryption permissions using this key to the given principal
*/
grantEncryptDecrypt(grantee) {
return this.grant(grantee, ...[...perms.DECRYPT_ACTIONS, ...perms.ENCRYPT_ACTIONS]);
}
/**
* Checks whether the grantee belongs to a stack that will be deployed
* after the stack containing this key.
*
* @param grantee the grantee to give permissions to
* @returns the account ID of the grantee stack if its stack does depend on this stack,
* undefined otherwise
*/
granteeStackDependsOnKeyStack(grantee) {
const grantPrincipal = grantee.grantPrincipal;
if (!isConstruct(grantPrincipal)) {
return undefined;
}
// this logic should only apply to newly created
// (= not imported) resources
if (!this.principalIsANewlyCreatedResource(grantPrincipal)) {
return undefined;
}
// return undefined;
const keyStack = core_1.Stack.of(this);
const granteeStack = core_1.Stack.of(grantPrincipal);
if (keyStack === granteeStack) {
return undefined;
}
return granteeStack.dependencies.includes(keyStack)
? granteeStack.account
: undefined;
}
principalIsANewlyCreatedResource(principal) {
// yes, this sucks
// this is just a temporary stopgap to stem the bleeding while we work on a proper fix
return principal instanceof iam.Role ||
principal instanceof iam.User ||
principal instanceof iam.Group;
}
isGranteeFromAnotherRegion(grantee) {
if (!isConstruct(grantee)) {
return false;
}
const bucketStack = core_1.Stack.of(this);
const identityStack = core_1.Stack.of(grantee);
return bucketStack.region !== identityStack.region;
}
isGranteeFromAnotherAccount(grantee) {
if (!isConstruct(grantee)) {
return false;
}
const bucketStack = core_1.Stack.of(this);
const identityStack = core_1.Stack.of(grantee);
return bucketStack.account !== identityStack.account;
}
}
/**
* The key spec, represents the cryptographic configuration of keys.
*/
var KeySpec;
(function (KeySpec) {
/**
* The default key spec.
*
* Valid usage: ENCRYPT_DECRYPT
*/
KeySpec["SYMMETRIC_DEFAULT"] = "SYMMETRIC_DEFAULT";
/**
* RSA with 2048 bits of key.
*
* Valid usage: ENCRYPT_DECRYPT and SIGN_VERIFY
*/
KeySpec["RSA_2048"] = "RSA_2048";
/**
* RSA with 3072 bits of key.
*
* Valid usage: ENCRYPT_DECRYPT and SIGN_VERIFY
*/
KeySpec["RSA_3072"] = "RSA_3072";
/**
* RSA with 4096 bits of key.
*
* Valid usage: ENCRYPT_DECRYPT and SIGN_VERIFY
*/
KeySpec["RSA_4096"] = "RSA_4096";
/**
* NIST FIPS 186-4, Section 6.4, ECDSA signature using the curve specified by the key and
* SHA-256 for the message digest.
*
* Valid usage: SIGN_VERIFY
*/
KeySpec["ECC_NIST_P256"] = "ECC_NIST_P256";
/**
* NIST FIPS 186-4, Section 6.4, ECDSA signature using the curve specified by the key and
* SHA-384 for the message digest.
*
* Valid usage: SIGN_VERIFY
*/
KeySpec["ECC_NIST_P384"] = "ECC_NIST_P384";
/**
* NIST FIPS 186-4, Section 6.4, ECDSA signature using the curve specified by the key and
* SHA-512 for the message digest.
*
* Valid usage: SIGN_VERIFY
*/
KeySpec["ECC_NIST_P521"] = "ECC_NIST_P521";
/**
* Standards for Efficient Cryptography 2, Section 2.4.1, ECDSA signature on the Koblitz curve.
*
* Valid usage: SIGN_VERIFY
*/
KeySpec["ECC_SECG_P256K1"] = "ECC_SECG_P256K1";
})(KeySpec = exports.KeySpec || (exports.KeySpec = {}));
/**
* The key usage, represents the cryptographic operations of keys.
*/
var KeyUsage;
(function (KeyUsage) {
/**
* Encryption and decryption.
*/
KeyUsage["ENCRYPT_DECRYPT"] = "ENCRYPT_DECRYPT";
/**
* Signing and verification
*/
KeyUsage["SIGN_VERIFY"] = "SIGN_VERIFY";
})(KeyUsage = exports.KeyUsage || (exports.KeyUsage = {}));
/**
* Defines a KMS key.
*
* @resource AWS::KMS::Key
*/
class Key extends KeyBase {
constructor(scope, id, props = {}) {
super(scope, id);
try {
jsiiDeprecationWarnings._aws_cdk_aws_kms_KeyProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, Key);
}
throw error;
}
const denyLists = {
[KeyUsage.ENCRYPT_DECRYPT]: [
KeySpec.ECC_NIST_P256,
KeySpec.ECC_NIST_P384,
KeySpec.ECC_NIST_P521,
KeySpec.ECC_SECG_P256K1,
],
[KeyUsage.SIGN_VERIFY]: [
KeySpec.SYMMETRIC_DEFAULT,
],
};
const keySpec = props.keySpec ?? KeySpec.SYMMETRIC_DEFAULT;
const keyUsage = props.keyUsage ?? KeyUsage.ENCRYPT_DECRYPT;
if (denyLists[keyUsage].includes(keySpec)) {
throw new Error(`key spec '${keySpec}' is not valid with usage '${keyUsage}'`);
}
if (keySpec !== KeySpec.SYMMETRIC_DEFAULT && props.enableKeyRotation) {
throw new Error('key rotation cannot be enabled on asymmetric keys');
}
const defaultKeyPoliciesFeatureEnabled = core_1.FeatureFlags.of(this).isEnabled(cxapi.KMS_DEFAULT_KEY_POLICIES);
this.policy = props.policy ?? new iam.PolicyDocument();
if (defaultKeyPoliciesFeatureEnabled) {
if (props.trustAccountIdentities === false) {
throw new Error('`trustAccountIdentities` cannot be false if the @aws-cdk/aws-kms:defaultKeyPolicies feature flag is set');
}
this.trustAccountIdentities = true;
// Set the default key policy if one hasn't been provided by the user.
if (!props.policy) {
this.addDefaultAdminPolicy();
}
}
else {
this.trustAccountIdentities = props.trustAccountIdentities ?? false;
if (this.trustAccountIdentities) {
this.addDefaultAdminPolicy();
}
else {
this.addLegacyAdminPolicy();
}
}
let pendingWindowInDays;
if (props.pendingWindow) {
pendingWindowInDays = props.pendingWindow.toDays();
if (pendingWindowInDays < 7 || pendingWindowInDays > 30) {
throw new Error(`'pendingWindow' value must between 7 and 30 days. Received: ${pendingWindowInDays}`);
}
}
const resource = new kms_generated_1.CfnKey(this, 'Resource', {
description: props.description,
enableKeyRotation: props.enableKeyRotation,
enabled: props.enabled,
keySpec: props.keySpec,
keyUsage: props.keyUsage,
keyPolicy: this.policy,
pendingWindowInDays: pendingWindowInDays,
});
this.keyArn = resource.attrArn;
this.keyId = resource.ref;
resource.applyRemovalPolicy(props.removalPolicy);
(props.admins ?? []).forEach((p) => this.grantAdmin(p));
if (props.alias !== undefined) {
this.addAlias(props.alias);
}
}
/**
* Import an externally defined KMS Key using its ARN.
*
* @param scope the construct that will "own" the imported key.
* @param id the id of the imported key in the construct tree.
* @param keyArn the ARN of an existing KMS key.
*/
static fromKeyArn(scope, id, keyArn) {
class Import extends KeyBase {
constructor(keyId) {
super(scope, id);
this.keyArn = keyArn;
this.policy = undefined;
// defaulting true: if we are importing the key the key policy is
// undefined and impossible to change here; this means updating identity
// policies is really the only option
this.trustAccountIdentities = true;
this.keyId = keyId;
}
}
const keyResourceName = core_1.Stack.of(scope).splitArn(keyArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
if (!keyResourceName) {
throw new Error(`KMS key ARN must be in the format 'arn:aws:kms:<region>:<account>:key/<keyId>', got: '${keyArn}'`);
}
return new Import(keyResourceName);
}
/**
* Create a mutable {@link IKey} based on a low-level {@link CfnKey}.
* This is most useful when combined with the cloudformation-include module.
* This method is different than {@link fromKeyArn()} because the {@link IKey}
* returned from this method is mutable;
* meaning, calling any mutating methods on it,
* like {@link IKey.addToResourcePolicy()},
* will actually be reflected in the resulting template,
* as opposed to the object returned from {@link fromKeyArn()},
* on which calling those methods would have no effect.
*/
static fromCfnKey(cfnKey) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_kms_CfnKey(cfnKey);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromCfnKey);
}
throw error;
}
// use a "weird" id that has a higher chance of being unique
const id = '@FromCfnKey';
// if fromCfnKey() was already called on this cfnKey,
// return the same L2
// (as different L2s would conflict, because of the mutation of the keyPolicy property of the L1 below)
const existing = cfnKey.node.tryFindChild(id);
if (existing) {
return existing;
}
let keyPolicy;
try {
keyPolicy = iam.PolicyDocument.fromJson(cfnKey.keyPolicy);
}
catch (e) {
// If the KeyPolicy contains any CloudFormation functions,
// PolicyDocument.fromJson() throws an exception.
// In that case, because we would have to effectively make the returned IKey immutable,
// throw an exception suggesting to use the other importing methods instead.
// We might make this parsing logic smarter later,
// but let's start by erroring out.
throw new Error('Could not parse the PolicyDocument of the passed AWS::KMS::Key resource because it contains CloudFormation functions. ' +
'This makes it impossible to create a mutable IKey from that Policy. ' +
'You have to use fromKeyArn instead, passing it the ARN attribute property of the low-level CfnKey');
}
// change the key policy of the L1, so that all changes done in the L2 are reflected in the resulting template
cfnKey.keyPolicy = core_1.Lazy.any({ produce: () => keyPolicy.toJSON() });
return new class extends KeyBase {
constructor() {
super(...arguments);
this.keyArn = cfnKey.attrArn;
this.keyId = cfnKey.ref;
this.policy = keyPolicy;
this.trustAccountIdentities = false;
}
}(cfnKey, id);
}
/**
* Import an existing Key by querying the AWS environment this stack is deployed to.
*
* This function only needs to be used to use Keys not defined in your CDK
* application. If you are looking to share a Key between stacks, you can
* pass the `Key` object between stacks and use it as normal. In addition,
* it's not necessary to use this method if an interface accepts an `IKey`.
* In this case, `Alias.fromAliasName()` can be used which returns an alias
* that extends `IKey`.
*
* Calling this method will lead to a lookup when the CDK CLI is executed.
* You can therefore not use any values that will only be available at
* CloudFormation execution time (i.e., Tokens).
*
* The Key information will be cached in `cdk.context.json` and the same Key
* will be used on future runs. To refresh the lookup, you will have to
* evict the value from the cache using the `cdk context` command. See
* https://docs.aws.amazon.com/cdk/latest/guide/context.html for more information.
*/
static fromLookup(scope, id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_kms_KeyLookupOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromLookup);
}
throw error;
}
class Import extends KeyBase {
constructor(keyId, keyArn) {
super(scope, id);
this.policy = undefined;
// defaulting true: if we are importing the key the key policy is
// undefined and impossible to change here; this means updating identity
// policies is really the only option
this.trustAccountIdentities = true;
this.keyId = keyId;
this.keyArn = keyArn;
}
}
if (core_1.Token.isUnresolved(options.aliasName)) {
throw new Error('All arguments to Key.fromLookup() must be concrete (no Tokens)');
}
const attributes = core_1.ContextProvider.getValue(scope, {
provider: cxschema.ContextProvider.KEY_PROVIDER,
props: {
aliasName: options.aliasName,
},
dummyValue: {
keyId: '1234abcd-12ab-34cd-56ef-1234567890ab',
},
}).value;
return new Import(attributes.keyId, core_1.Arn.format({ resource: 'key', service: 'kms', resourceName: attributes.keyId }, core_1.Stack.of(scope)));
}
/**
* Grant admins permissions using this key to the given principal
*
* Key administrators have permissions to manage the key (e.g., change permissions, revoke), but do not have permissions
* to use the key in cryptographic operations (e.g., encrypt, decrypt).
*/
grantAdmin(grantee) {
return this.grant(grantee, ...perms.ADMIN_ACTIONS);
}
/**
* Adds the default key policy to the key. This policy gives the AWS account (root user) full access to the CMK,
* which reduces the risk of the CMK becoming unmanageable and enables IAM policies to allow access to the CMK.
* This is the same policy that is default when creating a Key via the KMS API or Console.
* @see https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default
*/
addDefaultAdminPolicy() {
this.addToResourcePolicy(new iam.PolicyStatement({
resources: ['*'],
actions: ['kms:*'],
principals: [new iam.AccountRootPrincipal()],
}));
}
/**
* Grants the account admin privileges -- not full account access -- plus the GenerateDataKey action.
* The GenerateDataKey action was added for interop with S3 in https://github.com/aws/aws-cdk/issues/3458.
*
* This policy is discouraged and deprecated by the `@aws-cdk/aws-kms:defaultKeyPolicies` feature flag.
*
* @link https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default
* @deprecated
*/
addLegacyAdminPolicy() {
// This is equivalent to `[...perms.ADMIN_ACTIONS, 'kms:GenerateDataKey']`,
// but keeping this explicit ordering for backwards-compatibility (changing the ordering causes resource updates)
const actions = [
'kms:Create*',
'kms:Describe*',
'kms:Enable*',
'kms:List*',
'kms:Put*',
'kms:Update*',
'kms:Revoke*',
'kms:Disable*',
'kms:Get*',
'kms:Delete*',
'kms:ScheduleKeyDeletion',
'kms:CancelKeyDeletion',
'kms:GenerateDataKey',
'kms:TagResource',
'kms:UntagResource',
];
this.addToResourcePolicy(new iam.PolicyStatement({
resources: ['*'],
actions,
principals: [new iam.AccountRootPrincipal()],
}));
}
}
exports.Key = Key;
_a = JSII_RTTI_SYMBOL_1;
Key[_a] = { fqn: "@aws-cdk/aws-kms.Key", version: "1.197.0" };
/**
* Whether the given object is a Construct
*
* Normally we'd do `x instanceof Construct`, but that is not robust against
* multiple copies of the `constructs` library on disk. This can happen
* when upgrading and downgrading between v2 and v1, and in the use of CDK
* Pipelines is going to an error that says "Can't use Pipeline/Pipeline/Role in
* a cross-environment fashion", which is very confusing.
*/
function isConstruct(x) {
const sym = Symbol.for('constructs.Construct.node');
return (typeof x === 'object' && x &&
(x instanceof constructs_1.Construct // happy fast case
|| !!x.node // constructs v10
|| !!x[sym])); // constructs v3
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsia2V5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHdDQUF3QztBQUN4QywyREFBMkQ7QUFDM0Qsd0NBQWdKO0FBQ2hKLHlDQUF5QztBQUN6QywyQ0FBbUQ7QUFDbkQsbUNBQWdDO0FBRWhDLG1EQUF5QztBQUN6Qyx5Q0FBeUM7QUF3RHpDLE1BQWUsT0FBUSxTQUFRLGVBQVE7SUFBdkM7O1FBeUJFOzs7O1dBSUc7UUFDYyxZQUFPLEdBQVksRUFBRSxDQUFDO0lBMkp6QyxDQUFDO0lBekpDOztPQUVHO0lBQ0ksUUFBUSxDQUFDLFNBQWlCO1FBQy9CLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBRXhFLE1BQU0sS0FBSyxHQUFHLElBQUksYUFBSyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDdkUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFekIsT0FBTyxLQUFLLENBQUM7S0FDZDtJQUVEOzs7Ozs7T0FNRztJQUNJLG1CQUFtQixDQUFDLFNBQThCLEVBQUUsU0FBUyxHQUFHLElBQUk7UUFDekUsTUFBTSxLQUFLLEdBQUcsWUFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUU3QixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNoQixJQUFJLFNBQVMsRUFBRTtnQkFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLEtBQUssRUFBRSxDQUFDO2FBQUU7WUFDcEQsTUFBTSxJQUFJLEtBQUssQ0FBQywrREFBK0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUks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QVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0I7QUFDNUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGN4c2NoZW1hIGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgeyBGZWF0dXJlRmxhZ3MsIElSZXNvdXJjZSwgTGF6eSwgUmVtb3ZhbFBvbGljeSwgUmVzb3VyY2UsIFN0YWNrLCBEdXJhdGlvbiwgVG9rZW4sIENvbnRleHRQcm92aWRlciwgQXJuLCBBcm5Gb3JtYXQgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgeyBJQ29uc3RydWN0LCBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEFsaWFzIH0gZnJvbSAnLi9hbGlhcyc7XG5pbXBvcnQgeyBLZXlMb29rdXBPcHRpb25zIH0gZnJvbSAnLi9rZXktbG9va3VwJztcbmltcG9ydCB7IENmbktleSB9IGZyb20gJy4va21zLmdlbmVyYXRlZCc7XG5pbXBvcnQgKiBhcyBwZXJtcyBmcm9tICcuL3ByaXZhdGUvcGVybXMnO1xuXG4vKipcbiAqIEEgS01TIEtleSwgZWl0aGVyIG1hbmFnZWQgYnkgdGhpcyBDREsgYXBwLCBvciBpbXBvcnRlZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJS2V5IGV4dGVuZHMgSVJlc291cmNlIHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGtleS5cbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkga2V5QXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBJRCBvZiB0aGUga2V5XG4gICAqICh0aGUgcGFydCB0aGF0IGxvb2tzIHNvbWV0aGluZyBsaWtlOiAxMjM0YWJjZC0xMmFiLTM0Y2QtNTZlZi0xMjM0NTY3ODkwYWIpLlxuICAgKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSBrZXlJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGEgbmV3IGFsaWFzIGZvciB0aGUga2V5LlxuICAgKi9cbiAgYWRkQWxpYXMoYWxpYXM6IHN0cmluZyk6IEFsaWFzO1xuXG4gIC8qKlxuICAgKiBBZGRzIGEgc3RhdGVtZW50IHRvIHRoZSBLTVMga2V5IHJlc291cmNlIHBvbGljeS5cbiAgICogQHBhcmFtIHN0YXRlbWVudCBUaGUgcG9saWN5IHN0YXRlbWVudCB0byBhZGRcbiAgICogQHBhcmFtIGFsbG93Tm9PcCBJZiB0aGlzIGlzIHNldCB0byBgZmFsc2VgIGFuZCB0aGVyZSBpcyBubyBwb2xpY3lcbiAgICogZGVmaW5lZCAoaS5lLiBleHRlcm5hbCBrZXkpLCB0aGUgb3BlcmF0aW9uIHdpbGwgZmFpbC4gT3RoZXJ3aXNlLCBpdCB3aWxsXG4gICAqIG5vLW9wLlxuICAgKi9cbiAgYWRkVG9SZXNvdXJjZVBvbGljeShzdGF0ZW1lbnQ6IGlhbS5Qb2xpY3lTdGF0ZW1lbnQsIGFsbG93Tm9PcD86IGJvb2xlYW4pOiBpYW0uQWRkVG9SZXNvdXJjZVBvbGljeVJlc3VsdDtcblxuICAvKipcbiAgICogR3JhbnQgdGhlIGluZGljYXRlZCBwZXJtaXNzaW9ucyBvbiB0aGlzIGtleSB0byB0aGUgZ2l2ZW4gcHJpbmNpcGFsXG4gICAqL1xuICBncmFudChncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgLi4uYWN0aW9uczogc3RyaW5nW10pOiBpYW0uR3JhbnQ7XG5cbiAgLyoqXG4gICAqIEdyYW50IGRlY3J5cHRpb24gcGVybWlzc2lvbnMgdXNpbmcgdGhpcyBrZXkgdG8gdGhlIGdpdmVuIHByaW5jaXBhbFxuICAgKi9cbiAgZ3JhbnREZWNyeXB0KGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBHcmFudCBlbmNyeXB0aW9uIHBlcm1pc3Npb25zIHVzaW5nIHRoaXMga2V5IHRvIHRoZSBnaXZlbiBwcmluY2lwYWxcbiAgICovXG4gIGdyYW50RW5jcnlwdChncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudDtcblxuICAvKipcbiAgICogR3JhbnQgZW5jcnlwdGlvbiBhbmQgZGVjcnlwdGlvbiBwZXJtaXNzaW9ucyB1c2luZyB0aGlzIGtleSB0byB0aGUgZ2l2ZW4gcHJpbmNpcGFsXG4gICAqL1xuICBncmFudEVuY3J5cHREZWNyeXB0KGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xufVxuXG5hYnN0cmFjdCBjbGFzcyBLZXlCYXNlIGV4dGVuZHMgUmVzb3VyY2UgaW1wbGVtZW50cyBJS2V5IHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGtleS5cbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBrZXlBcm46IHN0cmluZztcblxuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkga2V5SWQ6IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9uYWwgcG9saWN5IGRvY3VtZW50IHRoYXQgcmVwcmVzZW50cyB0aGUgcmVzb3VyY2UgcG9saWN5IG9mIHRoaXMga2V5LlxuICAgKlxuICAgKiBJZiBzcGVjaWZpZWQsIGFkZFRvUmVzb3VyY2VQb2xpY3kgY2FuIGJlIHVzZWQgdG8gZWRpdCB0aGlzIHBvbGljeS5cbiAgICogT3RoZXJ3aXNlIHRoaXMgbWV0aG9kIHdpbGwgbm8tb3AuXG4gICAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgcmVhZG9ubHkgcG9saWN5PzogaWFtLlBvbGljeURvY3VtZW50O1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBwcm9wZXJ0eSB0byBjb250cm9sIHRydXN0aW5nIGFjY291bnQgaWRlbnRpdGllcy5cbiAgICpcbiAgICogSWYgc3BlY2lmaWVkLCBncmFudHMgd2lsbCBkZWZhdWx0IGlkZW50aXR5IHBvbGljaWVzIGluc3RlYWQgb2YgdG8gYm90aFxuICAgKiByZXNvdXJjZSBhbmQgaWRlbnRpdHkgcG9saWNpZXMuIFRoaXMgbWF0Y2hlcyB0aGUgZGVmYXVsdCBiZWhhdmlvciB3aGVuIGNyZWF0aW5nXG4gICAqIEtNUyBrZXlzIHZpYSB0aGUgQVBJIG9yIGNvbnNvbGUuXG4gICAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgcmVhZG9ubHkgdHJ1c3RBY2NvdW50SWRlbnRpdGllczogYm9vbGVhbjtcblxuICAvKipcbiAgICogQ29sbGVjdGlvbiBvZiBhbGlhc2VzIGFkZGVkIHRvIHRoZSBrZXlcbiAgICpcbiAgICogVHJhY2tlZCB0byBkZXRlcm1pbmUgd2hldGhlciBvciBub3QgdGhlIGFsaWFzTmFtZSBzaG91bGQgYmUgYWRkZWQgdG8gdGhlIGVuZCBvZiBpdHMgSURcbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgYWxpYXNlczogQWxpYXNbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGEgbmV3IGFsaWFzIGZvciB0aGUga2V5LlxuICAgKi9cbiAgcHVibGljIGFkZEFsaWFzKGFsaWFzTmFtZTogc3RyaW5nKTogQWxpYXMge1xuICAgIGNvbnN0IGFsaWFzSWQgPSB0aGlzLmFsaWFzZXMubGVuZ3RoID4gMCA/IGBBbGlhcyR7YWxpYXNOYW1lfWAgOiAnQWxpYXMnO1xuXG4gICAgY29uc3QgYWxpYXMgPSBuZXcgQWxpYXModGhpcywgYWxpYXNJZCwgeyBhbGlhc05hbWUsIHRhcmdldEtleTogdGhpcyB9KTtcbiAgICB0aGlzLmFsaWFzZXMucHVzaChhbGlhcyk7XG5cbiAgICByZXR1cm4gYWxpYXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHN0YXRlbWVudCB0byB0aGUgS01TIGtleSByZXNvdXJjZSBwb2xpY3kuXG4gICAqIEBwYXJhbSBzdGF0ZW1lbnQgVGhlIHBvbGljeSBzdGF0ZW1lbnQgdG8gYWRkXG4gICAqIEBwYXJhbSBhbGxvd05vT3AgSWYgdGhpcyBpcyBzZXQgdG8gYGZhbHNlYCBhbmQgdGhlcmUgaXMgbm8gcG9saWN5XG4gICAqIGRlZmluZWQgKGkuZS4gZXh0ZXJuYWwga2V5KSwgdGhlIG9wZXJhdGlvbiB3aWxsIGZhaWwuIE90aGVyd2lzZSwgaXQgd2lsbFxuICAgKiBuby1vcC5cbiAgICovXG4gIHB1YmxpYyBhZGRUb1Jlc291cmNlUG9saWN5KHN0YXRlbWVudDogaWFtLlBvbGljeVN0YXRlbWVudCwgYWxsb3dOb09wID0gdHJ1ZSk6IGlhbS5BZGRUb1Jlc291cmNlUG9saWN5UmVzdWx0IHtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgaWYgKCF0aGlzLnBvbGljeSkge1xuICAgICAgaWYgKGFsbG93Tm9PcCkgeyByZXR1cm4geyBzdGF0ZW1lbnRBZGRlZDogZmFsc2UgfTsgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gYWRkIHN0YXRlbWVudCB0byBJQU0gcmVzb3VyY2UgcG9saWN5IGZvciBLTVMga2V5OiAke0pTT04uc3RyaW5naWZ5KHN0YWNrLnJlc29sdmUodGhpcy5rZXlBcm4pKX1gKTtcbiAgICB9XG5cbiAgICB0aGlzLnBvbGljeS5hZGRTdGF0ZW1lbnRzKHN0YXRlbWVudCk7XG4gICAgcmV0dXJuIHsgc3RhdGVtZW50QWRkZWQ6IHRydWUsIHBvbGljeURlcGVuZGFibGU6IHRoaXMucG9saWN5IH07XG4gIH1cblxuICBwcm90ZWN0ZWQgdmFsaWRhdGUoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGVycm9ycyA9IHN1cGVyLnZhbGlkYXRlKCk7XG4gICAgZXJyb3JzLnB1c2goLi4udGhpcy5wb2xpY3k/LnZhbGlkYXRlRm9yUmVzb3VyY2VQb2xpY3koKSB8fCBbXSk7XG4gICAgcmV0dXJuIGVycm9ycztcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudCB0aGUgaW5kaWNhdGVkIHBlcm1pc3Npb25zIG9uIHRoaXMga2V5IHRvIHRoZSBnaXZlbiBwcmluY2lwYWxcbiAgICpcbiAgICogVGhpcyBtb2RpZmllcyBib3RoIHRoZSBwcmluY2lwYWwncyBwb2xpY3kgYXMgd2VsbCBhcyB0aGUgcmVzb3VyY2UgcG9saWN5LFxuICAgKiBzaW5jZSB0aGUgZGVmYXVsdCBDbG91ZEZvcm1hdGlvbiBzZXR1cCBmb3IgS01TIGtleXMgaXMgdGhhdCB0aGUgcG9saWN5XG4gICAqIG11c3Qgbm90IGJlIGVtcHR5IGFuZCBzbyBkZWZhdWx0IGdyYW50cyB3b24ndCB3b3JrLlxuICAgKi9cbiAgcHVibGljIGdyYW50KGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlLCAuLi5hY3Rpb25zOiBzdHJpbmdbXSk6IGlhbS5HcmFudCB7XG4gICAgLy8gS01TIHZlcmlmaWVzIHdoZXRoZXIgdGhlIHByaW5jaXBhbHMgaW5jbHVkZWQgaW4gaXRzIGtleSBwb2xpY3kgYWN0dWFsbHkgZXhpc3QuXG4gICAgLy8gVGhpcyBpcyBhIHByb2JsZW0gaWYgdGhlIHN0YWNrIHRoZSBncmFudGVlIGlzIHBhcnQgb2YgZGVwZW5kcyBvbiB0aGUga2V5IHN0YWNrXG4gICAgLy8gKGFzIGl0IHdvbid0IGV4aXN0IGJlZm9yZSB0aGUga2V5IHBvbGljeSBpcyBhdHRlbXB0ZWQgdG8gYmUgY3JlYXRlZCkuXG4gICAgLy8gSW4gdGhhdCBjYXNlLCBtYWtlIHRoZSBhY2NvdW50IHRoZSByZXNvdXJjZSBwb2xpY3kgcHJpbmNpcGFsXG4gICAgY29uc3QgZ3JhbnRlZVN0YWNrRGVwZW5kc09uS2V5U3RhY2sgPSB0aGlzLmdyYW50ZWVTdGFja0RlcGVuZHNPbktleVN0YWNrKGdyYW50ZWUpO1xuICAgIGNvbnN0IHByaW5jaXBhbCA9IGdyYW50ZWVTdGFja0RlcGVuZHNPbktleVN0YWNrXG4gICAgICA/IG5ldyBpYW0uQWNjb3VudFByaW5jaXBhbChncmFudGVlU3RhY2tEZXBlbmRzT25LZXlTdGFjaylcbiAgICAgIDogZ3JhbnRlZS5ncmFudFByaW5jaXBhbDtcblxuICAgIGNvbnN0IGNyb3NzQWNjb3VudEFjY2VzcyA9IHRoaXMuaXNHcmFudGVlRnJvbUFub3RoZXJBY2NvdW50KGdyYW50ZWUpO1xuICAgIGNvbnN0IGNyb3NzUmVnaW9uQWNjZXNzID0gdGhpcy5pc0dyYW50ZWVGcm9tQW5vdGhlclJlZ2lvbihncmFudGVlKTtcbiAgICBjb25zdCBjcm9zc0Vudmlyb25tZW50ID0gY3Jvc3NBY2NvdW50QWNjZXNzIHx8IGNyb3NzUmVnaW9uQWNjZXNzO1xuICAgIGNvbnN0IGdyYW50T3B0aW9uczogaWFtLkdyYW50V2l0aFJlc291cmNlT3B0aW9ucyA9IHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zLFxuICAgICAgcmVzb3VyY2U6IHRoaXMsXG4gICAgICByZXNvdXJjZUFybnM6IFt0aGlzLmtleUFybl0sXG4gICAgICByZXNvdXJjZVNlbGZBcm5zOiBjcm9zc0Vudmlyb25tZW50ID8gdW5kZWZpbmVkIDogWycqJ10sXG4gICAgfTtcbiAgICBpZiAodGhpcy50cnVzdEFjY291bnRJZGVudGl0aWVzICYmICFjcm9zc0Vudmlyb25tZW50KSB7XG4gICAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsT3JSZXNvdXJjZShncmFudE9wdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsQW5kUmVzb3VyY2Uoe1xuICAgICAgICAuLi5ncmFudE9wdGlvbnMsXG4gICAgICAgIC8vIGlmIHRoZSBrZXkgaXMgdXNlZCBpbiBhIGNyb3NzLWVudmlyb25tZW50IG1hdHRlcixcbiAgICAgICAgLy8gd2UgY2FuJ3QgYWNjZXNzIHRoZSBLZXkgQVJOICh0aGV5IGRvbid0IGhhdmUgcGh5c2ljYWwgbmFtZXMpLFxuICAgICAgICAvLyBzbyBmYWxsIGJhY2sgdG8gdXNpbmcgJyonLiBUb0RvIHdlIG5lZWQgdG8gbWFrZSB0aGlzIGJldHRlci4uLiBzb21laG93XG4gICAgICAgIHJlc291cmNlQXJuczogY3Jvc3NFbnZpcm9ubWVudCA/IFsnKiddIDogW3RoaXMua2V5QXJuXSxcbiAgICAgICAgcmVzb3VyY2VQb2xpY3lQcmluY2lwYWw6IHByaW5jaXBhbCxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudCBkZWNyeXB0aW9uIHBlcm1pc3Npb25zIHVzaW5nIHRoaXMga2V5IHRvIHRoZSBnaXZlbiBwcmluY2lwYWxcbiAgICovXG4gIHB1YmxpYyBncmFudERlY3J5cHQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIHJldHVybiB0aGlzLmdyYW50KGdyYW50ZWUsIC4uLnBlcm1zLkRFQ1JZUFRfQUNUSU9OUyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnQgZW5jcnlwdGlvbiBwZXJtaXNzaW9ucyB1c2luZyB0aGlzIGtleSB0byB0aGUgZ2l2ZW4gcHJpbmNpcGFsXG4gICAqL1xuICBwdWJsaWMgZ3JhbnRFbmNyeXB0KGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICByZXR1cm4gdGhpcy5ncmFudChncmFudGVlLCAuLi5wZXJtcy5FTkNSWVBUX0FDVElPTlMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50IGVuY3J5cHRpb24gYW5kIGRlY3J5cHRpb24gcGVybWlzc2lvbnMgdXNpbmcgdGhpcyBrZXkgdG8gdGhlIGdpdmVuIHByaW5jaXBhbFxuICAgKi9cbiAgcHVibGljIGdyYW50RW5jcnlwdERlY3J5cHQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIHJldHVybiB0aGlzLmdyYW50KGdyYW50ZWUsIC4uLlsuLi5wZXJtcy5ERUNSWVBUX0FDVElPTlMsIC4uLnBlcm1zLkVOQ1JZUFRfQUNUSU9OU10pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyB3aGV0aGVyIHRoZSBncmFudGVlIGJlbG9uZ3MgdG8gYSBzdGFjayB0aGF0IHdpbGwgYmUgZGVwbG95ZWRcbiAgICogYWZ0ZXIgdGhlIHN0YWNrIGNvbnRhaW5pbmcgdGhpcyBrZXkuXG4gICAqXG4gICAqIEBwYXJhbSBncmFudGVlIHRoZSBncmFudGVlIHRvIGdpdmUgcGVybWlzc2lvbnMgdG9cbiAgICogQHJldHVybnMgdGhlIGFjY291bnQgSUQgb2YgdGhlIGdyYW50ZWUgc3RhY2sgaWYgaXRzIHN0YWNrIGRvZXMgZGVwZW5kIG9uIHRoaXMgc3RhY2ssXG4gICAqICAgdW5kZWZpbmVkIG90aGVyd2lzZVxuICAgKi9cbiAgcHJpdmF0ZSBncmFudGVlU3RhY2tEZXBlbmRzT25LZXlTdGFjayhncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgZ3JhbnRQcmluY2lwYWwgPSBncmFudGVlLmdyYW50UHJpbmNpcGFsO1xuICAgIGlmICghaXNDb25zdHJ1Y3QoZ3JhbnRQcmluY2lwYWwpKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICAvLyB0aGlzIGxvZ2ljIHNob3VsZCBvbmx5IGFwcGx5IHRvIG5ld2x5IGNyZWF0ZWRcbiAgICAvLyAoPSBub3QgaW1wb3J0ZWQpIHJlc291cmNlc1xuICAgIGlmICghdGhpcy5wcmluY2lwYWxJc0FOZXdseUNyZWF0ZWRSZXNvdXJjZShncmFudFByaW5jaXBhbCkpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8vIHJldHVybiB1bmRlZmluZWQ7XG4gICAgY29uc3Qga2V5U3RhY2sgPSBTdGFjay5vZih0aGlzKTtcbiAgICBjb25zdCBncmFudGVlU3RhY2sgPSBTdGFjay5vZihncmFudFByaW5jaXBhbCk7XG4gICAgaWYgKGtleVN0YWNrID09PSBncmFudGVlU3RhY2spIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiBncmFudGVlU3RhY2suZGVwZW5kZW5jaWVzLmluY2x1ZGVzKGtleVN0YWNrKVxuICAgICAgPyBncmFudGVlU3RhY2suYWNjb3VudFxuICAgICAgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIHByaW5jaXBhbElzQU5ld2x5Q3JlYXRlZFJlc291cmNlKHByaW5jaXBhbDogSUNvbnN0cnVjdCk6IGJvb2xlYW4ge1xuICAgIC8vIHllcywgdGhpcyBzdWNrc1xuICAgIC8vIHRoaXMgaXMganVzdCBhIHRlbXBvcmFyeSBzdG9wZ2FwIHRvIHN0ZW0gdGhlIGJsZWVkaW5nIHdoaWxlIHdlIHdvcmsgb24gYSBwcm9wZXIgZml4XG4gICAgcmV0dXJuIHByaW5jaXBhbCBpbnN0YW5jZW9mIGlhbS5Sb2xlIHx8XG4gICAgICBwcmluY2lwYWwgaW5zdGFuY2VvZiBpYW0uVXNlciB8fFxuICAgICAgcHJpbmNpcGFsIGluc3RhbmNlb2YgaWFtLkdyb3VwO1xuICB9XG5cbiAgcHJpdmF0ZSBpc0dyYW50ZWVGcm9tQW5vdGhlclJlZ2lvbihncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGJvb2xlYW4ge1xuICAgIGlmICghaXNDb25zdHJ1Y3QoZ3JhbnRlZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgYnVja2V0U3RhY2sgPSBTdGFjay5vZih0aGlzKTtcbiAgICBjb25zdCBpZGVudGl0eVN0YWNrID0gU3RhY2sub2YoZ3JhbnRlZSk7XG4gICAgcmV0dXJuIGJ1Y2tldFN0YWNrLnJlZ2lvbiAhPT0gaWRlbnRpdHlTdGFjay5yZWdpb247XG4gIH1cblxuICBwcml2YXRlIGlzR3JhbnRlZUZyb21Bbm90aGVyQWNjb3VudChncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGJvb2xlYW4ge1xuICAgIGlmICghaXNDb25zdHJ1Y3QoZ3JhbnRlZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgYnVja2V0U3RhY2sgPSBTdGFjay5vZih0aGlzKTtcbiAgICBjb25zdCBpZGVudGl0eVN0YWNrID0gU3RhY2sub2YoZ3JhbnRlZSk7XG4gICAgcmV0dXJuIGJ1Y2tldFN0YWNrLmFjY291bnQgIT09IGlkZW50aXR5U3RhY2suYWNjb3VudDtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBrZXkgc3BlYywgcmVwcmVzZW50cyB0aGUgY3J5cHRvZ3JhcGhpYyBjb25maWd1cmF0aW9uIG9mIGtleXMuXG4gKi9cbmV4cG9ydCBlbnVtIEtleVNwZWMge1xuICAvKipcbiAgICogVGhlIGRlZmF1bHQga2V5IHNwZWMuXG4gICAqXG4gICAqIFZhbGlkIHVzYWdlOiBFTkNSWVBUX0RFQ1JZUFRcbiAgICovXG4gIFNZTU1FVFJJQ19ERUZBVUxUID0gJ1NZTU1FVFJJQ19ERUZBVUxUJyxcblxuICAvKipcbiAgICogUlNBIHdpdGggMjA0OCBiaXRzIG9mIGtleS5cbiAgICpcbiAgICogVmFsaWQgdXNhZ2U6IEVOQ1JZUFRfREVDUllQVCBhbmQgU0lHTl9WRVJJRllcbiAgICovXG4gIFJTQV8yMDQ4ID0gJ1JTQV8yMDQ4JyxcblxuICAvKipcbiAgICogUlNBIHdpdGggMzA3MiBiaXRzIG9mIGtleS5cbiAgICpcbiAgICogVmFsaWQgdXNhZ2U6IEVOQ1JZUFRfREVDUllQVCBhbmQgU0lHTl9WRVJJRllcbiAgICovXG4gIFJTQV8zMDcyID0gJ1JTQV8zMDcyJyxcblxuICAvKipcbiAgICogUlNBIHdpdGggNDA5NiBiaXRzIG9mIGtleS5cbiAgICpcbiAgICogVmFsaWQgdXNhZ2U6IEVOQ1JZUFRfREVDUllQVCBhbmQgU0lHTl9WRVJJRllcbiAgICovXG4gIFJTQV80MDk2ID0gJ1JTQV80MDk2JyxcblxuICAvKipcbiAgICogTklTVCBGSVBTIDE4Ni00LCBTZWN0aW9uIDYuNCwgRUNEU0Egc2lnbmF0dXJlIHVzaW5nIHRoZSBjdXJ2ZSBzcGVjaWZpZWQgYnkgdGhlIGtleSBhbmRcbiAgICogU0hBLTI1NiBmb3IgdGhlIG1lc3NhZ2UgZGlnZXN0LlxuICAgKlxuICAgKiBWYWxpZCB1c2FnZTogU0lHTl9WRVJJRllcbiAgICovXG4gIEVDQ19OSVNUX1AyNTYgPSAnRUNDX05JU1RfUDI1NicsXG5cbiAgLyoqXG4gICAqIE5JU1QgRklQUyAxODYtNCwgU2VjdGlvbiA2LjQsIEVDRFNBIHNpZ25hdHVyZSB1c2luZyB0aGUgY3VydmUgc3BlY2lmaWVkIGJ5IHRoZSBrZXkgYW5kXG4gICAqIFNIQS0zODQgZm9yIHRoZSBtZXNzYWdlIGRpZ2VzdC5cbiAgICpcbiAgICogVmFsaWQgdXNhZ2U6IFNJR05fVkVSSUZZXG4gICAqL1xuICBFQ0NfTklTVF9QMzg0ID0gJ0VDQ19OSVNUX1AzODQnLFxuXG4gIC8qKlxuICAgKiBOSVNUIEZJUFMgMTg2LTQsIFNlY3Rpb24gNi40LCBFQ0RTQSBzaWduYXR1cmUgdXNpbmcgdGhlIGN1cnZlIHNwZWNpZmllZCBieSB0aGUga2V5IGFuZFxuICAgKiBTSEEtNTEyIGZvciB0aGUgbWVzc2FnZSBkaWdlc3QuXG4gICAqXG4gICAqIFZhbGlkIHVzYWdlOiBTSUdOX1ZFUklGWVxuICAgKi9cbiAgRUNDX05JU1RfUDUyMSA9ICdFQ0NfTklTVF9QNTIxJyxcblxuICAvKipcbiAgICogU3RhbmRhcmRzIGZvciBFZmZpY2llbnQgQ3J5cHRvZ3JhcGh5IDIsIFNlY3Rpb24gMi40LjEsIEVDRFNBIHNpZ25hdHVyZSBvbiB0aGUgS29ibGl0eiBjdXJ2ZS5cbiAgICpcbiAgICogVmFsaWQgdXNhZ2U6IFNJR05fVkVSSUZZXG4gICAqL1xuICBFQ0NfU0VDR19QMjU2SzEgPSAnRUNDX1NFQ0dfUDI1NksxJyxcbn1cblxuLyoqXG4gKiBUaGUga2V5IHVzYWdlLCByZXByZXNlbnRzIHRoZSBjcnlwdG9ncmFwaGljIG9wZXJhdGlvbnMgb2Yga2V5cy5cbiAqL1xuZXhwb3J0IGVudW0gS2V5VXNhZ2Uge1xuICAvKipcbiAgICogRW5jcnlwdGlvbiBhbmQgZGVjcnlwdGlvbi5cbiAgICovXG4gIEVOQ1JZUFRfREVDUllQVCA9ICdFTkNSWVBUX0RFQ1JZUFQnLFxuXG4gIC8qKlxuICAgKiBTaWduaW5nIGFuZCB2ZXJpZmljYXRpb25cbiAgICovXG4gIFNJR05fVkVSSUZZID0gJ1NJR05fVkVSSUZZJyxcbn1cblxuLyoqXG4gKiBDb25zdHJ1Y3Rpb24gcHJvcGVydGllcyBmb3IgYSBLTVMgS2V5IG9iamVjdFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEtleVByb3BzIHtcbiAgLyoqXG4gICAqIEEgZGVzY3JpcHRpb24gb2YgdGhlIGtleS4gVXNlIGEgZGVzY3JpcHRpb24gdGhhdCBoZWxwcyB5b3VyIHVzZXJzIGRlY2lkZVxuICAgKiB3aGV0aGVyIHRoZSBrZXkgaXMgYXBwcm9wcmlhdGUgZm9yIGEgcGFydGljdWxhciB0YXNrLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGRlc2NyaXB0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEluaXRpYWwgYWxpYXMgdG8gYWRkIHRvIHRoZSBrZXlcbiAgICpcbiAgICogTW9yZSBhbGlhc2VzIGNhbiBiZSBhZGRlZCBsYXRlc