UNPKG

@aws-cdk/aws-kms

Version:

The CDK Construct Library for AWS::KMS

534 lines 71.6 kB
"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