UNPKG

@renovosolutions/cdk-library-crowdstrike-ingestion

Version:

A CDK library to ease repetetive construct creation for CrowdStrike data ingestion

300 lines 44.6 kB
"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, // Not using KMS encryption due to complexity with CrowdStrike integration 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) { const organizationBucketPolicy = new aws_cdk_lib_1.aws_iam.PolicyStatement({ actions: [ 's3:PutObject', 's3:PutObjectAcl', 's3:DeleteObject', 's3:AbortMultipartUpload', ], resources: [this.arnForObjects('*')], principals: [new aws_cdk_lib_1.aws_iam.OrganizationPrincipal(props.orgId)], }); this.addToResourcePolicy(organizationBucketPolicy); } // 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, encryption: aws_cdk_lib_1.aws_sqs.QueueEncryption.SQS_MANAGED, // Not using KMS encryption due to complexity with CrowdStrike integration 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 const bucketPolicy = new aws_cdk_lib_1.aws_iam.ManagedPolicy(this, 'BucketAccessPolicy', { statements: [ new aws_cdk_lib_1.aws_iam.PolicyStatement({ actions: [ 's3:GetObject', 's3:GetObjectVersion', 's3:GetObjectTagging', 's3:ListBucket', 's3:ListBucketVersions', 's3:GetBucketLocation', ], resources: [ this.bucketArn, this.arnForObjects('*'), ], }), ], }); this.role.addManagedPolicy(bucketPolicy); const queuePolicy = new aws_cdk_lib_1.aws_iam.ManagedPolicy(this, 'QueueAccessPolicy', { statements: [ new aws_cdk_lib_1.aws_iam.PolicyStatement({ actions: [ 'sqs:ReceiveMessage', 'sqs:ChangeMessageVisibility', 'sqs:GetQueueUrl', 'sqs:DeleteMessage', 'sqs:GetQueueAttributes', ], resources: [this.queue.queueArn], }), ], }); this.role.addManagedPolicy(queuePolicy); // 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: true, multiRegion: true, description: `KMS Key for CrowdStrike ingestion bucket ${this.bucketName}`, ...props.keyProps, }); // Grant the role permissions to use the KMS key for decryption. const keyDecryptPolicy = new aws_cdk_lib_1.aws_iam.ManagedPolicy(this, 'KeyDecryptPolicy', { statements: [ new aws_cdk_lib_1.aws_iam.PolicyStatement({ actions: [ 'kms:Decrypt', 'kms:DescribeKey', 'kms:GenerateDataKey', ], resources: [this.key.keyArn], }), ], }); this.role.addManagedPolicy(keyDecryptPolicy); /** * 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) { const organizationKeyPolicy = new aws_cdk_lib_1.aws_iam.PolicyStatement({ actions: [ 'kms:Encrypt', 'kms:Decrypt', 'kms:ReEncryptTo', 'kms:ReEncryptFrom', 'kms:GenerateDataKey', 'kms:GenerateDataKeyWithoutPlaintext', 'kms:DescribeKey', ], resources: ['*'], principals: [new aws_cdk_lib_1.aws_iam.OrganizationPrincipal(props.orgId)], }); this.key.addToResourcePolicy(organizationKeyPolicy); } // 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', }); } /** * This pattern is used to ensure that cdk-nag remains an optional * dependency. If cdk-nag is not installed, the require statement * will fail and we will skip adding suppressions, but the * construct will still work as expected. */ try { // eslint-disable-next-line @typescript-eslint/no-require-imports const { NagSuppressions } = require('cdk-nag'); NagSuppressions.addResourceSuppressions(this, [ { id: 'NIST.800.53.R5-S3DefaultEncryptionKMS', reason: 'Not using KMS encryption due to complexity with CrowdStrike integration.', }, { id: 'NIST.800.53.R5-S3BucketReplicationEnabled', reason: 'Replication is not required for CrowdStrike ingestion buckets because the data is sent directly to CrowdStrike.', }, { id: 'NIST.800.53.R5-S3BucketLoggingEnabled', reason: 'Access logging is not required for CrowdStrike ingestion buckets because they are normally themselves access log destinations.', }, { id: 'AwsSolutions-S1', reason: 'Access logging is not required for CrowdStrike ingestion buckets because they are normally themselves access log destinations.', }, { id: 'AwsSolutions-IAM5', reason: 'The bucket policy needs to grant access to all the objects in the bucket to be useful.', appliesTo: [{ regex: '/^Resource::<.*\\.Arn>\\/\\*$/', }], }, ], true); NagSuppressions.addResourceSuppressions(this.role, [ { id: 'AwsSolutions-IAM5', reason: 'The role needs access to all the objects in the bucket.', appliesTo: [{ regex: '/^Resource::<.*\\.Arn>\\/\\*$/', }], }, ], true); /** * Suppress cdk-nag violations for the BucketNotificationsHandler Lambda * that CDK automatically creates for S3 event notifications. * Apply at stack level since the handler is created there. */ aws_cdk_lib_1.Aspects.of(aws_cdk_lib_1.Stack.of(this)).add({ visit(node) { // Suppress IAM4 for the BucketNotificationsHandler role if (node instanceof aws_cdk_lib_1.aws_iam.CfnRole && node.node.path.includes('BucketNotificationsHandler')) { NagSuppressions.addResourceSuppressions(node, [ { id: 'AwsSolutions-IAM4', reason: 'The BucketNotificationsHandler Lambda is created by CDK and uses the standard AWSLambdaBasicExecutionRole managed policy.', appliesTo: ['Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'], }, ]); } // Suppress IAMNoInlinePolicy for the BucketNotificationsHandler policy if (node instanceof aws_cdk_lib_1.aws_iam.CfnPolicy && node.node.path.includes('BucketNotificationsHandler')) { NagSuppressions.addResourceSuppressions(node, [ { id: 'NIST.800.53.R5-IAMNoInlinePolicy', reason: 'The BucketNotificationsHandler Lambda is created by CDK and uses inline policies for its custom resource implementation.', }, ]); } }, }); } catch { // cdk-nag is not installed; NAG suppressions will not be applied } /** * 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.1.2" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVja2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2J1Y2tldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQVlxQjtBQTZEcEIsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxNQUFhLGlCQUFrQixTQUFRLG9CQUFFLENBQUMsTUFBTTtJQWtCOUM7Ozs7OztPQU1HO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUE2QjtRQUNyRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLFVBQVUsRUFBRSxvQkFBRSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsRUFBRSwwRUFBMEU7WUFDdEgsaUJBQWlCLEVBQUUsb0JBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTO1lBQ2pELFVBQVUsRUFBRSxJQUFJO1lBQ2hCLFNBQVMsRUFBRSxJQUFJO1lBQ2YsYUFBYSxFQUFFLDJCQUFhLENBQUMsMEJBQTBCO1lBQ3ZELEdBQUcsS0FBSztTQUNULENBQUMsQ0FBQztRQUVIOzs7V0FHRztRQUNILElBQUksS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2hCLE1BQU0sd0JBQXdCLEdBQUcsSUFBSSxxQkFBRyxDQUFDLGVBQWUsQ0FBQztnQkFDdkQsT0FBTyxFQUFFO29CQUNQLGNBQWM7b0JBQ2QsaUJBQWlCO29CQUNqQixpQkFBaUI7b0JBQ2pCLHlCQUF5QjtpQkFDMUI7Z0JBQ0QsU0FBUyxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDcEMsVUFBVSxFQUFFLENBQUMsSUFBSSxxQkFBRyxDQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUN6RCxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsbUJBQW1CLENBQUMsd0JBQXdCLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBRUQsK0dBQStHO1FBQy9HLElBQUksS0FBSyxDQUFDLHVCQUF1QixFQUFFLENB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U0FDbkUsQ0FBQyxDQUFDO1FBRUgsSUFBSSx1QkFBUyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUU7WUFDL0IsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTO1lBQ3JCLFdBQVcsRUFBRSxvREFBb0Q7U0FDbEUsQ0FBQyxDQUFDO1FBRUgsSUFBSSx1QkFBUyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUU7WUFDL0IsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUztZQUMzQixXQUFXLEVBQUUscURBQXFEO1NBQ25FLENBQUMsQ0FBQztRQUVILElBQUksdUJBQVMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBQzlCLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVE7WUFDekIsV0FBVyxFQUFFLG9EQUFvRDtTQUNsRSxDQUFDLENBQUM7SUFDTCxDQUFDOztBQXhWSCw4Q0F5VkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBbm5vdGF0aW9ucyxcbiAgQXNwZWN0cyxcbiAgQ2ZuT3V0cHV0LFxuICBSZW1vdmFsUG9saWN5LFxuICBTdGFjayxcbiAgYXdzX2lhbSBhcyBpYW0sXG4gIGF3c19rbXMgYXMga21zLFxuICBhd3NfczMgYXMgczMsXG4gIGF3c19zM19ub3RpZmljYXRpb25zIGFzIHMzbixcbiAgYXdzX3NxcyBhcyBzcXMsXG4gIGF3c19zc20gYXMgc3NtLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciB0aGUgQ3Jvd2RTdHJpa2VCdWNrZXQgY29uc3RydWN0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENyb3dkU3RyaWtlQnVja2V0UHJvcHMgZXh0ZW5kcyBzMy5CdWNrZXRQcm9wcyB7XG4gIC8qKlxuICAgKiBQcm9wZXJ0aWVzIGZvciB0aGUgU1FTIHF1ZXVlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGVuZm9yY2VTU0w6IHRydWUsIGRlYWRMZXR0ZXJRdWV1ZTogeyBtYXhSZWNlaXZlQ291bnQ6IDUsIHF1ZXVlOiBuZXcgc3FzLlF1ZXVlKHRoaXMsICdETFEnLCB7IHF1ZXVlTmFtZTogYCR7dGhpcy5idWNrZXROYW1lfS1kbHFgLCBlbmZvcmNlU1NMOiB0cnVlLCB9KSwgfSxcbiAgICovXG4gIHJlYWRvbmx5IHF1ZXVlUHJvcHM/OiBzcXMuUXVldWVQcm9wcztcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gY3JlYXRlIGEgS01TIGtleSBmb3IgdGhlIGJ1Y2tldC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgY3JlYXRlS21zS2V5PzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFByb3BlcnRpZXMgZm9yIHRoZSBLTVMga2V5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuUkVUQUlOX09OX1VQREFURV9PUl9ERUxFVEUsIGVuYWJsZUtleVJvdGF0aW9uOiBmYWxzZSwgbXVsdGlSZWdpb246IHRydWUsIGRlc2NyaXB0aW9uOiBgS01TIEtleSBmb3IgQ3Jvd2RTdHJpa2UgaW5nZXN0aW9uIGJ1Y2tldCAke3RoaXMuYnVja2V0TmFtZX1gLFxuICAgKi9cbiAgcmVhZG9ubHkga2V5UHJvcHM/OiBrbXMuS2V5UHJvcHM7XG4gIC8qKlxuICAgKiBQcm9wZXJ0aWVzIGZvciB0aGUgSUFNIHJvbGUuXG4gICAqXG4gICAqIElmIHlvdSBwcm92aWRlIHRoaXMsIHlvdSBtdXN0IHByb3ZpZGUgdGhlIHJvbGVQcm9wcy5hc3N1bWVkQnkgcHJvcGVydHksXG4gICAqIGFuZCB5b3UgZG9uJ3QgbmVlZCB0byBwcm92aWRlIHRoZSBjcm93ZFN0cmlrZVJvbGVQYXJhbWV0ZXJBcm4gYW5kIGNyb3dkU3RyaWtlRXh0ZXJuYWxJZFBhcmFtZXRlckFybi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lIGV4Y2VwdCBmb3IgdGhlIGFzc3VtZWRCeSBwcm9wZXJ0eSB3aGljaCBpcyBzZXQgdG8gYSBDcm93ZFN0cmlrZSBwcmluY2lwYWwuXG4gICAqL1xuICByZWFkb25seSByb2xlUHJvcHM/OiBpYW0uUm9sZVByb3BzO1xuICAvKipcbiAgICogVGhlIENyb3dkU3RyaWtlIHJvbGUgQVJOLlxuICAgKlxuICAgKiBSZXF1aXJlZCB1bmxlc3MgdGhlIHJvbGUgcHJpbmNpcGFsIGlzIHByb3ZpZGVkIGRpcmVjdGx5IGluIHRoZSByb2xlUHJvcHMuXG4gICAqL1xuICByZWFkb25seSBjcm93ZFN0cmlrZVJvbGVBcm4/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgQVJOIG9mIHRoZSBTU00gcGFyYW1ldGVyIGNvbnRhaW5pbmcgdGhlIENyb3dkU3RyaWtlIGV4dGVybmFsIElELlxuICAgKlxuICAgKiBSZXF1aXJlZCB1bmxlc3MgdGhlIHJvbGUgcHJpbmNpcGFsIGlzIHByb3ZpZGVkIGRpcmVjdGx5IGluIHRoZSByb2xlUHJvcHMuXG4gICAqL1xuICByZWFkb25seSBjcm93ZFN0cmlrZUV4dGVybmFsSWRQYXJhbWV0ZXJBcm4/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgb3JnYW5pemF0aW9uIElELlxuICAgKiBJZiBwcm92aWRlZCwgdGhlIGJ1Y2tldCB3aWxsIGFsbG93IHdyaXRlIGFjY2VzcyB0byBhbGwgYWNjb3VudHMgaW4gdGhlIG9yZ2FuaXphdGlvbi5cbiAgICogSWYgdGhlcmUgaXMgYSBLTVMga2V5LCBpdCB3aWxsIGFsc28gYWxsb3cgZW5jcnlwdC9kZWNyeXB0IGFjY2VzcyB0byB0aGUgb3JnYW5pemF0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIHJlYWRvbmx5IG9yZ0lkPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIFMzIGJ1Y2tldCB0aGF0IHdpbGwgYmUgc2VuZGluZyBTMyBhY2Nlc3MgbG9ncyB0byB0aGlzIGJ1Y2tldC5cbiAgICogVGhpcyBpcyB1c2VkIHRvIGNvbmZpZ3VyZSB0aGUgYnVja2V0IHBvbGljeSB0byBhbGxvdyBsb2dnaW5nIGZyb20gdGhhdCBidWNrZXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgbG9nZ2luZ0J1Y2tldFNvdXJjZU5hbWU/OiBzdHJpbmc7XG59O1xuXG4vKipcbiAqIEEgY29uc3RydWN0IHRoYXQgY3JlYXRlcyBhbiBTMyBidWNrZXQgZm9yIENyb3dkU3RyaWtlIGRhdGEgaW5nZXN0aW9uLFxuICogYWxvbmcgd2l0aCBhbiBTUVMgcXVldWUgZm9yIG5vdGlmaWNhdGlvbnMsIGFuIElBTSByb2xlIGZvciBhY2Nlc3MsXG4gKiBhbmQgb3B0aW9uYWxseSBhIEtNUyBrZXkgZm9yIGVuY3J5cHRpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBDcm93ZFN0cmlrZUJ1Y2tldCBleHRlbmRzIHMzLkJ1Y2tldCB7XG4gIC8qKlxuICAgKiBUaGUgU1FTIHF1ZXVlIHRoYXQgcmVjZWl2ZXMgbm90aWZpY2F0aW9ucyBmb3IgbmV3IG9iamVjdHMgaW4gdGhlIGJ1Y2tldC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBxdWV1ZTogc3FzLlF1ZXVlO1xuICAvKipcbiAgICogVGhlIEtNUyBrZXkgdXNlZCBmb3IgZW5jcnlwdGluZyBkYXRhIGluIHRoZSBidWNrZXQsIGlmIGNyZWF0ZWQuXG4gICAqIFRoaXMgd2lsbCBiZSB1bmRlZmluZWQgaWYgY3JlYXRlS21zS2V5IGlzIGZhbHNlLlxuICAgKlxuICAgKiBOb3RlIHRoYXQgdGhlIGJ1Y2tldCB3aWxsIHN0aWxsIGJlIGNyZWF0ZWQgd2l0aCBTMy1tYW5hZ2VkIGVuY3J5cHRpb25cbiAgICogZXZlbiBpZiB0aGlzIGlzIHByb3ZpZGVkLiBUaGUga2V5IGlzIHVzZWQgYnkgdGhlIHNlcnZpY2Ugd3JpdGluZyB0byB0aGUgYnVja2V0LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGtleT86IGttcy5LZXk7XG4gIC8qKlxuICAgKiBUaGUgSUFNIHJvbGUgdGhhdCBDcm93ZFN0cmlrZSB3aWxsIGFzc3VtZSB0byBhY2Nlc3MgdGhlIGRhdGEgaW4gdGhlIGJ1Y2tldC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSByb2xlOiBpYW0uUm9sZTtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIG5ldyBDcm93ZFN0cmlrZUJ1Y2tldC5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFRoZSBzY29wZSBpbiB3aGljaCB0aGlzIGNvbnN0cnVjdCBpcyBkZWZpbmVkLlxuICAgKiBAcGFyYW0gaWQgVGhlIHNjb3BlZCBjb25zdHJ1Y3QgSUQuXG4gICAqIEBwYXJhbSBwcm9wcyBUaGUgcHJvcGVydGllcyBmb3IgdGhlIGJ1Y2tldCwgcXVldWUsIHJvbGUsIGFuZCBvcHRpb25hbCBLTVMga2V5LlxuICAgKi9cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IENyb3dkU3RyaWtlQnVja2V0UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIGVuY3J5cHRpb246IHMzLkJ1Y2tldEVuY3J5cHRpb24uUzNfTUFOQUdFRCwgLy8gTm90IHVzaW5nIEtNUyBlbmNyeXB0aW9uIGR1ZSB0byBjb21wbGV4aXR5IHdpdGggQ3Jvd2RTdHJpa2UgaW50ZWdyYXRpb25cbiAgICAgIGJsb2NrUHVibGljQWNjZXNzOiBzMy5CbG9ja1B1YmxpY0FjY2Vzcy5CTE9DS19BTEwsXG4gICAgICBlbmZvcmNlU1NMOiB0cnVlLFxuICAgICAgdmVyc2lvbmVkOiB0cnVlLFxuICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5SRVRBSU5fT05fVVBEQVRFX09SX0RFTEVURSxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogSWYgd2UgaGF2ZSBhbiBvcmdJZCwgZ3JhbnQgYnVja2V0IHdyaXRlIGFjY2VzcyB0byBhbGwgYWNjb3VudHMgaW4gdGhlIG9yZ2FuaXphdGlvbi5cbiAgICAgKiBUaGlzIGlzIHVzZWZ1bCBmb3IgYWxsb3dpbmcgbXVsdGlwbGUgYWNjb3VudHMgaW4gYW4gb3JnYW5pemF0aW9uIHRvIHdyaXRlIHRvIHRoZSBzYW1lIGJ1Y2tldC5cbiAgICAgKi9cbiAgICBpZiAocHJvcHMub3JnSWQpIHtcbiAgICAgIGNvbnN0IG9yZ2FuaXphdGlvbkJ1Y2tldFBvbGljeSA9IG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgICdzMzpQdXRPYmplY3QnLFxuICAgICAgICAgICdzMzpQdXRPYmplY3RBY2wnLFxuICAgICAgICAgICdzMzpEZWxldGVPYmplY3QnLFxuICAgICAgICAgICdzMzpBYm9ydE11bHRpcGFydFVwbG9hZCcsXG4gICAgICAgIF0sXG4gICAgICAgIHJlc291cmNlczogW3RoaXMuYXJuRm9yT2JqZWN0cygnKicpXSxcbiAgICAgICAgcHJpbmNpcGFsczogW25ldyBpYW0uT3JnYW5pemF0aW9uUHJpbmNpcGFsKHByb3BzLm9yZ0lkKV0sXG4gICAgICB9KTtcbiAgICAgIHRoaXMuYWRkVG9SZXNvdXJjZVBvbGljeShvcmdhbml6YXRpb25CdWNrZXRQb2xpY3kpO1xuICAgIH1cblxuICAgIC8vIElmIGEgbG9nZ2luZyBidWNrZXQgc291cmNlIG5hbWUgaXMgcHJvdmlkZWQsIGFkZCBhIHBvbGljeSB0byBhbGxvdyB0aGF0IGJ1Y2tldCB0byB3cml0ZSBsb2dzIHRvIHRoaXMgYnVja2V0LlxuICAgIGlmIChwcm9wcy5sb2dnaW5nQnVja2V0U291cmNlTmFtZSkge1xuICAgICAgdGhpcy5hZGRUb1Jlc291cmNlUG9saWN5KFxuICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICAgIGFjdGlvbnM6IFsnczM6UHV0T2JqZWN0J10sXG4gICAgICAgICAgcmVzb3VyY2VzOiBbdGhpcy5hcm5Gb3JPYmplY3RzKCcqJyldLFxuICAgICAgICAgIHByaW5jaXBhbHM6IFtuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoJ2xvZ2dpbmcuczMuYW1hem9uYXdzLmNvbScpXSxcbiAgICAgICAgICBjb25kaXRpb25zOiB7XG4gICAgICAgICAgICBBcm5MaWtlOiB7XG4gICAgICAgICAgICAgICdhd3M6U291cmNlQXJuJzogYGFybjphd3M6czM6Ojoke3Byb3BzLmxvZ2dpbmdCdWNrZXRTb3VyY2VOYW1lfWAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgU3RyaW5nRXF1YWxzOiB7XG4gICAgICAgICAgICAgICdhd3M6U291cmNlQWNjb3VudCc6IFN0YWNrLm9mKHRoaXMpLmFjY291bnQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYW4gU1FTIHF1ZXVlIGZvciBub3RpZmljYXRpb25zLlxuICAgICAqIElmIGEgcXVldWVOYW1lIGlzIHByb3ZpZGVkLCB1c2UgaXQ7IG90aGVyd2lzZSwgZ2VuZXJhdGUgYSBkZWZhdWx0IG5hbWUgYmFzZWQgb24gdGhlIGJ1Y2tldCBuYW1lLlxuICAgICAqL1xuICAgIHRoaXMucXVldWUgPSBuZXcgc3FzLlF1ZXVlKHRoaXMsICdRdWV1ZScsIHtcbiAgICAgIHF1ZXVlTmFtZTogcHJvcHMucXVldWVQcm9wcz8ucXVldWVOYW1lIHx8IGAke3RoaXMuYnVja2V0TmFtZX0tcXVldWVgLFxuICAgICAgZW5mb3JjZVNTTDogdHJ1ZSxcbiAgICAgIGVuY3J5cHRpb246IHNxcy5RdWV1ZUVuY3J5cHRpb24uU1FTX01BTkFHRUQsIC8vIE5vdCB1c2luZyBLTVMgZW5jcnlwdGlvbiBkdWUgdG8gY29tcGxleGl0eSB3aXRoIENyb3dkU3RyaWtlIGludGVncmF0aW9uXG4gICAgICBkZWFkTGV0dGVyUXVldWU6IHtcbiAgICAgICAgbWF4UmVjZWl2ZUNvdW50OiA1LFxuICAgICAgICBxdWV1ZTogbmV3IHNxcy5RdWV1ZSh0aGlzLCAnRExRJywge1xuICAgICAgICAgIHF1ZXVlTmFtZTogYCR7dGhpcy5idWNrZXROYW1lfS1kbHFgLFxuICAgICAgICAgIGVuZm9yY2VTU0w6IHRydWUsXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICAgIC4uLnByb3BzLnF1ZXVlUHJvcHMsXG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYSBub3RpZmljYXRpb24gZm9yIGJ1Y2tldCBvYmplY3QgY3JlYXRpb24gZXZlbnRzIHRvIHRoZSBTUVMgcXVldWUuXG4gICAgdGhpcy5hZGRFdmVudE5vdGlmaWNhdGlvbihcbiAgICAgIHMzLkV2ZW50VHlwZS5PQkpFQ1RfQ1JFQVRFRCxcbiAgICAgIG5ldyBzM24uU3FzRGVzdGluYXRpb24odGhpcy5xdWV1ZSksXG4gICAgKTtcblxuICAgIC8qKlxuICAgICAqIERldGVybWluZSB0aGUgcHJpbmNpcGFsIGZvciBDcm93ZFN0cmlrZS5cbiAgICAgKiBJZiByb2xlUHJvcHMgYXJlIHByb3ZpZGVkLCB1c2UgdGhlIGFzc3VtZWRCeSBwcm9wZXJ0eSBmcm9tIHRoZXJlLlxuICAgICAqIE90aGVyd2lzZSwgY3JlYXRlIGEgQ3Jvd2RTdHJpa2UgcHJpbmNpcGFsIHVzaW5nIHRoZSByb2xlIEFSTiBhbmQgZXh0ZXJuYWwgSUQgZnJvbSBTU00gcGFyYW1ldGVycy5cbiAgICAgKi9cbiAgICBsZXQgY3Jvd2RTdHJpa2VQcmluY2lwYWw6IGlhbS5JUHJpbmNpcGFsO1xuICAgIGlmIChwcm9wcy5yb2xlUHJvcHMpIHtcbiAgICAgIGNyb3dkU3RyaWtlUHJpbmNpcGFsID0gcHJvcHMucm9sZVByb3BzLmFzc3VtZWRCeTtcbiAgICB9IGVsc2UgaWYgKHByb3BzLmNyb3dkU3RyaWtlUm9sZUFybiAmJiBwcm9wcy5jcm93ZFN0cmlrZUV4dGVybmFsSWRQYXJhbWV0ZXJBcm4pIHtcbiAgICAgIGNvbnN0IGNyb3dkU3RyaWtlUm9sZUFybiA9IHByb3BzLmNyb3dkU3RyaWtlUm9sZUFybjtcblxuICAgICAgY29uc3QgY3Jvd2RTdHJpa2VFeHRlcm5hbElkID0gc3NtLlN0cmluZ1BhcmFtZXRlci5mcm9tU3RyaW5nUGFyYW1ldGVyQXJuKFxuICAgICAgICB0aGlzLFxuICAgICAgICAnQ3Jvd2RTdHJpa2VFeHRlcm5hbElkUGFyYW0nLFxuICAgICAgICBwcm9wcy5jcm93ZFN0cmlrZUV4dGVybmFsSWRQYXJhbWV0ZXJBcm4sXG4gICAgICApLnN0cmluZ1ZhbHVlO1xuXG4gICAgICBjcm93ZFN0cmlrZVByaW5jaXBhbCA9IG5ldyBpYW0uUHJpbmNpcGFsV2l0aENvbmRpdGlvbnMobmV3IGlhbS5Bcm5QcmluY2lwYWwoY3Jvd2RTdHJpa2VSb2xlQXJuKSwge1xuICAgICAgICBTdHJpbmdFcXVhbHM6IHtcbiAgICAgICAgICAnc3RzOkV4dGVybmFsSWQnOiBjcm93ZFN0cmlrZUV4dGVybmFsSWQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkRXJyb3IoXG4gICAgICAgICdFaXRoZXIgcm9sZVByb3BzIG9yIGJvdGggY3Jvd2RTdHJpa2VSb2xlUGFyYW1ldGVyQXJuIGFuZCBjcm93ZFN0cmlrZUV4dGVybmFsSWRQYXJhbWV0ZXJBcm4gbXVzdCBiZSBwcm92aWRlZC4nLFxuICAgICAgKTtcbiAgICAgIC8vIFRoaXMgd2lsbCBub3QgYmUgdXNlZCBiZWNhdXNlIG9mIHRoZSBlcnJvciwgYnV0IHdlIG5lZWQgdG8gaW5pdGlhbGl6ZSBpdCB0byBzYXRpc2Z5IHRoZSB0eXBlLlxuICAgICAgY3Jvd2RTdHJpa2VQcmluY2lwYWwgPSBuZXcgaWFtLkFueVByaW5jaXBhbCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhbiBJQU0gcm9sZSBmb3IgQ3Jvd2RTdHJpa2UgdG8gYXNzdW1lLCBncmFudGluZyBpdCBhY2Nlc3MgdG8gdGhlIHJlc291cmNlcyBjcmVhdGVkIGluIHRoaXMgY29uc3RydWN0LlxuICAgICAqIFRoZSByb2xlIG5hbWUgY2FuIGJlIHByb3ZpZGVkIGluIHRoZSBwcm9wcywgb3IgYSBkZWZhdWx0IG5hbWUgd2lsbCBiZSBnZW5lcmF0ZWQgYmFzZWQgb24gdGhlIGJ1Y2tldCBuYW1lLlxuICAgICAqL1xuICAgIHRoaXMucm9sZSA9IG5ldyBpYW0uUm9sZSh0aGlzLCAnUm9sZScsIHtcbiAgICAgIHJvbGVOYW1lOiBwcm9wcy5yb2xlUHJvcHM/LnJvbGVOYW1lIHx8IGAke3RoaXMuYnVja2V0TmFtZX0tcm9sZWAsXG4gICAgICBhc3N1bWVkQnk6IGNyb3dkU3RyaWtlUHJpbmNpcGFsLFxuICAgICAgLi4ucHJvcHMucm9sZVByb3BzLFxuICAgIH0pO1xuXG4gICAgLy8gR3JhbnQgdGhlIHJvbGUgcGVybWlzc2lvbnMgdG8gcmVhZCBmcm9tIHRoZSBidWNrZXQgYW5kIGNvbnN1bWUgbWVzc2FnZXMgZnJvbSB0aGUgU1FTIHF1ZXVlXG4gICAgY29uc3QgYnVja2V0UG9saWN5ID0gbmV3IGlhbS5NYW5hZ2VkUG9saWN5KHRoaXMsICdCdWNrZXRBY2Nlc3NQb2xpY3knLCB7XG4gICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgICAnczM6R2V0T2JqZWN0JyxcbiAgICAgICAgICAgICdzMzpHZXRPYmplY3RWZXJzaW9uJyxcbiAgICAgICAgICAgICdzMzpHZXRPYmplY3RUYWdnaW5nJyxcbiAgICAgICAgICAgICdzMzpMaXN0QnVja2V0JyxcbiAgICAgICAgICAgICdzMzpMaXN0QnVja2V0VmVyc2lvbnMnLFxuICAgICAgICAgICAgJ3MzOkdldEJ1Y2tldExvY2F0aW9uJyxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgICAgdGhpcy5idWNrZXRBcm4sXG4gICAgICAgICAgICB0aGlzLmFybkZvck9iamVjdHMoJyonKSxcbiAgICAgICAgICBdLFxuICAgICAgICB9KSxcbiAgICAgIF0sXG4gICAgfSk7XG4gICAgdGhpcy5yb2xlLmFkZE1hbmFnZWRQb2xpY3koYnVja2V0UG9saWN5KTtcblxuICAgIGNvbnN0IHF1ZXVlUG9saWN5ID0gbmV3IGlhbS5NYW5hZ2VkUG9saWN5KHRoaXMsICdRdWV1ZUFjY2Vzc1BvbGljeScsIHtcbiAgICAgIHN0YXRlbWVudHM6IFtcbiAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgICdzcXM6UmVjZWl2ZU1lc3NhZ2UnLFxuICAgICAgICAgICAgJ3NxczpDaGFuZ2VNZXNzYWdlVmlzaWJpbGl0eScsXG4gICAgICAgICAgICAnc3FzOkdldFF1ZXVlVXJsJyxcbiAgICAgICAgICAgICdzcXM6RGVsZXRlTWVzc2FnZScsXG4gICAgICAgICAgICAnc3FzOkdldFF1ZXVlQXR0cmlidXRlcycsXG4gICAgICAgICAgXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFt0aGlzLnF1ZXVlLnF1ZXVlQXJuXSxcbiAgICAgICAgfSksXG4gICAgICBdLFxuICAgIH0pO1xuICAgIHRoaXMucm9sZS5hZGRNYW5hZ2VkUG9saWN5KHF1ZXVlUG9saWN5KTtcblxuICAgIC8vIElmIGNyZWF0ZUttc0tleSBpcyB0cnVlLCBjcmVhdGUgYSBLTVMga2V5IGZvciB0aGUgZGF0YS5cbiAgICBpZiAocHJvcHMuY3JlYXRlS21zS2V5KSB7XG4gICAgICB0aGlzLmtleSA9IG5ldyBrbXMuS2V5KHRoaXMsICdLZXknLCB7XG4gICAgICAgIGFsaWFzOiBgYWxpYXMvJHt0aGlzLmJ1Y2tldE5hbWV9YCxcbiAgICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5SRVRBSU5fT05fVVBEQVRFX09SX0RFTEVURSxcbiAgICAgICAgZW5hYmxlS2V5Um90YXRpb246IHRydWUsXG4gICAgICAgIG11bHRpUmVnaW9uOiB0cnVlLFxuICAgICAgICBkZXNjcmlwdGlvbjogYEtNUyBLZXkgZm9yIENyb3dkU3RyaWtlIGluZ2VzdGlvbiBidWNrZXQgJHt0aGlzLmJ1Y2tldE5hbWV9YCxcbiAgICAgICAgLi4ucHJvcHMua2V5UHJvcHMsXG4gICAgICB9KTtcblxuICAgICAgLy8gR3JhbnQgdGhlIHJvbGUgcGVybWlzc2lvbnMgdG8gdXNlIHRoZSBLTVMga2V5IGZvciBkZWNyeXB0aW9uLlxuICAgICAgY29uc3Qga2V5RGVjcnlwdFBvbGljeSA9IG5ldyBpYW0uTWFuYWdlZFBvbGljeSh0aGlzLCAnS2V5RGVjcnlwdFBvbGljeScsIHtcbiAgICAgICAgc3RhdGVtZW50czogW1xuICAgICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgICAgJ2ttczpEZWNyeXB0JyxcbiAgICAgICAgICAgICAgJ2ttczpEZXNjcmliZUtleScsXG4gICAgICAgICAgICAgICdrbXM6R2VuZXJhdGVEYXRhS2V5JyxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICByZXNvdXJjZXM6IFt0aGlzLmtleS5rZXlBcm5dLFxuICAgICAgICAgIH0pLFxuICAgICAgICBdLFxuICAgICAgfSk7XG4gICAgICB0aGlzLnJvbGUuYWRkTWFuYWdlZFBvbGljeShrZXlEZWNyeXB0UG9saWN5KTtcblxuICAgICAgLyoqXG4gICAgICAgKiBJZiBhbiBvcmdJZCBpcyBwcm92aWRlZCwgZ3JhbnQgcGVybWlzc2lvbnMgdG8gdXNlIHRoZSBLTVMga2V5XG4gICAgICAgKiBmb3IgZW5jcnlwdGlvbiBhbmQgZGVjcnlwdGlvbiBmb3IgYWxsIGFjY291bnRzIGluIHRoZSBvcmdhbml6YXRpb24uXG4gICAgICAgKi9cbiAgICAgIGlmIChwcm9wcy5vcmdJZCkge1xuICAgICAgICBjb25zdCBvcmdhbml6YXRpb25LZXlQb2xpY3kgPSBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgICAgJ2ttczpFbmNyeXB0JyxcbiAgICAgICAgICAgICdrbXM6RGVjcnlwdCcsXG4gICAgICAgICAgICAna21zOlJlRW5jcnlwdFRvJyxcbiAgICAgICAgICAgICdrbXM6UmVFbmNyeXB0RnJvbScsXG4gICAgICAgICAgICAna21zOkdlbmVyYXRlRGF0YUtleScsXG4gICAgICAgICAgICAna21zOkdlbmVyYXRlRGF0YUtleVdpdGhvdXRQbGFpbnRleHQnLFxuICAgICAgICAgICAgJ2ttczpEZXNjcmliZUtleScsXG4gICAgICAgICAgXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgICAgIHByaW5jaXBhbHM6IFtuZXcgaWFtLk9yZ2FuaXphdGlvblByaW5jaXBhbChwcm9wcy5vcmdJZCldLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5rZXkuYWRkVG9SZXNvdXJjZVBvbGljeShvcmdhbml6YXRpb25LZXlQb2xpY3kpO1xuICAgICAgfVxuXG4gICAgICAvLyBPdXRwdXQgdGhlIEtNUyBrZXkgQVJOIGZvciByZWZlcmVuY2UuXG4gICAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsICdLbXNLZXlBcm4nLCB7XG4gICAgICAgIHZhbHVlOiB0aGlzLmtleS5rZXlBcm4sXG4gICAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIEFSTiBvZiB0aGUgS01TIGtleSBmb3IgQ3Jvd2RTdHJpa2UgaW5nZXN0aW9uJyxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgcGF0dGVybiBpcyB1c2VkIHRvIGVuc3VyZSB0aGF0IGNkay1uYWcgcmVtYWlucyBhbiBvcHRpb25hbFxuICAgICAqIGRlcGVuZGVuY3kuIElmIGNkay1uYWcgaXMgbm90IGluc3RhbGxlZCwgdGhlIHJlcXVpcmUgc3RhdGVtZW50XG4gICAgICogd2lsbCBmYWlsIGFuZCB3ZSB3aWxsIHNraXAgYWRkaW5nIHN1cHByZXNzaW9ucywgYnV0IHRoZVxuICAgICAqIGNvbnN0cnVjdCB3aWxsIHN0aWxsIHdvcmsgYXMgZXhwZWN0ZWQuXG4gICAgICovXG4gICAgdHJ5IHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgICBjb25zdCB7IE5hZ1N1cHByZXNzaW9ucyB9ID0gcmVxdWlyZSgnY2RrLW5hZycpIGFzIHR5cGVvZiBpbXBvcnQoJ2Nkay1uYWcnKTtcblxuICAgICAgTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zKFxuICAgICAgICB0aGlzLFxuICAgICAgICBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgaWQ6ICdOSVNULjgwMC41My5SNS1TM0RlZmF1bHRFbmNyeXB0aW9uS01TJyxcbiAgICAgICAgICAgIHJlYXNvbjogJ05vdCB1c2luZyBLTVMgZW5jcnlwdGlvbiBkdWUgdG8gY29tcGxleGl0eSB3aXRoIENyb3dkU3RyaWtlIGludGVncmF0aW9uLicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZDogJ05JU1QuODAwLjUzLlI1LVMzQnVja2V0UmVwbGljYXRpb25FbmFibGVkJyxcbiAgICAgICAgICAgIHJlYXNvbjogJ1JlcGxpY2F0aW9uIGlzIG5vdCByZXF1aXJlZCBmb3IgQ3Jvd2RTdHJpa2UgaW5nZXN0aW9uIGJ1Y2tldHMgYmVjYXVzZSB0aGUgZGF0YSBpcyBzZW50IGRpcmVjdGx5IHRvIENyb3dkU3RyaWtlLicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZDogJ05JU1QuODAwLjUzLlI1LVMzQnVja2V0TG9nZ2luZ0VuYWJsZWQnLFxuICAgICAgICAgICAgcmVhc29uOiAnQWNjZXNzIGxvZ2dpbmcgaXMgbm90IHJlcXVpcmVkIGZvciBDcm93ZFN0cmlrZSBpbmdlc3Rpb24gYnVja2V0cyBiZWNhdXNlIHRoZXkgYXJlIG5vcm1hbGx5IHRoZW1zZWx2ZXMgYWNjZXNzIGxvZyBkZXN0aW5hdGlvbnMuJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGlkOiAnQXdzU29sdXRpb25zLVMxJyxcbiAgICAgICAgICAgIHJlYXNvbjogJ0FjY2VzcyBsb2dnaW5nIGlzIG5vdCByZXF1aXJlZCBmb3IgQ3Jvd2RTdHJpa2UgaW5nZXN0aW9uIGJ1Y2tldHMgYmVjYXVzZSB0aGV5IGFyZSBub3JtYWxseSB0aGVtc2VsdmVzIGFjY2VzcyBsb2cgZGVzdGluYXRpb25zLicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZDogJ0F3c1NvbHV0aW9ucy1JQU01JyxcbiAgICAgICAgICAgIHJlYXNvbjogJ1RoZSBidWNrZXQgcG9saWN5IG5lZWRzIHRvIGdyYW50IGFjY2VzcyB0byBhbGwgdGhlIG9iamVjdHMgaW4gdGhlIGJ1Y2tldCB0byBiZSB1c2VmdWwuJyxcbiAgICAgICAgICAgIGFwcGxpZXNUbzogW3tcbiAgICAgICAgICAgICAgcmVnZXg6ICcvXlJlc291cmNlOjo8LipcXFxcLkFybj5cXFxcL1xcXFwqJC8nLFxuICAgICAgICAgICAgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgdHJ1ZSxcbiAgICAgICk7XG5cbiAgICAgIE5hZ1N1cHByZXNzaW9ucy5hZGRSZXNvdXJjZVN1cHByZXNzaW9ucyhcbiAgICAgICAgdGhpcy5yb2xlLFxuICAgICAgICBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgaWQ6ICdBd3NTb2x1dGlvbnMtSUFNNScsXG4gICAgICAgICAgICByZWFzb246ICdUaGUgcm9sZSBuZWVkcyBhY2Nlc3MgdG8gYWxsIHRoZSBvYmplY3RzIGluIHRoZSBidWNrZXQuJyxcbiAgICAgICAgICAgIGFwcGxpZXNUbzogW3tcbiAgICAgICAgICAgICAgcmVnZXg6ICcvXlJlc291cmNlOjo8LipcXFxcLkFybj5cXFxcL1xcXFwqJC8nLFxuICAgICAgICAgICAgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgdHJ1ZSxcbiAgICAgICk7XG5cbiAgICAgIC8qKlxuICAgICAgICogU3VwcHJlc3MgY2RrLW5hZyB2aW9sYXRpb25zIGZvciB0aGUgQnVja2V0Tm90aWZpY2F0aW9uc0hhbmRsZXIgTGFtYmRhXG4gICAgICAgKiB0aGF0IENESyBhdXRvbWF0aWNhbGx5IGNyZWF0ZXMgZm9yIFMzIGV2ZW50IG5vdGlmaWNhdGlvbnMuXG4gICAgICAgKiBBcHBseSBhdCBzdGFjayBsZXZlbCBzaW5jZSB0aGUgaGFuZGxlciBpcyBjcmVhdGVkIHRoZXJlLlxuICAgICAgICovXG4gICAgICBBc3BlY3RzLm9mKFN0YWNrLm9mKHRoaXMpKS5hZGQoe1xuICAgICAgICB2aXNpdChub2RlOiBDb25zdHJ1Y3QpIHtcbiAgICAgICAgICAvLyBTdXBwcmVzcyBJQU00IGZvciB0aGUgQnVja2V0Tm90aWZpY2F0aW9uc0hhbmRsZXIgcm9sZVxuICAgICAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgaWFtLkNmblJvbGUgJiYgbm9kZS5ub2RlLnBhdGguaW5jbHVkZXMoJ0J1Y2tldE5vdGlmaWNhdGlvbnNIYW5kbGVyJykpIHtcbiAgICAgICAgICAgIE5hZ1N1cHByZXNzaW9ucy5hZGRSZXNvdXJjZVN1cHByZXNzaW9ucyhcbiAgICAgICAgICAgICAgbm9kZSxcbiAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGlkOiAnQXdzU29sdXRpb25zLUlBTTQnLFxuICAgICAgICAgICAgICAgICAgcmVhc29uOiAnVGhlIEJ1Y2tldE5vdGlmaWNhdGlvbnNIYW5kbGVyIExhbWJkYSBpcyBjcmVhdGVkIGJ5IENESyBhbmQgdXNlcyB0aGUgc3RhbmRhcmQgQVdTTGFtYmRhQmFzaWNFeGVjdXRpb25Sb2xlIG1hbmFnZWQgcG9saWN5LicsXG4gICAgICAgICAgICAgICAgICBhcHBsaWVzVG86IFsnUG9saWN5Ojphcm46PEFXUzo6UGFydGl0aW9uPjppYW06OmF3czpwb2xpY3kvc2VydmljZS1yb2xlL0FXU0xhbWJkYUJhc2ljRXhlY3V0aW9uUm9sZSddLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIFN1cHByZXNzIElBTU5vSW5saW5lUG9saWN5IGZvciB0aGUgQnVja2V0Tm90aWZpY2F0aW9uc0hhbmRsZXIgcG9saWN5XG4gICAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBpYW0uQ2ZuUG9saWN5ICYmIG5vZGUubm9kZS5wYXRoLmluY2x1ZGVzKCdCdWNrZXROb3RpZmljYXRpb25zSGFuZGxlcicpKSB7XG4gICAgICAgICAgICBOYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnMoXG4gICAgICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBpZDogJ05JU1QuODAwLjUzLlI1LUlBTU5vSW5saW5lUG9saWN5JyxcbiAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ1RoZSBCdWNrZXROb3RpZmljYXRpb25zSGFuZGxlciBMYW1iZGEgaXMgY3JlYXRlZCBieSBDREsgYW5kIHVzZXMgaW5saW5lIHBvbGljaWVzIGZvciBpdHMgY3VzdG9tIHJlc291cmNlIGltcGxlbWVudGF0aW9uLicsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBjZGstbmFnIGlzIG5vdCBpbnN0YWxsZWQ7IE5BRyBzdXBwcmVzc2lvbnMgd2lsbCBub3QgYmUgYXBwbGllZFxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE91dHB1dCB0aGUgYnVja2V0IG5hbWUsIGJ1Y2tldCBBUk4sIHF1ZXVlIG5hbWUsIGFuZCByb2xlIG5hbWUuXG4gICAgICogWW91IHdpbGwgbmVlZCB0aGVzZSB2YWx1ZXMgdG8gY29uZmlndXJlIENyb3dkU3RyaWtlIGNvbm5lY3RvcnMuXG4gICAgICovXG4gICAgbmV3IENmbk91dHB1dCh0aGlzLCAnQnVja2V0TmFtZScsIHtcbiAgICAgIHZhbHVlOiB0aGlzLmJ1Y2tldE5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSBOYW1lIG9mIHRoZSBTMyBidWNrZXQgZm9yIENyb3dkU3RyaWtlIGluZ2VzdGlvbicsXG4gICAgfSk7XG5cbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsICdCdWNrZXRBcm4nLCB7XG4gICAgICB2YWx1ZTogdGhpcy5idWNrZXRBcm4sXG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSBBUk4gb2YgdGhlIFMzIGJ1Y2tldCBmb3IgQ3Jvd2RTdHJpa2UgaW5nZXN0aW9uJyxcbiAgICB9KTtcblxuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgJ1F1ZXVlTmFtZScsIHtcbiAgICAgIHZhbHVlOiB0aGlzLnF1ZXVlLnF1ZXVlTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIE5hbWUgb2YgdGhlIFNRUyBxdWV1ZSBmb3IgQ3Jvd2RTdHJpa2UgaW5nZXN0aW9uJyxcbiAgICB9KTtcblxuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgJ1JvbGVOYW1lJywge1xuICAgICAgdmFsdWU6IHRoaXMucm9sZS5yb2xlTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIE5hbWUgb2YgdGhlIElBTSByb2xlIGZvciBDcm93ZFN0cmlrZSBpbmdlc3Rpb24nLFxuICAgIH0pO1xuICB9XG59XG4iXX0=