@renovosolutions/cdk-library-crowdstrike-ingestion
Version:
A CDK library to ease repetetive construct creation for CrowdStrike data ingestion
157 lines • 25.6 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CrowdStrikeBucket = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
;
/**
* A construct that creates an S3 bucket for CrowdStrike data ingestion,
* along with an SQS queue for notifications, an IAM role for access,
* and optionally a KMS key for encryption.
*/
class CrowdStrikeBucket extends aws_cdk_lib_1.aws_s3.Bucket {
/**
* Constructs a new CrowdStrikeBucket.
*
* @param scope The scope in which this construct is defined.
* @param id The scoped construct ID.
* @param props The properties for the bucket, queue, role, and optional KMS key.
*/
constructor(scope, id, props) {
super(scope, id, {
encryption: aws_cdk_lib_1.aws_s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: aws_cdk_lib_1.aws_s3.BlockPublicAccess.BLOCK_ALL,
enforceSSL: true,
versioned: true,
removalPolicy: aws_cdk_lib_1.RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE,
...props,
});
/**
* If we have an orgId, grant bucket write access to all accounts in the organization.
* This is useful for allowing multiple accounts in an organization to write to the same bucket.
*/
if (props.orgId) {
this.grantWrite(new aws_cdk_lib_1.aws_iam.OrganizationPrincipal(props.orgId));
}
// If a logging bucket source name is provided, add a policy to allow that bucket to write logs to this bucket.
if (props.loggingBucketSourceName) {
this.addToResourcePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW,
actions: ['s3:PutObject'],
resources: [this.arnForObjects('*')],
principals: [new aws_cdk_lib_1.aws_iam.ServicePrincipal('logging.s3.amazonaws.com')],
conditions: {
ArnLike: {
'aws:SourceArn': `arn:aws:s3:::${props.loggingBucketSourceName}`,
},
StringEquals: {
'aws:SourceAccount': aws_cdk_lib_1.Stack.of(this).account,
},
},
}));
}
/**
* Create an SQS queue for notifications.
* If a queueName is provided, use it; otherwise, generate a default name based on the bucket name.
*/
this.queue = new aws_cdk_lib_1.aws_sqs.Queue(this, 'Queue', {
queueName: props.queueProps?.queueName || `${this.bucketName}-queue`,
enforceSSL: true,
deadLetterQueue: {
maxReceiveCount: 5,
queue: new aws_cdk_lib_1.aws_sqs.Queue(this, 'DLQ', {
queueName: `${this.bucketName}-dlq`,
enforceSSL: true,
}),
},
...props.queueProps,
});
// Add a notification for bucket object creation events to the SQS queue.
this.addEventNotification(aws_cdk_lib_1.aws_s3.EventType.OBJECT_CREATED, new aws_cdk_lib_1.aws_s3_notifications.SqsDestination(this.queue));
/**
* Determine the principal for CrowdStrike.
* If roleProps are provided, use the assumedBy property from there.
* Otherwise, create a CrowdStrike principal using the role ARN and external ID from SSM parameters.
*/
let crowdStrikePrincipal;
if (props.roleProps) {
crowdStrikePrincipal = props.roleProps.assumedBy;
}
else if (props.crowdStrikeRoleArn && props.crowdStrikeExternalIdParameterArn) {
const crowdStrikeRoleArn = props.crowdStrikeRoleArn;
const crowdStrikeExternalId = aws_cdk_lib_1.aws_ssm.StringParameter.fromStringParameterArn(this, 'CrowdStrikeExternalIdParam', props.crowdStrikeExternalIdParameterArn).stringValue;
crowdStrikePrincipal = new aws_cdk_lib_1.aws_iam.PrincipalWithConditions(new aws_cdk_lib_1.aws_iam.ArnPrincipal(crowdStrikeRoleArn), {
StringEquals: {
'sts:ExternalId': crowdStrikeExternalId,
},
});
}
else {
aws_cdk_lib_1.Annotations.of(this).addError('Either roleProps or both crowdStrikeRoleParameterArn and crowdStrikeExternalIdParameterArn must be provided.');
// This will not be used because of the error, but we need to initialize it to satisfy the type.
crowdStrikePrincipal = new aws_cdk_lib_1.aws_iam.AnyPrincipal();
}
/**
* Create an IAM role for CrowdStrike to assume, granting it access to the resources created in this construct.
* The role name can be provided in the props, or a default name will be generated based on the bucket name.
*/
this.role = new aws_cdk_lib_1.aws_iam.Role(this, 'Role', {
roleName: props.roleProps?.roleName || `${this.bucketName}-role`,
assumedBy: crowdStrikePrincipal,
...props.roleProps,
});
// Grant the role permissions to read from the bucket and consume messages from the SQS queue.
this.grantRead(this.role);
this.queue.grantConsumeMessages(this.role);
// If createKmsKey is true, create a KMS key for the data.
if (props.createKmsKey) {
this.key = new aws_cdk_lib_1.aws_kms.Key(this, 'Key', {
alias: `alias/${this.bucketName}`,
removalPolicy: aws_cdk_lib_1.RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE,
enableKeyRotation: false,
multiRegion: true,
description: `KMS Key for CrowdStrike ingestion bucket ${this.bucketName}`,
...props.keyProps,
});
// Grant the role permissions to use the KMS key for decryption.
this.key.grantDecrypt(this.role);
/**
* If an orgId is provided, grant permissions to use the KMS key
* for encryption and decryption for all accounts in the organization.
*/
if (props.orgId) {
this.key.grantEncryptDecrypt(new aws_cdk_lib_1.aws_iam.OrganizationPrincipal(props.orgId));
}
// Output the KMS key ARN for reference.
new aws_cdk_lib_1.CfnOutput(this, 'KmsKeyArn', {
value: this.key.keyArn,
description: 'The ARN of the KMS key for CrowdStrike ingestion',
});
}
/**
* Output the bucket name, bucket ARN, queue name, and role name.
* You will need these values to configure CrowdStrike connectors.
*/
new aws_cdk_lib_1.CfnOutput(this, 'BucketName', {
value: this.bucketName,
description: 'The Name of the S3 bucket for CrowdStrike ingestion',
});
new aws_cdk_lib_1.CfnOutput(this, 'BucketArn', {
value: this.bucketArn,
description: 'The ARN of the S3 bucket for CrowdStrike ingestion',
});
new aws_cdk_lib_1.CfnOutput(this, 'QueueName', {
value: this.queue.queueName,
description: 'The Name of the SQS queue for CrowdStrike ingestion',
});
new aws_cdk_lib_1.CfnOutput(this, 'RoleName', {
value: this.role.roleName,
description: 'The Name of the IAM role for CrowdStrike ingestion',
});
}
}
exports.CrowdStrikeBucket = CrowdStrikeBucket;
_a = JSII_RTTI_SYMBOL_1;
CrowdStrikeBucket[_a] = { fqn: "@renovosolutions/cdk-library-crowdstrike-ingestion.CrowdStrikeBucket", version: "0.0.3" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVja2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2J1Y2tldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQVdxQjtBQTZEcEIsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxNQUFhLGlCQUFrQixTQUFRLG9CQUFFLENBQUMsTUFBTTtJQWtCOUM7Ozs7OztPQU1HO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUE2QjtRQUNyRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLFVBQVUsRUFBRSxvQkFBRSxDQUFDLGdCQUFnQixDQUFDLFVBQVU7WUFDMUMsaUJBQWlCLEVBQUUsb0JBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTO1lBQ2pELFVBQVUsRUFBRSxJQUFJO1lBQ2hCLFNBQVMsRUFBRSxJQUFJO1lBQ2YsYUFBYSxFQUFFLDJCQUFhLENBQUMsMEJBQTBCO1lBQ3ZELEdBQUcsS0FBSztTQUNULENBQUMsQ0FBQztRQUVIOzs7V0FHRztRQUNILElBQUksS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2hCLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxxQkFBRyxDQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQzlELENBQUM7UUFFRCwrR0FBK0c7UUFDL0csSUFBSSxLQUFLLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztZQUNsQyxJQUFJLENBQUMsbUJBQW1CLENBQ3RCLElBQUkscUJBQUcsQ0FBQyxlQUFlLENBQUM7Z0JBQ3RCLE1BQU0sRUFBRSxxQkFBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLO2dCQUN4QixPQUFPLEVBQUUsQ0FBQyxjQUFjLENBQUM7Z0JBQ3pCLFNBQVMsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ3BDLFVBQVUsRUFBRSxDQUFDLElBQUkscUJBQUcsQ0FBQyxnQkFBZ0IsQ0FBQywwQkFB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QUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRTtZQUMvQixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTO1lBQzNCLFdBQVcsRUFBRSxxREFBcUQ7U0FDbkUsQ0FBQyxDQUFDO1FBRUgsSUFBSSx1QkFBUyxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDOUIsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUTtZQUN6QixXQUFXLEVBQUUsb0RBQW9EO1NBQ2xFLENBQUMsQ0FBQztJQUNMLENBQUM7O0FBdExILDhDQXVMQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFubm90YXRpb25zLFxuICBDZm5PdXRwdXQsXG4gIFJlbW92YWxQb2xpY3ksXG4gIFN0YWNrLFxuICBhd3NfaWFtIGFzIGlhbSxcbiAgYXdzX2ttcyBhcyBrbXMsXG4gIGF3c19zMyBhcyBzMyxcbiAgYXdzX3MzX25vdGlmaWNhdGlvbnMgYXMgczNuLFxuICBhd3Nfc3FzIGFzIHNxcyxcbiAgYXdzX3NzbSBhcyBzc20sXG59IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIHRoZSBDcm93ZFN0cmlrZUJ1Y2tldCBjb25zdHJ1Y3QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3Jvd2RTdHJpa2VCdWNrZXRQcm9wcyBleHRlbmRzIHMzLkJ1Y2tldFByb3BzIHtcbiAgLyoqXG4gICAqIFByb3BlcnRpZXMgZm9yIHRoZSBTUVMgcXVldWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZW5mb3JjZVNTTDogdHJ1ZSwgZGVhZExldHRlclF1ZXVlOiB7IG1heFJlY2VpdmVDb3VudDogNSwgcXVldWU6IG5ldyBzcXMuUXVldWUodGhpcywgJ0RMUScsIHsgcXVldWVOYW1lOiBgJHt0aGlzLmJ1Y2tldE5hbWV9LWRscWAsIGVuZm9yY2VTU0w6IHRydWUsIH0pLCB9LFxuICAgKi9cbiAgcmVhZG9ubHkgcXVldWVQcm9wcz86IHNxcy5RdWV1ZVByb3BzO1xuICAvKipcbiAgICogV2hldGhlciB0byBjcmVhdGUgYSBLTVMga2V5IGZvciB0aGUgYnVja2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGZhbHNlXG4gICAqL1xuICByZWFkb25seSBjcmVhdGVLbXNLZXk/OiBib29sZWFuO1xuICAvKipcbiAgICogUHJvcGVydGllcyBmb3IgdGhlIEtNUyBrZXkuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5SRVRBSU5fT05fVVBEQVRFX09SX0RFTEVURSwgZW5hYmxlS2V5Um90YXRpb246IGZhbHNlLCBtdWx0aVJlZ2lvbjogdHJ1ZSwgZGVzY3JpcHRpb246IGBLTVMgS2V5IGZvciBDcm93ZFN0cmlrZSBpbmdlc3Rpb24gYnVja2V0ICR7dGhpcy5idWNrZXROYW1lfWAsXG4gICAqL1xuICByZWFkb25seSBrZXlQcm9wcz86IGttcy5LZXlQcm9wcztcbiAgLyoqXG4gICAqIFByb3BlcnRpZXMgZm9yIHRoZSBJQU0gcm9sZS5cbiAgICpcbiAgICogSWYgeW91IHByb3ZpZGUgdGhpcywgeW91IG11c3QgcHJvdmlkZSB0aGUgcm9sZVByb3BzLmFzc3VtZWRCeSBwcm9wZXJ0eSxcbiAgICogYW5kIHlvdSBkb24ndCBuZWVkIHRvIHByb3ZpZGUgdGhlIGNyb3dkU3RyaWtlUm9sZVBhcmFtZXRlckFybiBhbmQgY3Jvd2RTdHJpa2VFeHRlcm5hbElkUGFyYW1ldGVyQXJuLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmUgZXhjZXB0IGZvciB0aGUgYXNzdW1lZEJ5IHByb3BlcnR5IHdoaWNoIGlzIHNldCB0byBhIENyb3dkU3RyaWtlIHByaW5jaXBhbC5cbiAgICovXG4gIHJlYWRvbmx5IHJvbGVQcm9wcz86IGlhbS5Sb2xlUHJvcHM7XG4gIC8qKlxuICAgKiBUaGUgQ3Jvd2RTdHJpa2Ugcm9sZSBBUk4uXG4gICAqXG4gICAqIFJlcXVpcmVkIHVubGVzcyB0aGUgcm9sZSBwcmluY2lwYWwgaXMgcHJvdmlkZWQgZGlyZWN0bHkgaW4gdGhlIHJvbGVQcm9wcy5cbiAgICovXG4gIHJlYWRvbmx5IGNyb3dkU3RyaWtlUm9sZUFybj86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIFNTTSBwYXJhbWV0ZXIgY29udGFpbmluZyB0aGUgQ3Jvd2RTdHJpa2UgZXh0ZXJuYWwgSUQuXG4gICAqXG4gICAqIFJlcXVpcmVkIHVubGVzcyB0aGUgcm9sZSBwcmluY2lwYWwgaXMgcHJvdmlkZWQgZGlyZWN0bHkgaW4gdGhlIHJvbGVQcm9wcy5cbiAgICovXG4gIHJlYWRvbmx5IGNyb3dkU3RyaWtlRXh0ZXJuYWxJZFBhcmFtZXRlckFybj86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBvcmdhbml6YXRpb24gSUQuXG4gICAqIElmIHByb3ZpZGVkLCB0aGUgYnVja2V0IHdpbGwgYWxsb3cgd3JpdGUgYWNjZXNzIHRvIGFsbCBhY2NvdW50cyBpbiB0aGUgb3JnYW5pemF0aW9uLlxuICAgKiBJZiB0aGVyZSBpcyBhIEtNUyBrZXksIGl0IHdpbGwgYWxzbyBhbGxvdyBlbmNyeXB0L2RlY3J5cHQgYWNjZXNzIHRvIHRoZSBvcmdhbml6YXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgb3JnSWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgUzMgYnVja2V0IHRoYXQgd2lsbCBiZSBzZW5kaW5nIFMzIGFjY2VzcyBsb2dzIHRvIHRoaXMgYnVja2V0LlxuICAgKiBUaGlzIGlzIHVzZWQgdG8gY29uZmlndXJlIHRoZSBidWNrZXQgcG9saWN5IHRvIGFsbG93IGxvZ2dpbmcgZnJvbSB0aGF0IGJ1Y2tldC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICByZWFkb25seSBsb2dnaW5nQnVja2V0U291cmNlTmFtZT86IHN0cmluZztcbn07XG5cbi8qKlxuICogQSBjb25zdHJ1Y3QgdGhhdCBjcmVhdGVzIGFuIFMzIGJ1Y2tldCBmb3IgQ3Jvd2RTdHJpa2UgZGF0YSBpbmdlc3Rpb24sXG4gKiBhbG9uZyB3aXRoIGFuIFNRUyBxdWV1ZSBmb3Igbm90aWZpY2F0aW9ucywgYW4gSUFNIHJvbGUgZm9yIGFjY2VzcyxcbiAqIGFuZCBvcHRpb25hbGx5IGEgS01TIGtleSBmb3IgZW5jcnlwdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIENyb3dkU3RyaWtlQnVja2V0IGV4dGVuZHMgczMuQnVja2V0IHtcbiAgLyoqXG4gICAqIFRoZSBTUVMgcXVldWUgdGhhdCByZWNlaXZlcyBub3RpZmljYXRpb25zIGZvciBuZXcgb2JqZWN0cyBpbiB0aGUgYnVja2V0LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHF1ZXVlOiBzcXMuUXVldWU7XG4gIC8qKlxuICAgKiBUaGUgS01TIGtleSB1c2VkIGZvciBlbmNyeXB0aW5nIGRhdGEgaW4gdGhlIGJ1Y2tldCwgaWYgY3JlYXRlZC5cbiAgICogVGhpcyB3aWxsIGJlIHVuZGVmaW5lZCBpZiBjcmVhdGVLbXNLZXkgaXMgZmFsc2UuXG4gICAqXG4gICAqIE5vdGUgdGhhdCB0aGUgYnVja2V0IHdpbGwgc3RpbGwgYmUgY3JlYXRlZCB3aXRoIFMzLW1hbmFnZWQgZW5jcnlwdGlvblxuICAgKiBldmVuIGlmIHRoaXMgaXMgcHJvdmlkZWQuIFRoZSBrZXkgaXMgdXNlZCBieSB0aGUgc2VydmljZSB3cml0aW5nIHRvIHRoZSBidWNrZXQuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkga2V5Pzoga21zLktleTtcbiAgLyoqXG4gICAqIFRoZSBJQU0gcm9sZSB0aGF0IENyb3dkU3RyaWtlIHdpbGwgYXNzdW1lIHRvIGFjY2VzcyB0aGUgZGF0YSBpbiB0aGUgYnVja2V0LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHJvbGU6IGlhbS5Sb2xlO1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgbmV3IENyb3dkU3RyaWtlQnVja2V0LlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgVGhlIHNjb3BlIGluIHdoaWNoIHRoaXMgY29uc3RydWN0IGlzIGRlZmluZWQuXG4gICAqIEBwYXJhbSBpZCBUaGUgc2NvcGVkIGNvbnN0cnVjdCBJRC5cbiAgICogQHBhcmFtIHByb3BzIFRoZSBwcm9wZXJ0aWVzIGZvciB0aGUgYnVja2V0LCBxdWV1ZSwgcm9sZSwgYW5kIG9wdGlvbmFsIEtNUyBrZXkuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQ3Jvd2RTdHJpa2VCdWNrZXRQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge1xuICAgICAgZW5jcnlwdGlvbjogczMuQnVja2V0RW5jcnlwdGlvbi5TM19NQU5BR0VELFxuICAgICAgYmxvY2tQdWJsaWNBY2Nlc3M6IHMzLkJsb2NrUHVibGljQWNjZXNzLkJMT0NLX0FMTCxcbiAgICAgIGVuZm9yY2VTU0w6IHRydWUsXG4gICAgICB2ZXJzaW9uZWQ6IHRydWUsXG4gICAgICByZW1vdmFsUG9saWN5OiBSZW1vdmFsUG9saWN5LlJFVEFJTl9PTl9VUERBVEVfT1JfREVMRVRFLFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBJZiB3ZSBoYXZlIGFuIG9yZ0lkLCBncmFudCBidWNrZXQgd3JpdGUgYWNjZXNzIHRvIGFsbCBhY2NvdW50cyBpbiB0aGUgb3JnYW5pemF0aW9uLlxuICAgICAqIFRoaXMgaXMgdXNlZnVsIGZvciBhbGxvd2luZyBtdWx0aXBsZSBhY2NvdW50cyBpbiBhbiBvcmdhbml6YXRpb24gdG8gd3JpdGUgdG8gdGhlIHNhbWUgYnVja2V0LlxuICAgICAqL1xuICAgIGlmIChwcm9wcy5vcmdJZCkge1xuICAgICAgdGhpcy5ncmFudFdyaXRlKG5ldyBpYW0uT3JnYW5pemF0aW9uUHJpbmNpcGFsKHByb3BzLm9yZ0lkKSk7XG4gICAgfVxuXG4gICAgLy8gSWYgYSBsb2dnaW5nIGJ1Y2tldCBzb3VyY2UgbmFtZSBpcyBwcm92aWRlZCwgYWRkIGEgcG9saWN5IHRvIGFsbG93IHRoYXQgYnVja2V0IHRvIHdyaXRlIGxvZ3MgdG8gdGhpcyBidWNrZXQuXG4gICAgaWYgKHByb3BzLmxvZ2dpbmdCdWNrZXRTb3VyY2VOYW1lKSB7XG4gICAgICB0aGlzLmFkZFRvUmVzb3VyY2VQb2xpY3koXG4gICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgICAgYWN0aW9uczogWydzMzpQdXRPYmplY3QnXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFt0aGlzLmFybkZvck9iamVjdHMoJyonKV0sXG4gICAgICAgICAgcHJpbmNpcGFsczogW25ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnbG9nZ2luZy5zMy5hbWF6b25hd3MuY29tJyldLFxuICAgICAgICAgIGNvbmRpdGlvbnM6IHtcbiAgICAgICAgICAgIEFybkxpa2U6IHtcbiAgICAgICAgICAgICAgJ2F3czpTb3VyY2VBcm4nOiBgYXJuOmF3czpzMzo6OiR7cHJvcHMubG9nZ2luZ0J1Y2tldFNvdXJjZU5hbWV9YCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBTdHJpbmdFcXVhbHM6IHtcbiAgICAgICAgICAgICAgJ2F3czpTb3VyY2VBY2NvdW50JzogU3RhY2sub2YodGhpcykuYWNjb3VudCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhbiBTUVMgcXVldWUgZm9yIG5vdGlmaWNhdGlvbnMuXG4gICAgICogSWYgYSBxdWV1ZU5hbWUgaXMgcHJvdmlkZWQsIHVzZSBpdDsgb3RoZXJ3aXNlLCBnZW5lcmF0ZSBhIGRlZmF1bHQgbmFtZSBiYXNlZCBvbiB0aGUgYnVja2V0IG5hbWUuXG4gICAgICovXG4gICAgdGhpcy5xdWV1ZSA9IG5ldyBzcXMuUXVldWUodGhpcywgJ1F1ZXVlJywge1xuICAgICAgcXVldWVOYW1lOiBwcm9wcy5xdWV1ZVByb3BzPy5xdWV1ZU5hbWUgfHwgYCR7dGhpcy5idWNrZXROYW1lfS1xdWV1ZWAsXG4gICAgICBlbmZvcmNlU1NMOiB0cnVlLFxuICAgICAgZGVhZExldHRlclF1ZXVlOiB7XG4gICAgICAgIG1heFJlY2VpdmVDb3VudDogNSxcbiAgICAgICAgcXVldWU6IG5ldyBzcXMuUXVldWUodGhpcywgJ0RMUScsIHtcbiAgICAgICAgICBxdWV1ZU5hbWU6IGAke3RoaXMuYnVja2V0TmFtZX0tZGxxYCxcbiAgICAgICAgICBlbmZvcmNlU1NMOiB0cnVlLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgICAuLi5wcm9wcy5xdWV1ZVByb3BzLFxuICAgIH0pO1xuXG4gICAgLy8gQWRkIGEgbm90aWZpY2F0aW9uIGZvciBidWNrZXQgb2JqZWN0IGNyZWF0aW9uIGV2ZW50cyB0byB0aGUgU1FTIHF1ZXVlLlxuICAgIHRoaXMuYWRkRXZlbnROb3RpZmljYXRpb24oXG4gICAgICBzMy5FdmVudFR5cGUuT0JKRUNUX0NSRUFURUQsXG4gICAgICBuZXcgczNuLlNxc0Rlc3RpbmF0aW9uKHRoaXMucXVldWUpLFxuICAgICk7XG5cbiAgICAvKipcbiAgICAgKiBEZXRlcm1pbmUgdGhlIHByaW5jaXBhbCBmb3IgQ3Jvd2RTdHJpa2UuXG4gICAgICogSWYgcm9sZVByb3BzIGFyZSBwcm92aWRlZCwgdXNlIHRoZSBhc3N1bWVkQnkgcHJvcGVydHkgZnJvbSB0aGVyZS5cbiAgICAgKiBPdGhlcndpc2UsIGNyZWF0ZSBhIENyb3dkU3RyaWtlIHByaW5jaXBhbCB1c2luZyB0aGUgcm9sZSBBUk4gYW5kIGV4dGVybmFsIElEIGZyb20gU1NNIHBhcmFtZXRlcnMuXG4gICAgICovXG4gICAgbGV0IGNyb3dkU3RyaWtlUHJpbmNpcGFsOiBpYW0uSVByaW5jaXBhbDtcbiAgICBpZiAocHJvcHMucm9sZVByb3BzKSB7XG4gICAgICBjcm93ZFN0cmlrZVByaW5jaXBhbCA9IHByb3BzLnJvbGVQcm9wcy5hc3N1bWVkQnk7XG4gICAgfSBlbHNlIGlmIChwcm9wcy5jcm93ZFN0cmlrZVJvbGVBcm4gJiYgcHJvcHMuY3Jvd2RTdHJpa2VFeHRlcm5hbElkUGFyYW1ldGVyQXJuKSB7XG4gICAgICBjb25zdCBjcm93ZFN0cmlrZVJvbGVBcm4gPSBwcm9wcy5jcm93ZFN0cmlrZVJvbGVBcm47XG5cbiAgICAgIGNvbnN0IGNyb3dkU3RyaWtlRXh0ZXJuYWxJZCA9IHNzbS5TdHJpbmdQYXJhbWV0ZXIuZnJvbVN0cmluZ1BhcmFtZXRlckFybihcbiAgICAgICAgdGhpcyxcbiAgICAgICAgJ0Nyb3dkU3RyaWtlRXh0ZXJuYWxJZFBhcmFtJyxcbiAgICAgICAgcHJvcHMuY3Jvd2RTdHJpa2VFeHRlcm5hbElkUGFyYW1ldGVyQXJuLFxuICAgICAgKS5zdHJpbmdWYWx1ZTtcblxuICAgICAgY3Jvd2RTdHJpa2VQcmluY2lwYWwgPSBuZXcgaWFtLlByaW5jaXBhbFdpdGhDb25kaXRpb25zKG5ldyBpYW0uQXJuUHJpbmNpcGFsKGNyb3dkU3RyaWtlUm9sZUFybiksIHtcbiAgICAgICAgU3RyaW5nRXF1YWxzOiB7XG4gICAgICAgICAgJ3N0czpFeHRlcm5hbElkJzogY3Jvd2RTdHJpa2VFeHRlcm5hbElkLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZEVycm9yKFxuICAgICAgICAnRWl0aGVyIHJvbGVQcm9wcyBvciBib3RoIGNyb3dkU3RyaWtlUm9sZVBhcmFtZXRlckFybiBhbmQgY3Jvd2RTdHJpa2VFeHRlcm5hbElkUGFyYW1ldGVyQXJuIG11c3QgYmUgcHJvdmlkZWQuJyxcbiAgICAgICk7XG4gICAgICAvLyBUaGlzIHdpbGwgbm90IGJlIHVzZWQgYmVjYXVzZSBvZiB0aGUgZXJyb3IsIGJ1dCB3ZSBuZWVkIHRvIGluaXRpYWxpemUgaXQgdG8gc2F0aXNmeSB0aGUgdHlwZS5cbiAgICAgIGNyb3dkU3RyaWtlUHJpbmNpcGFsID0gbmV3IGlhbS5BbnlQcmluY2lwYWwoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYW4gSUFNIHJvbGUgZm9yIENyb3dkU3RyaWtlIHRvIGFzc3VtZSwgZ3JhbnRpbmcgaXQgYWNjZXNzIHRvIHRoZSByZXNvdXJjZXMgY3JlYXRlZCBpbiB0aGlzIGNvbnN0cnVjdC5cbiAgICAgKiBUaGUgcm9sZSBuYW1lIGNhbiBiZSBwcm92aWRlZCBpbiB0aGUgcHJvcHMsIG9yIGEgZGVmYXVsdCBuYW1lIHdpbGwgYmUgZ2VuZXJhdGVkIGJhc2VkIG9uIHRoZSBidWNrZXQgbmFtZS5cbiAgICAgKi9cbiAgICB0aGlzLnJvbGUgPSBuZXcgaWFtLlJvbGUodGhpcywgJ1JvbGUnLCB7XG4gICAgICByb2xlTmFtZTogcHJvcHMucm9sZVByb3BzPy5yb2xlTmFtZSB8fCBgJHt0aGlzLmJ1Y2tldE5hbWV9LXJvbGVgLFxuICAgICAgYXNzdW1lZEJ5OiBjcm93ZFN0cmlrZVByaW5jaXBhbCxcbiAgICAgIC4uLnByb3BzLnJvbGVQcm9wcyxcbiAgICB9KTtcblxuICAgIC8vIEdyYW50IHRoZSByb2xlIHBlcm1pc3Npb25zIHRvIHJlYWQgZnJvbSB0aGUgYnVja2V0IGFuZCBjb25zdW1lIG1lc3NhZ2VzIGZyb20gdGhlIFNRUyBxdWV1ZS5cbiAgICB0aGlzLmdyYW50UmVhZCh0aGlzLnJvbGUpO1xuICAgIHRoaXMucXVldWUuZ3JhbnRDb25zdW1lTWVzc2FnZXModGhpcy5yb2xlKTtcblxuICAgIC8vIElmIGNyZWF0ZUttc0tleSBpcyB0cnVlLCBjcmVhdGUgYSBLTVMga2V5IGZvciB0aGUgZGF0YS5cbiAgICBpZiAocHJvcHMuY3JlYXRlS21zS2V5KSB7XG4gICAgICB0aGlzLmtleSA9IG5ldyBrbXMuS2V5KHRoaXMsICdLZXknLCB7XG4gICAgICAgIGFsaWFzOiBgYWxpYXMvJHt0aGlzLmJ1Y2tldE5hbWV9YCxcbiAgICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5SRVRBSU5fT05fVVBEQVRFX09SX0RFTEVURSxcbiAgICAgICAgZW5hYmxlS2V5Um90YXRpb246IGZhbHNlLFxuICAgICAgICBtdWx0aVJlZ2lvbjogdHJ1ZSxcbiAgICAgICAgZGVzY3JpcHRpb246IGBLTVMgS2V5IGZvciBDcm93ZFN0cmlrZSBpbmdlc3Rpb24gYnVja2V0ICR7dGhpcy5idWNrZXROYW1lfWAsXG4gICAgICAgIC4uLnByb3BzLmtleVByb3BzLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIEdyYW50IHRoZSByb2xlIHBlcm1pc3Npb25zIHRvIHVzZSB0aGUgS01TIGtleSBmb3IgZGVjcnlwdGlvbi5cbiAgICAgIHRoaXMua2V5LmdyYW50RGVjcnlwdCh0aGlzLnJvbGUpO1xuXG4gICAgICAvKipcbiAgICAgICAqIElmIGFuIG9yZ0lkIGlzIHByb3ZpZGVkLCBncmFudCBwZXJtaXNzaW9ucyB0byB1c2UgdGhlIEtNUyBrZXlcbiAgICAgICAqIGZvciBlbmNyeXB0aW9uIGFuZCBkZWNyeXB0aW9uIGZvciBhbGwgYWNjb3VudHMgaW4gdGhlIG9yZ2FuaXphdGlvbi5cbiAgICAgICAqL1xuICAgICAgaWYgKHByb3BzLm9yZ0lkKSB7XG4gICAgICAgIHRoaXMua2V5LmdyYW50RW5jcnlwdERlY3J5cHQobmV3IGlhbS5Pcmdhbml6YXRpb25QcmluY2lwYWwocHJvcHMub3JnSWQpKTtcbiAgICAgIH1cblxuICAgICAgLy8gT3V0cHV0IHRoZSBLTVMga2V5IEFSTiBmb3IgcmVmZXJlbmNlLlxuICAgICAgbmV3IENmbk91dHB1dCh0aGlzLCAnS21zS2V5QXJuJywge1xuICAgICAgICB2YWx1ZTogdGhpcy5rZXkua2V5QXJuLFxuICAgICAgICBkZXNjcmlwdGlvbjogJ1RoZSBBUk4gb2YgdGhlIEtNUyBrZXkgZm9yIENyb3dkU3RyaWtlIGluZ2VzdGlvbicsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPdXRwdXQgdGhlIGJ1Y2tldCBuYW1lLCBidWNrZXQgQVJOLCBxdWV1ZSBuYW1lLCBhbmQgcm9sZSBuYW1lLlxuICAgICAqIFlvdSB3aWxsIG5lZWQgdGhlc2UgdmFsdWVzIHRvIGNvbmZpZ3VyZSBDcm93ZFN0cmlrZSBjb25uZWN0b3JzLlxuICAgICAqL1xuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgJ0J1Y2tldE5hbWUnLCB7XG4gICAgICB2YWx1ZTogdGhpcy5idWNrZXROYW1lLFxuICAgICAgZGVzY3JpcHRpb246ICdUaGUgTmFtZSBvZiB0aGUgUzMgYnVja2V0IGZvciBDcm93ZFN0cmlrZSBpbmdlc3Rpb24nLFxuICAgIH0pO1xuXG4gICAgbmV3IENmbk91dHB1dCh0aGlzLCAnQnVja2V0QXJuJywge1xuICAgICAgdmFsdWU6IHRoaXMuYnVja2V0QXJuLFxuICAgICAgZGVzY3JpcHRpb246ICdUaGUgQVJOIG9mIHRoZSBTMyBidWNrZXQgZm9yIENyb3dkU3RyaWtlIGluZ2VzdGlvbicsXG4gICAgfSk7XG5cbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsICdRdWV1ZU5hbWUnLCB7XG4gICAgICB2YWx1ZTogdGhpcy5xdWV1ZS5xdWV1ZU5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSBOYW1lIG9mIHRoZSBTUVMgcXVldWUgZm9yIENyb3dkU3RyaWtlIGluZ2VzdGlvbicsXG4gICAgfSk7XG5cbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsICdSb2xlTmFtZScsIHtcbiAgICAgIHZhbHVlOiB0aGlzLnJvbGUucm9sZU5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSBOYW1lIG9mIHRoZSBJQU0gcm9sZSBmb3IgQ3Jvd2RTdHJpa2UgaW5nZXN0aW9uJyxcbiAgICB9KTtcbiAgfVxufVxuIl19