UNPKG

@aws-cdk/aws-s3tables-alpha

Version:

CDK Constructs for S3 Tables

450 lines 64.2 kB
"use strict"; var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TableBucket = exports.TableBucketEncryption = exports.UnreferencedFileRemovalStatus = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const os_1 = require("os"); const s3tables = require("aws-cdk-lib/aws-s3tables"); const table_bucket_policy_1 = require("./table-bucket-policy"); const perms = require("./permissions"); const util_1 = require("./util"); const iam = require("aws-cdk-lib/aws-iam"); const kms = require("aws-cdk-lib/aws-kms"); const core_1 = require("aws-cdk-lib/core"); const metadata_resource_1 = require("aws-cdk-lib/core/lib/metadata-resource"); const prop_injectable_1 = require("aws-cdk-lib/core/lib/prop-injectable"); /** * Controls whether unreferenced file removal is enabled or disabled. */ var UnreferencedFileRemovalStatus; (function (UnreferencedFileRemovalStatus) { /** * Enable unreferenced file removal. */ UnreferencedFileRemovalStatus["ENABLED"] = "Enabled"; /** * Disable unreferenced file removal. */ UnreferencedFileRemovalStatus["DISABLED"] = "Disabled"; })(UnreferencedFileRemovalStatus || (exports.UnreferencedFileRemovalStatus = UnreferencedFileRemovalStatus = {})); /** * Controls Server Side Encryption (SSE) for this TableBucket. */ var TableBucketEncryption; (function (TableBucketEncryption) { /** * Use a customer defined KMS key for encryption * If `encryptionKey` is specified, this key will be used, otherwise, one will be defined. */ TableBucketEncryption["KMS"] = "aws:kms"; /** * Use S3 managed encryption keys with AES256 encryption */ TableBucketEncryption["S3_MANAGED"] = "AES256"; })(TableBucketEncryption || (exports.TableBucketEncryption = TableBucketEncryption = {})); class TableBucketBase extends core_1.Resource { /** * Adds a statement to the resource policy for a principal (i.e. * account/role/service) to perform actions on this table bucket and/or its * contents. Use `tableBucketArn` and `arnForObjects(keys)` to obtain ARNs for * this bucket or objects. * * Note that the policy statement may or may not be added to the policy. * For example, when an `ITableBucket` is created from an existing table bucket, * it's not possible to tell whether the bucket already has a policy * attached, let alone to re-use that policy to add more statements to it. * So it's safest to do nothing in these cases. * * @param statement the policy statement to be added to the bucket's * policy. * @returns metadata about the execution of this method. If the policy * was not added, the value of `statementAdded` will be `false`. You * should always check this value to make sure that the operation was * actually carried out. Otherwise, synthesis and deploy will terminate * silently, which may be confusing. */ addToResourcePolicy(statement) { if (!this.tableBucketPolicy && this.autoCreatePolicy) { this.tableBucketPolicy = new table_bucket_policy_1.TableBucketPolicy(this, 'DefaultPolicy', { tableBucket: this, }); } if (this.tableBucketPolicy) { this.tableBucketPolicy.document.addStatements(statement); return { statementAdded: true, policyDependable: this.tableBucketPolicy }; } return { statementAdded: false }; } grantRead(identity, tableId) { return this.grant(identity, perms.TABLE_BUCKET_READ_ACCESS, perms.KEY_READ_ACCESS, this.tableBucketArn, this.getTableArn(tableId)); } grantWrite(identity, tableId) { return this.grant(identity, perms.TABLE_BUCKET_WRITE_ACCESS, perms.KEY_READ_WRITE_ACCESS, this.tableBucketArn, this.getTableArn(tableId)); } grantReadWrite(identity, tableId) { return this.grant(identity, perms.TABLE_BUCKET_READ_WRITE_ACCESS, perms.KEY_WRITE_ACCESS, this.tableBucketArn, this.getTableArn(tableId)); } /** * Grants the given s3tables permissions to the provided principal * @returns Grant object */ grant(grantee, tableBucketActions, keyActions, resourceArn, ...otherResourceArns) { const resources = [resourceArn, ...otherResourceArns].filter(arn => arn != undefined); const grant = iam.Grant.addToPrincipalOrResource({ grantee, actions: tableBucketActions, resourceArns: resources, resource: this, }); if (this.encryptionKey && keyActions && keyActions.length !== 0) { this.encryptionKey.grant(grantee, ...keyActions); } return grant; } getTableArn(tableId) { return tableId ? `${this.tableBucketArn}/table/${tableId}` : undefined; } } /** * An S3 table bucket with helpers for associated resource policies * * This bucket may not yet have all features that exposed by the underlying CfnTableBucket. * * @stateful * @example * const sampleTableBucket = new TableBucket(scope, 'ExampleTableBucket', { * tableBucketName: 'example-bucket', * // Optional fields: * unreferencedFileRemoval: { * noncurrentDays: 123, * status: UnreferencedFileRemovalStatus.ENABLED, * unreferencedDays: 123, * }, * }); */ let TableBucket = (() => { let _classDecorators = [prop_injectable_1.propertyInjectable]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = TableBucketBase; var TableBucket = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); TableBucket = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-s3tables-alpha.TableBucket", version: "2.223.0-alpha.0" }; /** Uniquely identifies this class. */ static PROPERTY_INJECTION_ID = '@aws-cdk.aws-s3tables-alpha.TableBucket'; /** * Defines a TableBucket construct from an external table bucket ARN. * * @param scope The parent creating construct (usually `this`). * @param id The construct's name. * @param tableBucketArn Amazon Resource Name (arn) of the table bucket */ static fromTableBucketArn(scope, id, tableBucketArn) { return TableBucket.fromTableBucketAttributes(scope, id, { tableBucketArn }); } /** * Defines a TableBucket construct that represents an external table bucket. * * @param scope The parent creating construct (usually `this`). * @param id The construct's name. * @param attrs A `TableBucketAttributes` object. Can be manually created. */ static fromTableBucketAttributes(scope, id, attrs) { try { jsiiDeprecationWarnings._aws_cdk_aws_s3tables_alpha_TableBucketAttributes(attrs); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.fromTableBucketAttributes); } throw error; } const { tableBucketName, region, account, tableBucketArn } = (0, util_1.validateTableBucketAttributes)(scope, attrs); TableBucket.validateTableBucketName(tableBucketName); class Import extends TableBucketBase { tableBucketName = tableBucketName; tableBucketArn = tableBucketArn; tableBucketPolicy; region = region; account = account; encryptionKey = attrs.encryptionKey; autoCreatePolicy = false; /** * Exports this bucket from the stack. */ export() { return attrs; } } return new Import(scope, id, { account, region, physicalName: tableBucketName, }); } /** * Throws an exception if the given table bucket name is not valid. * * @param bucketName name of the bucket. */ static validateTableBucketName(bucketName) { if (bucketName == undefined || core_1.Token.isUnresolved(bucketName)) { // the name is a late-bound value, not a defined string, so skip validation return; } const errors = []; // Length validation if (bucketName.length < 3 || bucketName.length > 63) { errors.push('Bucket name must be at least 3 and no more than 63 characters'); } // Character set validation const illegalCharsetRegEx = /[^a-z0-9-]/; const allowedEdgeCharsetRegEx = /[a-z0-9]/; const illegalCharMatch = bucketName.match(illegalCharsetRegEx); if (illegalCharMatch) { errors.push('Bucket name must only contain lowercase characters, numbers, and hyphens (-)' + ` (offset: ${illegalCharMatch.index})`); } // Edge character validation if (!allowedEdgeCharsetRegEx.test(bucketName.charAt(0))) { errors.push('Bucket name must start with a lowercase letter or number (offset: 0)'); } if (!allowedEdgeCharsetRegEx.test(bucketName.charAt(bucketName.length - 1))) { errors.push(`Bucket name must end with a lowercase letter or number (offset: ${bucketName.length - 1})`); } if (errors.length > 0) { throw new core_1.UnscopedValidationError(`Invalid S3 table bucket name (value: ${bucketName})${os_1.EOL}${errors.join(os_1.EOL)}`); } } /** * Throws an exception if the given unreferencedFileRemovalProperty is not valid. * @param unreferencedFileRemoval configuration for the table bucket */ static validateUnreferencedFileRemoval(unreferencedFileRemoval) { try { jsiiDeprecationWarnings._aws_cdk_aws_s3tables_alpha_UnreferencedFileRemoval(unreferencedFileRemoval); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.validateUnreferencedFileRemoval); } throw error; } // Skip validation if property is not defined if (!unreferencedFileRemoval) { return; } const { noncurrentDays, status, unreferencedDays } = unreferencedFileRemoval; const errors = []; if (noncurrentDays != undefined) { if (noncurrentDays < 1) { errors.push('noncurrentDays must be at least 1 day'); } if (!Number.isInteger(noncurrentDays)) { errors.push('noncurrentDays must be a whole number'); } } if (unreferencedDays != undefined) { if (unreferencedDays < 1) { errors.push('unreferencedDays must be at least 1 day'); } if (!Number.isInteger(noncurrentDays)) { errors.push('unreferencedDays must be a whole number'); } } const allowedStatus = ['Enabled', 'Disabled']; if (status != undefined && !allowedStatus.includes(status)) { errors.push('status must be one of \'Enabled\' or \'Disabled\''); } if (errors.length > 0) { throw new core_1.UnscopedValidationError(`Invalid UnreferencedFileRemovalProperty})${os_1.EOL}${errors.join(os_1.EOL)}`); } } /** * The underlying CfnTableBucket L1 resource * @internal */ _resource; /** * The resource policy for this tableBucket. */ tableBucketPolicy; /** * The unique Amazon Resource Name (arn) of this table bucket */ tableBucketArn; /** * The name of this table bucket */ tableBucketName; encryptionKey; autoCreatePolicy = true; constructor(scope, id, props) { super(scope, id, { physicalName: props.tableBucketName, }); try { jsiiDeprecationWarnings._aws_cdk_aws_s3tables_alpha_TableBucketProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, TableBucket); } throw error; } // Enhanced CDK Analytics Telemetry (0, metadata_resource_1.addConstructMetadata)(this, props); TableBucket.validateTableBucketName(props.tableBucketName); TableBucket.validateUnreferencedFileRemoval(props.unreferencedFileRemoval); const { bucketEncryption, encryptionKey } = this.parseEncryption(props); this.encryptionKey = encryptionKey; this._resource = new s3tables.CfnTableBucket(this, id, { tableBucketName: props.tableBucketName, unreferencedFileRemoval: { ...props.unreferencedFileRemoval, noncurrentDays: props.unreferencedFileRemoval?.noncurrentDays, unreferencedDays: props.unreferencedFileRemoval?.unreferencedDays, }, encryptionConfiguration: bucketEncryption, }); this.tableBucketName = this.getResourceNameAttribute(this._resource.ref); this.tableBucketArn = this._resource.attrTableBucketArn; this._resource.applyRemovalPolicy(props.removalPolicy); } /** * Set up key properties and return the Bucket encryption property from the * user's configuration, according to the following table: * * | props.encryption | props.encryptionKey | bucketEncryption (return value) | encryptionKey (return value) | * |------------------|---------------------|---------------------------------|-------------------------------| * | undefined | undefined | undefined | undefined | * | undefined | k | aws:kms | k | * | KMS | undefined | aws:kms | new key (allow maintenance SP)| * | KMS | k | aws:kms | k | * | S3_MANAGED | undefined | AES256 | undefined | * | S3_MANAGED | k | ERROR! | ERROR! | */ parseEncryption(props) { const encryptionType = props.encryption; let key = props.encryptionKey; if (encryptionType === undefined) { if (key === undefined) { return { bucketEncryption: undefined, encryptionKey: undefined }; } else { return { bucketEncryption: { kmsKeyArn: key.keyArn, sseAlgorithm: TableBucketEncryption.KMS, }, encryptionKey: key, }; } } if (encryptionType === TableBucketEncryption.KMS) { if (key === undefined) { key = new kms.Key(this, 'Key', { description: `Created by ${this.node.path}`, enableKeyRotation: true, }); this.allowTablesMaintenanceAccessToKey(key, props.tableBucketName); } return { bucketEncryption: { kmsKeyArn: key.keyArn, sseAlgorithm: TableBucketEncryption.KMS, }, encryptionKey: key, }; } if (encryptionType === TableBucketEncryption.S3_MANAGED) { if (key === undefined) { return { bucketEncryption: { sseAlgorithm: TableBucketEncryption.S3_MANAGED, }, }; } else { throw new core_1.UnscopedValidationError('Expected encryption = `KMS` with user provided encryption key'); } } throw new core_1.UnscopedValidationError(`Unknown encryption configuration detected: ${props.encryption} with key ${props.encryptionKey}`); } /** * Allowlist S3 Tables Maintenance to access this table bucket's encryption key * * @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-kms-permissions.html * @param encryptionKey The key to provide access to */ allowTablesMaintenanceAccessToKey(encryptionKey, tableBucketName) { const region = this.stack.region; const account = this.stack.account; const partition = this.stack.partition; encryptionKey.addToResourcePolicy(new iam.PolicyStatement({ sid: 'AllowS3TablesMaintenanceAccess', effect: iam.Effect.ALLOW, principals: [ new iam.ServicePrincipal('maintenance.s3tables.amazonaws.com'), ], actions: [ 'kms:GenerateDataKey', 'kms:Decrypt', ], resources: ['*'], conditions: { StringLike: { 'kms:EncryptionContext:aws:s3:arn': `arn:${partition}:s3tables:${region}:${account}:bucket/${tableBucketName}/*`, }, }, })); } static { __runInitializers(_classThis, _classExtraInitializers); } }; return TableBucket = _classThis; })(); exports.TableBucket = TableBucket; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUtYnVja2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidGFibGUtYnVja2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDJCQUF5QjtBQUV6QixxREFBcUQ7QUFDckQsK0RBQTBEO0FBQzFELHVDQUF1QztBQUN2QyxpQ0FBdUQ7QUFDdkQsMkNBQTJDO0FBQzNDLDJDQUEyQztBQUMzQywyQ0FBc0c7QUFDdEcsOEVBQThFO0FBQzlFLDBFQUEwRTtBQTBIMUU7O0dBRUc7QUFDSCxJQUFZLDZCQVVYO0FBVkQsV0FBWSw2QkFBNkI7SUFDdkM7O09BRUc7SUFDSCxvREFBbUIsQ0FBQTtJQUVuQjs7T0FFRztJQUNILHNEQUFxQixDQUFBO0FBQ3ZCLENBQUMsRUFWVyw2QkFBNkIsNkNBQTdCLDZCQUE2QixRQVV4QztBQUVEOztHQUVHO0FBQ0gsSUFBWSxxQkFXWDtBQVhELFdBQVkscUJBQXFCO0lBQy9COzs7T0FHRztJQUNILHdDQUFlLENBQUE7SUFFZjs7T0FFRztJQUNILDhDQUFxQixDQUFBO0FBQ3ZCLENBQUMsRUFYVyxxQkFBcUIscUNBQXJCLHFCQUFxQixRQVdoQztBQUVELE1BQWUsZUFBZ0IsU0FBUSxlQUFRO0lBb0I3Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQW1CRztJQUNJLG1CQUFtQixDQUN4QixTQUE4QjtRQUU5QixJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3JELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLHVDQUFpQixDQUFDLElBQUksRUFBRSxlQUFlLEVBQUU7Z0JBQ3BFLFdBQVcsRUFBRSxJQUFJO2FBQ2xCLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQzNCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMs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Q0FBQyxHQUFHLENBQUM7Z0JBQ2hCLFVBQVUsRUFBRTtvQkFDVixVQUFVLEVBQUU7d0JBQ1Ysa0NBQWtDLEVBQUUsT0FBTyxTQUFTLGFBQWEsTUFBTSxJQUFJLE9BQU8sV0FBVyxlQUFlLElBQUk7cUJBQ2pIO2lCQUNGO2FBQ0YsQ0FBQyxDQUFDLENBQUM7U0FDTDs7WUE5U1UsdURBQVc7Ozs7O0FBQVgsa0NBQVciLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFT0wgfSBmcm9tICdvcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCAqIGFzIHMzdGFibGVzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zM3RhYmxlcyc7XG5pbXBvcnQgeyBUYWJsZUJ1Y2tldFBvbGljeSB9IGZyb20gJy4vdGFibGUtYnVja2V0LXBvbGljeSc7XG5pbXBvcnQgKiBhcyBwZXJtcyBmcm9tICcuL3Blcm1pc3Npb25zJztcbmltcG9ydCB7IHZhbGlkYXRlVGFibGVCdWNrZXRBdHRyaWJ1dGVzIH0gZnJvbSAnLi91dGlsJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGttcyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mta21zJztcbmltcG9ydCB7IFJlc291cmNlLCBJUmVzb3VyY2UsIFVuc2NvcGVkVmFsaWRhdGlvbkVycm9yLCBSZW1vdmFsUG9saWN5LCBUb2tlbiB9IGZyb20gJ2F3cy1jZGstbGliL2NvcmUnO1xuaW1wb3J0IHsgYWRkQ29uc3RydWN0TWV0YWRhdGEgfSBmcm9tICdhd3MtY2RrLWxpYi9jb3JlL2xpYi9tZXRhZGF0YS1yZXNvdXJjZSc7XG5pbXBvcnQgeyBwcm9wZXJ0eUluamVjdGFibGUgfSBmcm9tICdhd3MtY2RrLWxpYi9jb3JlL2xpYi9wcm9wLWluamVjdGFibGUnO1xuXG4vKipcbiAqIEludGVyZmFjZSBkZWZpbml0aW9uIGZvciBTMyBUYWJsZSBCdWNrZXRzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSVRhYmxlQnVja2V0IGV4dGVuZHMgSVJlc291cmNlIHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIHRhYmxlIGJ1Y2tldC5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVCdWNrZXRBcm46IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIHRhYmxlIGJ1Y2tldC5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVCdWNrZXROYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBhY2NvdW50SWQgY29udGFpbmluZyB0aGUgdGFibGUgYnVja2V0LlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSBhY2NvdW50Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVnaW9uIGNvbnRhaW5pbmcgdGhlIHRhYmxlIGJ1Y2tldC5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVnaW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBLTVMgZW5jcnlwdGlvbiBrZXkgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUgYnVja2V0LlxuICAgKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuXG4gIC8qKlxuICAgKiBBZGRzIGEgc3RhdGVtZW50IHRvIHRoZSByZXNvdXJjZSBwb2xpY3kgZm9yIGEgcHJpbmNpcGFsIChpLmUuXG4gICAqIGFjY291bnQvcm9sZS9zZXJ2aWNlKSB0byBwZXJmb3JtIGFjdGlvbnMgb24gdGhpcyB0YWJsZSBidWNrZXQgYW5kL29yIGl0c1xuICAgKiB0YWJsZXMuXG4gICAqXG4gICAqIE5vdGUgdGhhdCB0aGUgcG9saWN5IHN0YXRlbWVudCBtYXkgb3IgbWF5IG5vdCBiZSBhZGRlZCB0byB0aGUgcG9saWN5LlxuICAgKiBGb3IgZXhhbXBsZSwgd2hlbiBhbiBgSVRhYmxlQnVja2V0YCBpcyBjcmVhdGVkIGZyb20gYW4gZXhpc3RpbmcgdGFibGUgYnVja2V0LFxuICAgKiBpdCdzIG5vdCBwb3NzaWJsZSB0byB0ZWxsIHdoZXRoZXIgdGhlIGJ1Y2tldCBhbHJlYWR5IGhhcyBhIHBvbGljeVxuICAgKiBhdHRhY2hlZCwgbGV0IGFsb25lIHRvIHJlLXVzZSB0aGF0IHBvbGljeSB0byBhZGQgbW9yZSBzdGF0ZW1lbnRzIHRvIGl0LlxuICAgKiBTbyBpdCdzIHNhZmVzdCB0byBkbyBub3RoaW5nIGluIHRoZXNlIGNhc2VzLlxuICAgKlxuICAgKiBAcGFyYW0gc3RhdGVtZW50IHRoZSBwb2xpY3kgc3RhdGVtZW50IHRvIGJlIGFkZGVkIHRvIHRoZSBidWNrZXQnc1xuICAgKiBwb2xpY3kuXG4gICAqIEByZXR1cm5zIG1ldGFkYXRhIGFib3V0IHRoZSBleGVjdXRpb24gb2YgdGhpcyBtZXRob2QuIElmIHRoZSBwb2xpY3lcbiAgICogd2FzIG5vdCBhZGRlZCwgdGhlIHZhbHVlIG9mIGBzdGF0ZW1lbnRBZGRlZGAgd2lsbCBiZSBgZmFsc2VgLiBZb3VcbiAgICogc2hvdWxkIGFsd2F5cyBjaGVjayB0aGlzIHZhbHVlIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBvcGVyYXRpb24gd2FzXG4gICAqIGFjdHVhbGx5IGNhcnJpZWQgb3V0LiBPdGhlcndpc2UsIHN5bnRoZXNpcyBhbmQgZGVwbG95IHdpbGwgdGVybWluYXRlXG4gICAqIHNpbGVudGx5LCB3aGljaCBtYXkgYmUgY29uZnVzaW5nLlxuICAgKi9cbiAgYWRkVG9SZXNvdXJjZVBvbGljeShzdGF0ZW1lbnQ6IGlhbS5Qb2xpY3lTdGF0ZW1lbnQpOiBpYW0uQWRkVG9SZXNvdXJjZVBvbGljeVJlc3VsdDtcblxuICAvKipcbiAgICogR3JhbnQgcmVhZCBwZXJtaXNzaW9ucyBmb3IgdGhpcyB0YWJsZSBidWNrZXQgYW5kIGl0cyB0YWJsZXNcbiAgICogdG8gYW4gSUFNIHByaW5jaXBhbCAoUm9sZS9Hcm91cC9Vc2VyKS5cbiAgICpcbiAgICogSWYgZW5jcnlwdGlvbiBpcyB1c2VkLCBwZXJtaXNzaW9uIHRvIHVzZSB0aGUga2V5IHRvIGRlY3J5cHQgdGhlIGNvbnRlbnRzXG4gICAqIG9mIHRoZSBidWNrZXQgd2lsbCBhbHNvIGJlIGdyYW50ZWQgdG8gdGhlIHNhbWUgcHJpbmNpcGFsLlxuICAgKlxuICAgKiBAcGFyYW0gaWRlbnRpdHkgVGhlIHByaW5jaXBhbCB0byBhbGxvdyByZWFkIHBlcm1pc3Npb25zIHRvXG4gICAqIEBwYXJhbSB0YWJsZUlkIEFsbG93IHRoZSBwZXJtaXNzaW9ucyB0byBhbGwgdGFibGVzIHVzaW5nICcqJyBvciB0byBzaW5nbGUgdGFibGUgYnkgaXRzIHVuaXF1ZSBJRC5cbiAgICovXG4gIGdyYW50UmVhZChpZGVudGl0eTogaWFtLklHcmFudGFibGUsIHRhYmxlSWQ6IHN0cmluZyk6IGlhbS5HcmFudDtcblxuICAvKipcbiAgICogR3JhbnQgd3JpdGUgcGVybWlzc2lvbnMgZm9yIHRoaXMgdGFibGUgYnVja2V0IGFuZCBpdHMgdGFibGVzXG4gICAqIHRvIGFuIElBTSBwcmluY2lwYWwgKFJvbGUvR3JvdXAvVXNlcikuXG4gICAqXG4gICAqIElmIGVuY3J5cHRpb24gaXMgdXNlZCwgcGVybWlzc2lvbiB0byB1c2UgdGhlIGtleSB0byBlbmNyeXB0IHRoZSBjb250ZW50c1xuICAgKiBvZiB0aGUgYnVja2V0IHdpbGwgYWxzbyBiZSBncmFudGVkIHRvIHRoZSBzYW1lIHByaW5jaXBhbC5cbiAgICpcbiAgICogQHBhcmFtIGlkZW50aXR5IFRoZSBwcmluY2lwYWwgdG8gYWxsb3cgd3JpdGUgcGVybWlzc2lvbnMgdG9cbiAgICogQHBhcmFtIHRhYmxlSWQgQWxsb3cgdGhlIHBlcm1pc3Npb25zIHRvIGFsbCB0YWJsZXMgdXNpbmcgJyonIG9yIHRvIHNpbmdsZSB0YWJsZSBieSBpdHMgdW5pcXVlIElELlxuICAgKi9cbiAgZ3JhbnRXcml0ZShpZGVudGl0eTogaWFtLklHcmFudGFibGUsIHRhYmxlSWQ6IHN0cmluZyk6IGlhbS5HcmFudDtcblxuICAvKipcbiAgICogR3JhbnQgcmVhZCBhbmQgd3JpdGUgcGVybWlzc2lvbnMgZm9yIHRoaXMgdGFibGUgYnVja2V0IGFuZCBpdHMgdGFibGVzXG4gICAqIHRvIGFuIElBTSBwcmluY2lwYWwgKFJvbGUvR3JvdXAvVXNlcikuXG4gICAqXG4gICAqIElmIGVuY3J5cHRpb24gaXMgdXNlZCwgcGVybWlzc2lvbiB0byB1c2UgdGhlIGtleSB0byBlbmNyeXB0L2RlY3J5cHQgdGhlIGNvbnRlbnRzXG4gICAqIG9mIHRoZSBidWNrZXQgd2lsbCBhbHNvIGJlIGdyYW50ZWQgdG8gdGhlIHNhbWUgcHJpbmNpcGFsLlxuICAgKlxuICAgKiBAcGFyYW0gaWRlbnRpdHkgVGhlIHByaW5jaXBhbCB0byBhbGxvdyByZWFkIGFuZCB3cml0ZSBwZXJtaXNzaW9ucyB0b1xuICAgKiBAcGFyYW0gdGFibGVJZCBBbGxvdyB0aGUgcGVybWlzc2lvbnMgdG8gYWxsIHRhYmxlcyB1c2luZyAnKicgb3IgdG8gc2luZ2xlIHRhYmxlIGJ5IGl0cyB1bmlxdWUgSUQuXG4gICAqL1xuICBncmFudFJlYWRXcml0ZShpZGVudGl0eTogaWFtLklHcmFudGFibGUsIHRhYmxlSWQ6IHN0cmluZyk6IGlhbS5HcmFudDtcbn1cblxuLyoqXG4gKiBVbnJlZmVyZW5jZWQgZmlsZSByZW1vdmFsIHNldHRpbmdzIGZvciB0aGUgdGhpcyB0YWJsZSBidWNrZXQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVW5yZWZlcmVuY2VkRmlsZVJlbW92YWwge1xuICAvKipcbiAgICogRHVyYXRpb24gYWZ0ZXIgd2hpY2ggbm9uY3VycmVudCBmaWxlcyBzaG91bGQgYmUgcmVtb3ZlZC4gU2hvdWxkIGJlIGF0IGxlYXN0IG9uZSBkYXkuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvblMzL2xhdGVzdC91c2VyZ3VpZGUvczMtdGFibGUtYnVja2V0cy1tYWludGVuYW5jZS5odG1sXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gU2VlIFMzIFRhYmxlcyBVc2VyIEd1aWRlXG4gICAqL1xuICByZWFkb25seSBub25jdXJyZW50RGF5cz86IG51bWJlcjtcblxuICAvKipcbiAgICogU3RhdHVzIG9mIHVucmVmZXJlbmNlZCBmaWxlIHJlbW92YWwuIENhbiBiZSBFbmFibGVkIG9yIERpc2FibGVkLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25TMy9sYXRlc3QvdXNlcmd1aWRlL3MzLXRhYmxlLWJ1Y2tldHMtbWFpbnRlbmFuY2UuaHRtbFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFNlZSBTMyBUYWJsZXMgVXNlciBHdWlkZVxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdHVzPzogVW5yZWZlcmVuY2VkRmlsZVJlbW92YWxTdGF0dXM7XG5cbiAgLyoqXG4gICAqIER1cmF0aW9uIGFmdGVyIHdoaWNoIHVucmVmZXJlbmNlZCBmaWxlcyBzaG91bGQgYmUgcmVtb3ZlZC4gU2hvdWxkIGJlIGF0IGxlYXN0IG9uZSBkYXkuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvblMzL2xhdGVzdC91c2VyZ3VpZGUvczMtdGFibGUtYnVja2V0cy1tYWludGVuYW5jZS5odG1sXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gU2VlIFMzIFRhYmxlcyBVc2VyIEd1aWRlXG4gICAqL1xuICByZWFkb25seSB1bnJlZmVyZW5jZWREYXlzPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIENvbnRyb2xzIHdoZXRoZXIgdW5yZWZlcmVuY2VkIGZpbGUgcmVtb3ZhbCBpcyBlbmFibGVkIG9yIGRpc2FibGVkLlxuICovXG5leHBvcnQgZW51bSBVbnJlZmVyZW5jZWRGaWxlUmVtb3ZhbFN0YXR1cyB7XG4gIC8qKlxuICAgKiBFbmFibGUgdW5yZWZlcmVuY2VkIGZpbGUgcmVtb3ZhbC5cbiAgICovXG4gIEVOQUJMRUQgPSAnRW5hYmxlZCcsXG5cbiAgLyoqXG4gICAqIERpc2FibGUgdW5yZWZlcmVuY2VkIGZpbGUgcmVtb3ZhbC5cbiAgICovXG4gIERJU0FCTEVEID0gJ0Rpc2FibGVkJyxcbn1cblxuLyoqXG4gKiBDb250cm9scyBTZXJ2ZXIgU2lkZSBFbmNyeXB0aW9uIChTU0UpIGZvciB0aGlzIFRhYmxlQnVja2V0LlxuICovXG5leHBvcnQgZW51bSBUYWJsZUJ1Y2tldEVuY3J5cHRpb24ge1xuICAvKipcbiAgICogVXNlIGEgY3VzdG9tZXIgZGVmaW5lZCBLTVMga2V5IGZvciBlbmNyeXB0aW9uXG4gICAqIElmIGBlbmNyeXB0aW9uS2V5YCBpcyBzcGVjaWZpZWQsIHRoaXMga2V5IHdpbGwgYmUgdXNlZCwgb3RoZXJ3aXNlLCBvbmUgd2lsbCBiZSBkZWZpbmVkLlxuICAgKi9cbiAgS01TID0gJ2F3czprbXMnLFxuXG4gIC8qKlxuICAgKiBVc2UgUzMgbWFuYWdlZCBlbmNyeXB0aW9uIGtleXMgd2l0aCBBRVMyNTYgZW5jcnlwdGlvblxuICAgKi9cbiAgUzNfTUFOQUdFRCA9ICdBRVMyNTYnLFxufVxuXG5hYnN0cmFjdCBjbGFzcyBUYWJsZUJ1Y2tldEJhc2UgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElUYWJsZUJ1Y2tldCB7XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSB0YWJsZUJ1Y2tldEFybjogc3RyaW5nO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgdGFibGVCdWNrZXROYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSByZXNvdXJjZSBwb2xpY3kgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUgYnVja2V0LlxuICAgKlxuICAgKiBJZiBgYXV0b0NyZWF0ZVBvbGljeWAgaXMgdHJ1ZSwgYSBgVGFibGVCdWNrZXRQb2xpY3lgIHdpbGwgYmUgY3JlYXRlZCB1cG9uIHRoZVxuICAgKiBmaXJzdCBjYWxsIHRvIGFkZFRvUmVzb3VyY2VQb2xpY3kocykuXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgdGFibGVCdWNrZXRQb2xpY3k/OiBUYWJsZUJ1Y2tldFBvbGljeTtcblxuICAvKipcbiAgICogSW5kaWNhdGVzIGlmIGEgdGFibGUgYnVja2V0IHJlc291cmNlIHBvbGljeSBzaG91bGQgYXV0b21hdGljYWxseSBjcmVhdGVkIHVwb25cbiAgICogdGhlIGZpcnN0IGNhbGwgdG8gYGFkZFRvUmVzb3VyY2VQb2xpY3lgLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGF1dG9DcmVhdGVQb2xpY3k6IGJvb2xlYW47XG5cbiAgcHVibGljIGFic3RyYWN0IGVuY3J5cHRpb25LZXk/OiBrbXMuSUtleSB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQWRkcyBhIHN0YXRlbWVudCB0byB0aGUgcmVzb3VyY2UgcG9saWN5IGZvciBhIHByaW5jaXBhbCAoaS5lLlxuICAgKiBhY2NvdW50L3JvbGUvc2VydmljZSkgdG8gcGVyZm9ybSBhY3Rpb25zIG9uIHRoaXMgdGFibGUgYnVja2V0IGFuZC9vciBpdHNcbiAgICogY29udGVudHMuIFVzZSBgdGFibGVCdWNrZXRBcm5gIGFuZCBgYXJuRm9yT2JqZWN0cyhrZXlzKWAgdG8gb2J0YWluIEFSTnMgZm9yXG4gICAqIHRoaXMgYnVja2V0IG9yIG9iamVjdHMuXG4gICAqXG4gICAqIE5vdGUgdGhhdCB0aGUgcG9saWN5IHN0YXRlbWVudCBtYXkgb3IgbWF5IG5vdCBiZSBhZGRlZCB0byB0aGUgcG9saWN5LlxuICAgKiBGb3IgZXhhbXBsZSwgd2hlbiBhbiBgSVRhYmxlQnVja2V0YCBpcyBjcmVhdGVkIGZyb20gYW4gZXhpc3RpbmcgdGFibGUgYnVja2V0LFxuICAgKiBpdCdzIG5vdCBwb3NzaWJsZSB0byB0ZWxsIHdoZXRoZXIgdGhlIGJ1Y2tldCBhbHJlYWR5IGhhcyBhIHBvbGljeVxuICAgKiBhdHRhY2hlZCwgbGV0IGFsb25lIHRvIHJlLXVzZSB0aGF0IHBvbGljeSB0byBhZGQgbW9yZSBzdGF0ZW1lbnRzIHRvIGl0LlxuICAgKiBTbyBpdCdzIHNhZmVzdCB0byBkbyBub3RoaW5nIGluIHRoZXNlIGNhc2VzLlxuICAgKlxuICAgKiBAcGFyYW0gc3RhdGVtZW50IHRoZSBwb2xpY3kgc3RhdGVtZW50IHRvIGJlIGFkZGVkIHRvIHRoZSBidWNrZXQnc1xuICAgKiBwb2xpY3kuXG4gICAqIEByZXR1cm5zIG1ldGFkYXRhIGFib3V0IHRoZSBleGVjdXRpb24gb2YgdGhpcyBtZXRob2QuIElmIHRoZSBwb2xpY3lcbiAgICogd2FzIG5vdCBhZGRlZCwgdGhlIHZhbHVlIG9mIGBzdGF0ZW1lbnRBZGRlZGAgd2lsbCBiZSBgZmFsc2VgLiBZb3VcbiAgICogc2hvdWxkIGFsd2F5cyBjaGVjayB0aGlzIHZhbHVlIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBvcGVyYXRpb24gd2FzXG4gICAqIGFjdHVhbGx5IGNhcnJpZWQgb3V0LiBPdGhlcndpc2UsIHN5bnRoZXNpcyBhbmQgZGVwbG95IHdpbGwgdGVybWluYXRlXG4gICAqIHNpbGVudGx5LCB3aGljaCBtYXkgYmUgY29uZnVzaW5nLlxuICAgKi9cbiAgcHVibGljIGFkZFRvUmVzb3VyY2VQb2xpY3koXG4gICAgc3RhdGVtZW50OiBpYW0uUG9saWN5U3RhdGVtZW50LFxuICApOiBpYW0uQWRkVG9SZXNvdXJjZVBvbGljeVJlc3VsdCB7XG4gICAgaWYgKCF0aGlzLnRhYmxlQnVja2V0UG9saWN5ICYmIHRoaXMuYXV0b0NyZWF0ZVBvbGljeSkge1xuICAgICAgdGhpcy50YWJsZUJ1Y2tldFBvbGljeSA9IG5ldyBUYWJsZUJ1Y2tldFBvbGljeSh0aGlzLCAnRGVmYXVsdFBvbGljeScsIHtcbiAgICAgICAgdGFibGVCdWNrZXQ6IHRoaXMsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy50YWJsZUJ1Y2tldFBvbGljeSkge1xuICAgICAgdGhpcy50YWJsZUJ1Y2tldFBvbGljeS5kb2N1bWVudC5hZGRTdGF0ZW1lbnRzKHN0YXRlbWVudCk7XG4gICAgICByZXR1cm4geyBzdGF0ZW1lbnRBZGRlZDogdHJ1ZSwgcG9saWN5RGVwZW5kYWJsZTogdGhpcy50YWJsZUJ1Y2tldFBvbGljeSB9O1xuICAgIH1cblxuICAgIHJldHVybiB7IHN0YXRlbWVudEFkZGVkOiBmYWxzZSB9O1xuICB9XG5cbiAgcHVibGljIGdyYW50UmVhZChpZGVudGl0eTogaWFtLklHcmFudGFibGUsIHRhYmxlSWQ6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmdyYW50KFxuICAgICAgaWRlbnRpdHksXG4gICAgICBwZXJtcy5UQUJMRV9CVUNLRVRfUkVBRF9BQ0NFU1MsXG4gICAgICBwZXJtcy5LRVlfUkVBRF9BQ0NFU1MsXG4gICAgICB0aGlzLnRhYmxlQnVja2V0QXJuLFxuICAgICAgdGhpcy5nZXRUYWJsZUFybih0YWJsZUlkKSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGdyYW50V3JpdGUoaWRlbnRpdHk6IGlhbS5JR3JhbnRhYmxlLCB0YWJsZUlkOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5ncmFudChcbiAgICAgIGlkZW50aXR5LFxuICAgICAgcGVybXMuVEFCTEVfQlVDS0VUX1dSSVRFX0FDQ0VTUyxcbiAgICAgIHBlcm1zLktFWV9SRUFEX1dSSVRFX0FDQ0VTUyxcbiAgICAgIHRoaXMudGFibGVCdWNrZXRBcm4sXG4gICAgICB0aGlzLmdldFRhYmxlQXJuKHRhYmxlSWQpLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgZ3JhbnRSZWFkV3JpdGUoaWRlbnRpdHk6IGlhbS5JR3JhbnRhYmxlLCB0YWJsZUlkOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5ncmFudChcbiAgICAgIGlkZW50aXR5LFxuICAgICAgcGVybXMuVEFCTEVfQlVDS0VUX1JFQURfV1JJVEVfQUNDRVNTLFxuICAgICAgcGVybXMuS0VZX1dSSVRFX0FDQ0VTUyxcbiAgICAgIHRoaXMudGFibGVCdWNrZXRBcm4sXG4gICAgICB0aGlzLmdldFRhYmxlQXJuKHRhYmxlSWQpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHRoZSBnaXZlbiBzM3RhYmxlcyBwZXJtaXNzaW9ucyB0byB0aGUgcHJvdmlkZWQgcHJpbmNpcGFsXG4gICAqIEByZXR1cm5zIEdyYW50IG9iamVjdFxuICAgKi9cbiAgcHJpdmF0ZSBncmFudChcbiAgICBncmFudGVlOiBpYW0uSUdyYW50YWJsZSxcbiAgICB0YWJsZUJ1Y2tldEFjdGlvbnM6IHN0cmluZ1tdLFxuICAgIGtleUFjdGlvbnM6IHN0cmluZ1tdLFxuICAgIHJlc291cmNlQXJuOiBzdHJpbmcsXG4gICAgLi4ub3RoZXJSZXNvdXJjZUFybnM6IChzdHJpbmcgfCB1bmRlZmluZWQpW10pIHtcbiAgICBjb25zdCByZXNvdXJjZXMgPSBbcmVzb3VyY2VBcm4sIC4uLm90aGVyUmVzb3VyY2VBcm5zXS5maWx0ZXIoYXJuID0+IGFybiAhPSB1bmRlZmluZWQpO1xuXG4gICAgY29uc3QgZ3JhbnQgPSBpYW0uR3JhbnQuYWRkVG9QcmluY2lwYWxPclJlc291cmNlKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zOiB0YWJsZUJ1Y2tldEFjdGlvbnMsXG4gICAgICByZXNvdXJjZUFybnM6IHJlc291cmNlcyxcbiAgICAgIHJlc291cmNlOiB0aGlzLFxuICAgIH0pO1xuXG4gICAgaWYgKHRoaXMuZW5jcnlwdGlvbktleSAmJiBrZXlBY3Rpb25zICYmIGtleUFjdGlvbnMubGVuZ3RoICE9PSAwKSB7XG4gICAgICB0aGlzLmVuY3J5cHRpb25LZXkuZ3JhbnQoZ3JhbnRlZSwgLi4ua2V5QWN0aW9ucyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdyYW50O1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUYWJsZUFybih0YWJsZUlkOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdGFibGVJZCA/IGAke3RoaXMudGFibGVCdWNrZXRBcm59L3RhYmxlLyR7dGFibGVJZH1gIDogdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3IgY29uc3RydWN0aW5nIGEgVGFibGVCdWNrZXRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUYWJsZUJ1Y2tldFByb3BzIHtcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIFMzIFRhYmxlQnVja2V0LlxuICAgKiBAbGluayBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uUzMvbGF0ZXN0L3VzZXJndWlkZS9zMy10YWJsZXMtYnVja2V0cy1uYW1pbmcuaHRtbCN0YWJsZS1idWNrZXRzLW5hbWluZy1ydWxlc1xuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVCdWNrZXROYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFVucmVmZXJlbmNlZCBmaWxlIHJlbW92YWwgc2V0dGluZ3MgZm9yIHRoZSBTMyBUYWJsZUJ1Y2tldC5cbiAgICogQGxpbmsgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtczN0YWJsZXMtdGFibGVidWNrZXQtdW5yZWZlcmVuY2VkZmlsZXJlbW92YWwuaHRtbFxuICAgKiBAZGVmYXVsdCBFbmFibGVkIHdpdGggZGVmYXVsdCB2YWx1ZXNcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uUzMvbGF0ZXN0L3VzZXJndWlkZS9zMy10YWJsZS1idWNrZXRzLW1haW50ZW5hbmNlLmh0bWxcbiAgICovXG4gIHJlYWRvbmx5IHVucmVmZXJlbmNlZEZpbGVSZW1vdmFsPzogVW5yZWZlcmVuY2VkRmlsZVJlbW92YWw7XG5cbiAgLyoqXG4gICAqIEFXUyByZWdpb24gdGhhdCB0aGUgdGFibGUgYnVja2V0IGV4aXN0cyBpbi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBpdCdzIGFzc3VtZWQgdGhlIGJ1Y2tldCBpcyBpbiB0aGUgc2FtZSByZWdpb24gYXMgdGhlIHNjb3BlIGl0J3MgYmVpbmcgaW1wb3J0ZWQgaW50b1xuICAgKi9cbiAgcmVhZG9ubHkgcmVnaW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBV1MgQWNjb3VudCBJRCBvZiB0aGUgdGFibGUgYnVja2V0IG93bmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGl0J3MgYXNzdW1lZCB0aGUgYnVja2V0IGJlbG9uZ3MgdG8gdGhlIHNhbWUgYWNjb3VudCBhcyB0aGUgc2NvcGUgaXQncyBiZWluZyBpbXBvcnRlZCBpbnRvXG4gICAqL1xuICByZWFkb25seSBhY2NvdW50Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUga2luZCBvZiBzZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIHRvIGFwcGx5IHRvIHRoaXMgYnVja2V0LlxuICAgKlxuICAgKiBJZiB5b3UgY2hvb3NlIEtNUywgeW91IGNhbiBzcGVjaWZ5IGEgS01TIGtleSB2aWEgYGVuY3J5cHRpb25LZXlgLiBJZlxuICAgKiBlbmNyeXB0aW9uIGtleSBpcyBub3Qgc3BlY2lmaWVkLCBhIGtleSB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgY3JlYXRlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBgS01TYCBpZiBgZW5jcnlwdGlvbktleWAgaXMgc3BlY2lmaWVkLCBvciBgUzNfTUFOQUdFRGAgb3RoZXJ3aXNlLlxuICAgKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbj86IFRhYmxlQnVja2V0RW5jcnlwdGlvbjtcblxuICAvKipcbiAgICogRXh0ZXJuYWwgS01TIGtleSB0byB1c2UgZm9yIGJ1Y2tldCBlbmNyeXB0aW9uLlxuICAgKlxuICAgKiBUaGUgYGVuY3J5cHRpb25gIHByb3BlcnR5IG11c3QgYmUgZWl0aGVyIG5vdCBzcGVjaWZpZWQgb3Igc2V0IHRvIGBLTVNgLlxuICAgKiBBbiBlcnJvciB3aWxsIGJlIGVtaXR0ZWQgaWYgYGVuY3J5cHRpb25gIGlzIHNldCB0byBgUzNfTUFOQUdFRGAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gSWYgYGVuY3J5cHRpb25gIGlzIHNldCB0byBgS01TYCBhbmQgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWQsXG4gICAqIGEgbmV3IEtNUyBrZXkgd2lsbCBiZSBjcmVhdGVkIGFuZCBhc3NvY2lhdGVkIHdpdGggdGhpcyBidWNrZXQuXG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG5cbiAgLyoqXG4gICAqIENvbnRyb2xzIHdoYXQgaGFwcGVucyB0byB0aGlzIHRhYmxlIGJ1Y2tldCBpdCBpdCBzdG9wZWQgYmVpbmcgbWFuYWdlZCBieSBjbG91ZGZvcm1hdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgUkVUQUlOXG4gICAqL1xuICByZWFkb25seSByZW1vdmFsUG9saWN5PzogUmVtb3ZhbFBvbGljeTtcbn1cblxuLyoqXG4gKiBBIHJlZmVyZW5jZSB0byBhIHRhYmxlIGJ1Y2tldCBvdXRzaWRlIHRoaXMgc3RhY2tcbiAqXG4gKiBUaGUgdGFibGVCdWNrZXROYW1lLCByZWdpb24sIGFuZCBhY2NvdW50IGNhbiBiZSBwcm92aWRlZCBleHBsaWNpdGx5XG4gKiBvciB3aWxsIGJlIGluZmVycmVkIGZyb20gdGhlIHRhYmxlQnVja2V0QXJuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGFibGVCdWNrZXRBdHRyaWJ1dGVzIHtcbiAgLyoqXG4gICAqIEFXUyByZWdpb24gdGhpcyB0YWJsZSBidWNrZXQgZXhpc3RzIGluXG4gICAqIEBkZWZhdWx0IHJlZ2lvbiBpbmZlcnJlZCBmcm9tIHNjb3BlXG4gICAqL1xuICByZWFkb25seSByZWdpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBhY2NvdW50SWQgY29udGFpbmluZyB0aGlzIHRhYmxlIGJ1Y2tldFxuICAgKiBAZGVmYXVsdCBhY2NvdW50IGluZmVycmVkIGZyb20gc2NvcGVcbiAgICovXG4gIHJlYWRvbmx5IGFjY291bnQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB0YWJsZSBidWNrZXQgbmFtZSwgdW5pcXVlIHBlciByZWdpb25cbiAgICogQGRlZmF1bHQgdGFibGVCdWNrZXROYW1lIGluZmVycmVkIGZyb20gYXJuXG4gICAqL1xuICByZWFkb25seSB0YWJsZUJ1Y2tldE5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB0YWJsZSBidWNrZXQncyBBUk4uXG4gICAqIEBkZWZhdWx0IHRhYmxlQnVja2V0QXJuIGNvbnN0cnVjdGVkIGZyb20gcmVnaW9uLCBhY2NvdW50IGFuZCB0YWJsZUJ1Y2tldE5hbWUgYXJlIHByb3ZpZGVkXG4gICAqL1xuICByZWFkb25seSB0YWJsZUJ1Y2tldEFybj86IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9uYWwgS01TIGVuY3J5cHRpb24ga2V5IGFzc29jaWF0ZWQgd2l0aCB0aGlzIGJ1Y2tldC5cbiAgICogQGRlZmF1bHQgLSB1bmRlZmluZWRcbiAgICovXG4gIHJlYWRvbmx5IGVuY3J5cHRpb25LZXk/OiBrbXMuSUtleTtcbn1cblxuLyoqXG4gKiBBbiBTMyB0YWJsZSBidWNrZXQgd2l0aCBoZWxwZXJzIGZvciBhc3NvY2lhdGVkIHJlc291cmNlIHBvbGljaWVzXG4gKlxuICogVGhpcyBidWNrZXQgbWF5IG5vdCB5ZXQgaGF2ZSBhbGwgZmVhdHVyZXMgdGhhdCBleHBvc2VkIGJ5IHRoZSB1bmRlcmx5aW5nIENmblRhYmxlQnVja2V0LlxuICpcbiAqIEBzdGF0ZWZ1bFxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHNhbXBsZVRhYmxlQnVja2V0ID0gbmV3IFRhYmxlQnVja2V0KHNjb3BlLCAnRXhhbXBsZVRhYmxlQnVja2V0Jywge1xuICogICB0YWJsZUJ1Y2tldE5hbWU6ICdleGFtcGxlLWJ1Y2tldCcsXG4gKiAgIC8vIE9wdGlvbmFsIGZpZWxkczpcbiAqICAgdW5yZWZlcmVuY2VkRmlsZVJlbW92YWw6IHtcbiAqICAgICBub25jdXJyZW50RGF5czogMTIzLFxuICogICAgIHN0YXR1czogVW5yZWZlcmVuY2VkRmlsZVJlbW92YWxTdGF0dXMuRU5BQkxFRCxcbiAqICAgICB1bnJlZmVyZW5jZWREYXlzOiAxMjMsXG4gKiAgIH0sXG4gK