@aws-cdk/aws-s3
Version:
The CDK Construct Library for AWS::S3
150 lines • 21.8 kB
JavaScript
"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=