UNPKG

@aws-cdk/aws-s3

Version:

The CDK Construct Library for AWS::S3

150 lines 21.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BucketNotifications = void 0; const iam = require("@aws-cdk/aws-iam"); const cdk = require("@aws-cdk/core"); const bucket_1 = require("../bucket"); const destination_1 = require("../destination"); const notifications_resource_handler_1 = require("./notifications-resource-handler"); // keep this import separate from other imports to reduce chance for merge conflicts with v2-main // eslint-disable-next-line no-duplicate-imports, import/order const core_1 = require("@aws-cdk/core"); /** * A custom CloudFormation resource that updates bucket notifications for a * bucket. The reason we need it is because the AWS::S3::Bucket notification * configuration is defined on the bucket itself, which makes it impossible to * provision notifications at the same time as the target (since * PutBucketNotifications validates the targets). * * Since only a single BucketNotifications resource is allowed for each Bucket, * this construct is not exported in the public API of this module. Instead, it * is created just-in-time by `s3.Bucket.onEvent`, so a 1:1 relationship is * ensured. * * @see * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-notificationconfig.html */ class BucketNotifications extends core_1.Construct { constructor(scope, id, props) { super(scope, id); this.eventBridgeEnabled = false; this.lambdaNotifications = new Array(); this.queueNotifications = new Array(); this.topicNotifications = new Array(); this.bucket = props.bucket; this.handlerRole = props.handlerRole; } /** * Adds a notification subscription for this bucket. * If this is the first notification, a BucketNotification resource is added to the stack. * * @param event The type of event * @param target The target construct * @param filters A set of S3 key filters */ addNotification(event, target, ...filters) { const resource = this.createResourceOnce(); // resolve target. this also provides an opportunity for the target to e.g. update // policies to allow this notification to happen. const targetProps = target.bind(this, this.bucket); const commonConfig = { Events: [event], Filter: renderFilters(filters), }; // if the target specifies any dependencies, add them to the custom resource. // for example, the SNS topic policy must be created /before/ the notification resource. // otherwise, S3 won't be able to confirm the subscription. if (targetProps.dependencies) { resource.node.addDependency(...targetProps.dependencies); } // based on the target type, add the the correct configurations array switch (targetProps.type) { case destination_1.BucketNotificationDestinationType.LAMBDA: this.lambdaNotifications.push({ ...commonConfig, LambdaFunctionArn: targetProps.arn }); break; case destination_1.BucketNotificationDestinationType.QUEUE: this.queueNotifications.push({ ...commonConfig, QueueArn: targetProps.arn }); break; case destination_1.BucketNotificationDestinationType.TOPIC: this.topicNotifications.push({ ...commonConfig, TopicArn: targetProps.arn }); break; default: throw new Error('Unsupported notification target type:' + destination_1.BucketNotificationDestinationType[targetProps.type]); } } enableEventBridgeNotification() { this.createResourceOnce(); this.eventBridgeEnabled = true; } renderNotificationConfiguration() { return { EventBridgeConfiguration: this.eventBridgeEnabled ? {} : undefined, LambdaFunctionConfigurations: this.lambdaNotifications.length > 0 ? this.lambdaNotifications : undefined, QueueConfigurations: this.queueNotifications.length > 0 ? this.queueNotifications : undefined, TopicConfigurations: this.topicNotifications.length > 0 ? this.topicNotifications : undefined, }; } /** * Defines the bucket notifications resources in the stack only once. * This is called lazily as we add notifications, so that if notifications are not added, * there is no notifications resource. */ createResourceOnce() { if (!this.resource) { const handler = notifications_resource_handler_1.NotificationsResourceHandler.singleton(this, { role: this.handlerRole, }); const managed = this.bucket instanceof bucket_1.Bucket; if (!managed) { handler.addToRolePolicy(new iam.PolicyStatement({ actions: ['s3:GetBucketNotification'], resources: ['*'], })); } this.resource = new cdk.CfnResource(this, 'Resource', { type: 'Custom::S3BucketNotifications', properties: { ServiceToken: handler.functionArn, BucketName: this.bucket.bucketName, NotificationConfiguration: cdk.Lazy.any({ produce: () => this.renderNotificationConfiguration() }), Managed: managed, }, }); } return this.resource; } } exports.BucketNotifications = BucketNotifications; function renderFilters(filters) { if (!filters || filters.length === 0) { return undefined; } const renderedRules = new Array(); let hasPrefix = false; let hasSuffix = false; for (const rule of filters) { if (!rule.suffix && !rule.prefix) { throw new Error('NotificationKeyFilter must specify `prefix` and/or `suffix`'); } if (rule.suffix) { if (hasSuffix) { throw new Error('Cannot specify more than one suffix rule in a filter.'); } renderedRules.push({ Name: 'suffix', Value: rule.suffix }); hasSuffix = true; } if (rule.prefix) { if (hasPrefix) { throw new Error('Cannot specify more than one prefix rule in a filter.'); } renderedRules.push({ Name: 'prefix', Value: rule.prefix }); hasPrefix = true; } } return { Key: { FilterRules: renderedRules, }, }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZpY2F0aW9ucy1yZXNvdXJjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm5vdGlmaWNhdGlvbnMtcmVzb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsd0NBQXdDO0FBQ3hDLHFDQUFxQztBQUNyQyxzQ0FBOEU7QUFDOUUsZ0RBQW1HO0FBQ25HLHFGQUFnRjtBQUVoRixpR0FBaUc7QUFDakcsOERBQThEO0FBQzlELHdDQUEwQztBQWMxQzs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQWEsbUJBQW9CLFNBQVEsZ0JBQVM7SUFTaEQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUF5QjtRQUNqRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBVFgsdUJBQWtCLEdBQUcsS0FBSyxDQUFDO1FBQ2xCLHdCQUFtQixHQUFHLElBQUksS0FBSyxFQUErQixDQUFDO1FBQy9ELHVCQUFrQixHQUFHLElBQUksS0FBSyxFQUFzQixDQUFDO1FBQ3JELHVCQUFrQixHQUFHLElBQUksS0FBSyxFQUFzQixDQUFDO1FBT3BFLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztRQUMzQixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7S0FDdEM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ksZUFBZSxDQUFDLEtBQWdCLEVBQUUsTUFBc0MsRUFBRSxHQUFHLE9BQWdDO1FBQ2xILE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBRTNDLGtGQUFrRjtRQUNsRixpREFBaUQ7UUFDakQsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ25ELE1BQU0sWUFBWSxHQUF3QjtZQUN4QyxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUM7WUFDZixNQUFNLEVBQUUsYUFBYSxDQUFDLE9B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LGFBQWEsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUMzRCxTQUFTLEdBQUcsSUFBSSxDQUFDO1NBQ2xCO0tBQ0Y7SUFFRCxPQUFPO1FBQ0wsR0FBRyxFQUFFO1lBQ0gsV0FBVyxFQUFFLGFBQWE7U0FDM0I7S0FDRixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGNkayBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IElCdWNrZXQsIEV2ZW50VHlwZSwgTm90aWZpY2F0aW9uS2V5RmlsdGVyLCBCdWNrZXQgfSBmcm9tICcuLi9idWNrZXQnO1xuaW1wb3J0IHsgQnVja2V0Tm90aWZpY2F0aW9uRGVzdGluYXRpb25UeXBlLCBJQnVja2V0Tm90aWZpY2F0aW9uRGVzdGluYXRpb24gfSBmcm9tICcuLi9kZXN0aW5hdGlvbic7XG5pbXBvcnQgeyBOb3RpZmljYXRpb25zUmVzb3VyY2VIYW5kbGVyIH0gZnJvbSAnLi9ub3RpZmljYXRpb25zLXJlc291cmNlLWhhbmRsZXInO1xuXG4vLyBrZWVwIHRoaXMgaW1wb3J0IHNlcGFyYXRlIGZyb20gb3RoZXIgaW1wb3J0cyB0byByZWR1Y2UgY2hhbmNlIGZvciBtZXJnZSBjb25mbGljdHMgd2l0aCB2Mi1tYWluXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZHVwbGljYXRlLWltcG9ydHMsIGltcG9ydC9vcmRlclxuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5cbmludGVyZmFjZSBOb3RpZmljYXRpb25zUHJvcHMge1xuICAvKipcbiAgICogVGhlIGJ1Y2tldCB0byBtYW5hZ2Ugbm90aWZpY2F0aW9ucyBmb3IuXG4gICAqL1xuICBidWNrZXQ6IElCdWNrZXQ7XG5cbiAgLyoqXG4gICAqIFRoZSByb2xlIHRvIGJlIHVzZWQgYnkgdGhlIGxhbWJkYSBoYW5kbGVyXG4gICAqL1xuICBoYW5kbGVyUm9sZT86IGlhbS5JUm9sZTtcbn1cblxuLyoqXG4gKiBBIGN1c3RvbSBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZSB0aGF0IHVwZGF0ZXMgYnVja2V0IG5vdGlmaWNhdGlvbnMgZm9yIGFcbiAqIGJ1Y2tldC4gVGhlIHJlYXNvbiB3ZSBuZWVkIGl0IGlzIGJlY2F1c2UgdGhlIEFXUzo6UzM6OkJ1Y2tldCBub3RpZmljYXRpb25cbiAqIGNvbmZpZ3VyYXRpb24gaXMgZGVmaW5lZCBvbiB0aGUgYnVja2V0IGl0c2VsZiwgd2hpY2ggbWFrZXMgaXQgaW1wb3NzaWJsZSB0b1xuICogcHJvdmlzaW9uIG5vdGlmaWNhdGlvbnMgYXQgdGhlIHNhbWUgdGltZSBhcyB0aGUgdGFyZ2V0IChzaW5jZVxuICogUHV0QnVja2V0Tm90aWZpY2F0aW9ucyB2YWxpZGF0ZXMgdGhlIHRhcmdldHMpLlxuICpcbiAqIFNpbmNlIG9ubHkgYSBzaW5nbGUgQnVja2V0Tm90aWZpY2F0aW9ucyByZXNvdXJjZSBpcyBhbGxvd2VkIGZvciBlYWNoIEJ1Y2tldCxcbiAqIHRoaXMgY29uc3RydWN0IGlzIG5vdCBleHBvcnRlZCBpbiB0aGUgcHVibGljIEFQSSBvZiB0aGlzIG1vZHVsZS4gSW5zdGVhZCwgaXRcbiAqIGlzIGNyZWF0ZWQganVzdC1pbi10aW1lIGJ5IGBzMy5CdWNrZXQub25FdmVudGAsIHNvIGEgMToxIHJlbGF0aW9uc2hpcCBpc1xuICogZW5zdXJlZC5cbiAqXG4gKiBAc2VlXG4gKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1zMy1idWNrZXQtbm90aWZpY2F0aW9uY29uZmlnLmh0bWxcbiAqL1xuZXhwb3J0IGNsYXNzIEJ1Y2tldE5vdGlmaWNhdGlvbnMgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwcml2YXRlIGV2ZW50QnJpZGdlRW5hYmxlZCA9IGZhbHNlO1xuICBwcml2YXRlIHJlYWRvbmx5IGxhbWJkYU5vdGlmaWNhdGlvbnMgPSBuZXcgQXJyYXk8TGFtYmRhRnVuY3Rpb25Db25maWd1cmF0aW9uPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHF1ZXVlTm90aWZpY2F0aW9ucyA9IG5ldyBBcnJheTxRdWV1ZUNvbmZpZ3VyYXRpb24+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgdG9waWNOb3RpZmljYXRpb25zID0gbmV3IEFycmF5PFRvcGljQ29uZmlndXJhdGlvbj4oKTtcbiAgcHJpdmF0ZSByZXNvdXJjZT86IGNkay5DZm5SZXNvdXJjZTtcbiAgcHJpdmF0ZSByZWFkb25seSBidWNrZXQ6IElCdWNrZXQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgaGFuZGxlclJvbGU/OiBpYW0uSVJvbGU7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE5vdGlmaWNhdGlvbnNQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG4gICAgdGhpcy5idWNrZXQgPSBwcm9wcy5idWNrZXQ7XG4gICAgdGhpcy5oYW5kbGVyUm9sZSA9IHByb3BzLmhhbmRsZXJSb2xlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBub3RpZmljYXRpb24gc3Vic2NyaXB0aW9uIGZvciB0aGlzIGJ1Y2tldC5cbiAgICogSWYgdGhpcyBpcyB0aGUgZmlyc3Qgbm90aWZpY2F0aW9uLCBhIEJ1Y2tldE5vdGlmaWNhdGlvbiByZXNvdXJjZSBpcyBhZGRlZCB0byB0aGUgc3RhY2suXG4gICAqXG4gICAqIEBwYXJhbSBldmVudCBUaGUgdHlwZSBvZiBldmVudFxuICAgKiBAcGFyYW0gdGFyZ2V0IFRoZSB0YXJnZXQgY29uc3RydWN0XG4gICAqIEBwYXJhbSBmaWx0ZXJzIEEgc2V0IG9mIFMzIGtleSBmaWx0ZXJzXG4gICAqL1xuICBwdWJsaWMgYWRkTm90aWZpY2F0aW9uKGV2ZW50OiBFdmVudFR5cGUsIHRhcmdldDogSUJ1Y2tldE5vdGlmaWNhdGlvbkRlc3RpbmF0aW9uLCAuLi5maWx0ZXJzOiBOb3RpZmljYXRpb25LZXlGaWx0ZXJbXSkge1xuICAgIGNvbnN0IHJlc291cmNlID0gdGhpcy5jcmVhdGVSZXNvdXJjZU9uY2UoKTtcblxuICAgIC8vIHJlc29sdmUgdGFyZ2V0LiB0aGlzIGFsc28gcHJvdmlkZXMgYW4gb3Bwb3J0dW5pdHkgZm9yIHRoZSB0YXJnZXQgdG8gZS5nLiB1cGRhdGVcbiAgICAvLyBwb2xpY2llcyB0byBhbGxvdyB0aGlzIG5vdGlmaWNhdGlvbiB0byBoYXBwZW4uXG4gICAgY29uc3QgdGFyZ2V0UHJvcHMgPSB0YXJnZXQuYmluZCh0aGlzLCB0aGlzLmJ1Y2tldCk7XG4gICAgY29uc3QgY29tbW9uQ29uZmlnOiBDb21tb25Db25maWd1cmF0aW9uID0ge1xuICAgICAgRXZlbnRzOiBbZXZlbnRdLFxuICAgICAgRmlsdGVyOiByZW5kZXJGaWx0ZXJzKGZpbHRlcnMpLFxuICAgIH07XG5cbiAgICAvLyBpZiB0aGUgdGFyZ2V0IHNwZWNpZmllcyBhbnkgZGVwZW5kZW5jaWVzLCBhZGQgdGhlbSB0byB0aGUgY3VzdG9tIHJlc291cmNlLlxuICAgIC8vIGZvciBleGFtcGxlLCB0aGUgU05TIHRvcGljIHBvbGljeSBtdXN0IGJlIGNyZWF0ZWQgL2JlZm9yZS8gdGhlIG5vdGlmaWNhdGlvbiByZXNvdXJjZS5cbiAgICAvLyBvdGhlcndpc2UsIFMzIHdvbid0IGJlIGFibGUgdG8gY29uZmlybSB0aGUgc3Vic2NyaXB0aW9uLlxuICAgIGlmICh0YXJnZXRQcm9wcy5kZXBlbmRlbmNpZXMpIHtcbiAgICAgIHJlc291cmNlLm5vZGUuYWRkRGVwZW5kZW5jeSguLi50YXJnZXRQcm9wcy5kZXBlbmRlbmNpZXMpO1xuICAgIH1cblxuICAgIC8vIGJhc2VkIG9uIHRoZSB0YXJnZXQgdHlwZSwgYWRkIHRoZSB0aGUgY29ycmVjdCBjb25maWd1cmF0aW9ucyBhcnJheVxuICAgIHN3aXRjaCAodGFyZ2V0UHJvcHMudHlwZSkge1xuICAgICAgY2FzZSBCdWNrZXROb3RpZmljYXRpb25EZXN0aW5hdGlvblR5cGUuTEFNQkRBOlxuICAgICAgICB0aGlzLmxhbWJkYU5vdGlmaWNhdGlvbnMucHVzaCh7IC4uLmNvbW1vbkNvbmZpZywgTGFtYmRhRnVuY3Rpb25Bcm46IHRhcmdldFByb3BzLmFybiB9KTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgQnVja2V0Tm90aWZpY2F0aW9uRGVzdGluYXRpb25UeXBlLlFVRVVFOlxuICAgICAgICB0aGlzLnF1ZXVlTm90aWZpY2F0aW9ucy5wdXNoKHsgLi4uY29tbW9uQ29uZmlnLCBRdWV1ZUFybjogdGFyZ2V0UHJvcHMuYXJuIH0pO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBCdWNrZXROb3RpZmljYXRpb25EZXN0aW5hdGlvblR5cGUuVE9QSUM6XG4gICAgICAgIHRoaXMudG9waWNOb3RpZmljYXRpb25zLnB1c2goeyAuLi5jb21tb25Db25maWcsIFRvcGljQXJuOiB0YXJnZXRQcm9wcy5hcm4gfSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIG5vdGlmaWNhdGlvbiB0YXJnZXQgdHlwZTonICsgQnVja2V0Tm90aWZpY2F0aW9uRGVzdGluYXRpb25UeXBlW3RhcmdldFByb3BzLnR5cGVdKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZW5hYmxlRXZlbnRCcmlkZ2VOb3RpZmljYXRpb24oKSB7XG4gICAgdGhpcy5jcmVhdGVSZXNvdXJjZU9uY2UoKTtcbiAgICB0aGlzLmV2ZW50QnJpZGdlRW5hYmxlZCA9IHRydWU7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlck5vdGlmaWNhdGlvbkNvbmZpZ3VyYXRpb24oKTogTm90aWZpY2F0aW9uQ29uZmlndXJhdGlvbiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIEV2ZW50QnJpZGdlQ29uZmlndXJhdGlvbjogdGhpcy5ldmVudEJyaWRnZUVuYWJsZWQgPyB7fSA6IHVuZGVmaW5lZCxcbiAgICAgIExhbWJkYUZ1bmN0aW9uQ29uZmlndXJhdGlvbnM6IHRoaXMubGFtYmRhTm90aWZpY2F0aW9ucy5sZW5ndGggPiAwID8gdGhpcy5sYW1iZGFOb3RpZmljYXRpb25zIDogdW5kZWZpbmVkLFxuICAgICAgUXVldWVDb25maWd1cmF0aW9uczogdGhpcy5xdWV1ZU5vdGlmaWNhdGlvbnMubGVuZ3RoID4gMCA/IHRoaXMucXVldWVOb3RpZmljYXRpb25zIDogdW5kZWZpbmVkLFxuICAgICAgVG9waWNDb25maWd1cmF0aW9uczogdGhpcy50b3BpY05vdGlmaWNhdGlvbnMubGVuZ3RoID4gMCA/IHRoaXMudG9waWNOb3RpZmljYXRpb25zIDogdW5kZWZpbmVkLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRGVmaW5lcyB0aGUgYnVja2V0IG5vdGlmaWNhdGlvbnMgcmVzb3VyY2VzIGluIHRoZSBzdGFjayBvbmx5IG9uY2UuXG4gICAqIFRoaXMgaXMgY2FsbGVkIGxhemlseSBhcyB3ZSBhZGQgbm90aWZpY2F0aW9ucywgc28gdGhhdCBpZiBub3RpZmljYXRpb25zIGFyZSBub3QgYWRkZWQsXG4gICAqIHRoZXJlIGlzIG5vIG5vdGlmaWNhdGlvbnMgcmVzb3VyY2UuXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZVJlc291cmNlT25jZSgpIHtcbiAgICBpZiAoIXRoaXMucmVzb3VyY2UpIHtcbiAgICAgIGNvbnN0IGhhbmRsZXIgPSBOb3RpZmljYXRpb25zUmVzb3VyY2VIYW5kbGVyLnNpbmdsZXRvbih0aGlzLCB7XG4gICAgICAgIHJvbGU6IHRoaXMuaGFuZGxlclJvbGUsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgbWFuYWdlZCA9IHRoaXMuYnVja2V0IGluc3RhbmNlb2YgQnVja2V0O1xuXG4gICAgICBpZiAoIW1hbmFnZWQpIHtcbiAgICAgICAgaGFuZGxlci5hZGRUb1JvbGVQb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFsnczM6R2V0QnVja2V0Tm90aWZpY2F0aW9uJ10sXG4gICAgICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICAgICAgfSkpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnJlc291cmNlID0gbmV3IGNkay5DZm5SZXNvdXJjZSh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICAgIHR5cGU6ICdDdXN0b206OlMzQnVja2V0Tm90aWZpY2F0aW9ucycsXG4gICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICBTZXJ2aWNlVG9rZW46IGhhbmRsZXIuZnVuY3Rpb25Bcm4sXG4gICAgICAgICAgQnVja2V0TmFtZTogdGhpcy5idWNrZXQuYnVja2V0TmFtZSxcbiAgICAgICAgICBOb3RpZmljYXRpb25Db25maWd1cmF0aW9uOiBjZGsuTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLnJlbmRlck5vdGlmaWNhdGlvbkNvbmZpZ3VyYXRpb24oKSB9KSxcbiAgICAgICAgICBNYW5hZ2VkOiBtYW5hZ2VkLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucmVzb3VyY2U7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyRmlsdGVycyhmaWx0ZXJzPzogTm90aWZpY2F0aW9uS2V5RmlsdGVyW10pOiBGaWx0ZXIgfCB1bmRlZmluZWQge1xuICBpZiAoIWZpbHRlcnMgfHwgZmlsdGVycy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgcmVuZGVyZWRSdWxlcyA9IG5ldyBBcnJheTxGaWx0ZXJSdWxlPigpO1xuICBsZXQgaGFzUHJlZml4ID0gZmFsc2U7XG4gIGxldCBoYXNTdWZmaXggPSBmYWxzZTtcblxuICBmb3IgKGNvbnN0IHJ1bGUgb2YgZmlsdGVycykge1xuICAgIGlmICghcnVsZS5zdWZmaXggJiYgIXJ1bGUucHJlZml4KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdGlmaWNhdGlvbktleUZpbHRlciBtdXN0IHNwZWNpZnkgYHByZWZpeGAgYW5kL29yIGBzdWZmaXhgJyk7XG4gICAgfVxuXG4gICAgaWYgKHJ1bGUuc3VmZml4KSB7XG4gICAgICBpZiAoaGFzU3VmZml4KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHNwZWNpZnkgbW9yZSB0aGFuIG9uZSBzdWZmaXggcnVsZSBpbiBhIGZpbHRlci4nKTtcbiAgICAgIH1cbiAgICAgIHJlbmRlcmVkUnVsZXMucHVzaCh7IE5hbWU6ICdzdWZmaXgnLCBWYWx1ZTogcnVsZS5zdWZmaXggfSk7XG4gICAgICBoYXNTdWZmaXggPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChydWxlLnByZWZpeCkge1xuICAgICAgaWYgKGhhc1ByZWZpeCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBzcGVjaWZ5IG1vcmUgdGhhbiBvbmUgcHJlZml4IHJ1bGUgaW4gYSBmaWx0ZXIuJyk7XG4gICAgICB9XG4gICAgICByZW5kZXJlZFJ1bGVzLnB1c2goeyBOYW1lOiAncHJlZml4JywgVmFsdWU6IHJ1bGUucHJlZml4IH0pO1xuICAgICAgaGFzUHJlZml4ID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIEtleToge1xuICAgICAgRmlsdGVyUnVsZXM6IHJlbmRlcmVkUnVsZXMsXG4gICAgfSxcbiAgfTtcbn1cblxuaW50ZXJmYWNlIE5vdGlmaWNhdGlvbkNvbmZpZ3VyYXRpb24ge1xuICBFdmVudEJyaWRnZUNvbmZpZ3VyYXRpb24/OiBFdmVudEJyaWRnZUNvbmZpZ3VyYXRpb247XG4gIExhbWJkYUZ1bmN0aW9uQ29uZmlndXJhdGlvbnM/OiBMYW1iZGFGdW5jdGlvbkNvbmZpZ3VyYXRpb25bXTtcbiAgUXVldWVDb25maWd1cmF0aW9ucz86IFF1ZXVlQ29uZmlndXJhdGlvbltdO1xuICBUb3BpY0NvbmZpZ3VyYXRpb25zPzogVG9waWNDb25maWd1cmF0aW9uW107XG59XG5cbmludGVyZmFjZSBDb21tb25Db25maWd1cmF0aW9uIHtcbiAgSWQ/OiBzdHJpbmc7XG4gIEV2ZW50czogRXZlbnRUeXBlW107XG4gIEZpbHRlcj86IEZpbHRlclxufVxuXG5pbnRlcmZhY2UgRXZlbnRCcmlkZ2VDb25maWd1cmF0aW9uIHsgfVxuXG5pbnRlcmZhY2UgTGFtYmRhRnVuY3Rpb25Db25maWd1cmF0aW9uIGV4dGVuZHMgQ29tbW9uQ29uZmlndXJhdGlvbiB7XG4gIExhbWJkYUZ1bmN0aW9uQXJuOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBRdWV1ZUNvbmZpZ3VyYXRpb24gZXh0ZW5kcyBDb21tb25Db25maWd1cmF0aW9uIHtcbiAgUXVldWVBcm46IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIFRvcGljQ29uZmlndXJhdGlvbiBleHRlbmRzIENvbW1vbkNvbmZpZ3VyYXRpb24ge1xuICBUb3BpY0Fybjogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgRmlsdGVyUnVsZSB7XG4gIE5hbWU6ICdwcmVmaXgnIHwgJ3N1ZmZpeCc7XG4gIFZhbHVlOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBGaWx0ZXIge1xuICBLZXk6IHsgRmlsdGVyUnVsZXM6IEZpbHRlclJ1bGVbXSB9XG59XG4iXX0=