UNPKG

@aws-solutions-constructs/core

Version:
217 lines 29.8 kB
"use strict"; /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * with the License. A copy of the License is located at * * http://www.apache.org/licenses/LICENSE-2.0 * * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * and limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.buildKendraIndex = buildKendraIndex; exports.AddMultipleKendraDataSources = AddMultipleKendraDataSources; exports.AddKendraDataSource = AddKendraDataSource; exports.normalizeKendraPermissions = normalizeKendraPermissions; /* * The functions found here in the core library are for internal use and can be changed * or removed outside of a major release. We recommend against calling them directly from client code. */ const kendra = require("aws-cdk-lib/aws-kendra"); const iam = require("aws-cdk-lib/aws-iam"); const utils_1 = require("./utils"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const kendra_defaults_1 = require("./kendra-defaults"); /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ function buildKendraIndex(scope, id, props) { // Conditional lambda function creation if (props.existingIndexObj) { // The client provided an Index, so we'll do nothing and return it to them return props.existingIndexObj; } else { let indexRoleArn = ""; // If the client provided a role, then don't bother creating a new one that we don't need if (!props.kendraIndexProps?.roleArn) { indexRoleArn = CreateKendraIndexLoggingRole(scope, id); } const defaultIndexProperties = (0, kendra_defaults_1.DefaultKendraIndexProps)(id, indexRoleArn); const consolidatedIndexProperties = (0, utils_1.consolidateProps)(defaultIndexProperties, props.kendraIndexProps); const newIndex = new kendra.CfnIndex(scope, `kendra-index-${id}`, consolidatedIndexProperties); (0, utils_1.addCfnSuppressRules)(newIndex, [{ id: "W80", reason: "We consulted the Kendra TFC and they confirmed the default encryption is sufficient for general use cases" }]); return newIndex; } } /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ function AddMultipleKendraDataSources(scope, id, kendraIndex, clientDataSourceProps) { const returnDataSources = []; clientDataSourceProps.forEach((props, index) => { returnDataSources.push(AddKendraDataSource(scope, `${id}${index}`, kendraIndex, props)); }); return returnDataSources; } /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ function AddKendraDataSource(scope, id, index, clientDataSourceProps) { if (clientDataSourceProps.type === 'S3') { return CreateS3DataSource(scope, index, id, clientDataSourceProps); } else { if (clientDataSourceProps.indexId) { throw new Error('Invalid DataSource prop specified - Construct must set the indexId prop'); } return new kendra.CfnDataSource(scope, `kendra-data-source-${id}`, { ...clientDataSourceProps, indexId: index.attrId }); } } function CreateS3DataSource(scope, targetIndex, id, clientProps) { // We go through some hoops here to extract the various inputs, because we need to narrow // the type to remove the union with IResolvable const dataSourceConfig = clientProps.dataSourceConfiguration; if (!dataSourceConfig) { throw new Error('Error - an S3 Kendra DataSource requires an DataSourceConfiguration prop'); } const s3DataSourceConfig = dataSourceConfig.s3Configuration; if (!s3DataSourceConfig) { throw new Error('Error - an S3 Kendra DataSource requires an DataSourceConfiguration.S3Configuration prop'); } // No Bucket name is an error if (!s3DataSourceConfig.bucketName) { throw new Error('Error - an S3 Kendra DataSource requires the DataSourceConfiguration.S3Configuration.bucketName prop'); } // If there's no role, make a role and put it into defaultProps // Put bucket name in default props let defaultProps = { indexId: targetIndex.ref, name: (0, utils_1.generatePhysicalKendraIndexName)('', ['s3-datasource', id]), type: 'S3' }; // Return consolidated default and user props if (!clientProps.roleArn) { const s3CrawlPolicy = new iam.PolicyDocument({ statements: [ new iam.PolicyStatement({ actions: [ "s3:GetObject" ], resources: [ `arn:aws:s3:::${s3DataSourceConfig.bucketName}/*` ], effect: iam.Effect.ALLOW }), new iam.PolicyStatement({ actions: [ "s3:ListBucket" ], resources: [ `arn:aws:s3:::${s3DataSourceConfig.bucketName}` ], effect: iam.Effect.ALLOW }), new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ "kendra:BatchPutDocument", "kendra:BatchDeleteDocument" ], resources: [ targetIndex.attrArn ] }), ] }); const dataSourceRole = new iam.Role(scope, `data-source-role-${id}`, { assumedBy: new iam.ServicePrincipal('kendra.amazonaws.com'), description: 'Policy for Kendra S3 Data Source', inlinePolicies: { s3CrawlPolicy, }, }); defaultProps = (0, utils_1.overrideProps)(defaultProps, { roleArn: dataSourceRole.roleArn }); (0, utils_1.addCfnGuardSuppressRules)(dataSourceRole, ["IAM_NO_INLINE_POLICY_CHECK"]); } const consolidatedProps = (0, utils_1.consolidateProps)(defaultProps, clientProps); return new kendra.CfnDataSource(scope, `data-source-${id}`, consolidatedProps); } function CreateKendraIndexLoggingRole(scope, id) { const allowKendraToLogPolicy = new iam.PolicyDocument({ statements: [ new iam.PolicyStatement({ resources: ['*'], actions: [ "cloudwatch:PutMetricData" ], effect: iam.Effect.ALLOW, conditions: { StringEquals: { "cloudwatch:namespace": "AWS/Kendra" } } }), new iam.PolicyStatement({ resources: [`arn:aws:logs:${aws_cdk_lib_1.Aws.REGION}:${aws_cdk_lib_1.Aws.ACCOUNT_ID}:log-group:/aws/kendra/*`], actions: [ "logs:CreateLogGroup" ], effect: iam.Effect.ALLOW, }), new iam.PolicyStatement({ resources: [`arn:${aws_cdk_lib_1.Aws.PARTITION}:logs:${aws_cdk_lib_1.Aws.REGION}:${aws_cdk_lib_1.Aws.ACCOUNT_ID}:log-group:/aws/kendra/*`], actions: [ "logs:DescribeLogGroups" ], effect: iam.Effect.ALLOW, }), new iam.PolicyStatement({ resources: [`arn:${aws_cdk_lib_1.Aws.PARTITION}:logs:${aws_cdk_lib_1.Aws.REGION}:${aws_cdk_lib_1.Aws.ACCOUNT_ID}:log-group:/aws/kendra/*:log-stream:*`], actions: [ 'logs:CreateLogStream', 'logs:PutLogEvents', 'logs:DescribeLogStream', ], effect: iam.Effect.ALLOW, }), ], }); const indexRole = new iam.Role(scope, `kendra-index-role-${id}`, { assumedBy: new iam.ServicePrincipal('kendra.amazonaws.com'), description: 'Allow Kendra index to write CloudWatch Logs', inlinePolicies: { AllowLogging: allowKendraToLogPolicy, }, }); (0, utils_1.addCfnSuppressRules)(indexRole, [{ id: "W11", reason: "PutMetricData does not allow resource specification, " + "scope is narrowed by the namespace condition. " + "https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazoncloudwatch.html" }]); (0, utils_1.addCfnGuardSuppressRules)(indexRole, ["IAM_NO_INLINE_POLICY_CHECK"]); return indexRole.roleArn; } // @summary Confirm each entry is a correct value, uppercase each entry function normalizeKendraPermissions(rawPermissions) { const validPermissions = ["READ", "SUBMITFEEDBACK", "WRITE"]; const result = rawPermissions.map((s) => { const upperCaseValue = s.toUpperCase(); if (!validPermissions.includes(upperCaseValue)) { throw new Error(`Invalid indexPermission value - valid values are "READ", "SUBMITFEEDBACK" and "WRITE"`); } return upperCaseValue; }); return result; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2VuZHJhLWhlbHBlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImtlbmRyYS1oZWxwZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7OztHQVdHOztBQTZCSCw0Q0F3QkM7QUFLRCxvRUFVQztBQUtELGtEQWVDO0FBaUpELGdFQVdDO0FBbFBEOzs7R0FHRztBQUVILGlEQUFpRDtBQUNqRCwyQ0FBMkM7QUFDM0MsbUNBQTBJO0FBQzFJLDZDQUFrQztBQUlsQyx1REFBNEQ7QUFZNUQ7O0dBRUc7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUE0QjtJQUN6Rix1Q0FBdUM7SUFDdkMsSUFBSSxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUMzQiwwRUFBMEU7UUFDMUUsT0FBTyxLQUFLLENBQUMsZ0JBQWdCLENBQUM7SUFDaEMsQ0FBQztTQUFNLENBQUM7UUFFTixJQUFJLFlBQVksR0FBVyxFQUFFLENBQUM7UUFFOUIseUZBQXlGO1FBQ3pGLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsT0FBTyxFQUFFLENBQUM7WUFDckMsWUFBWSxHQUFHLDRCQUE0QixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBQ0QsTUFBTSxzQkFBc0IsR0FBRyxJQUFBLHlDQUF1QixFQUFDLEVBQUUsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUV6RSxNQUFNLDJCQUEyQixHQUFHLElBQUEsd0JBQWdCLEVBQUMsc0JBQXNCLEVBQUUsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDckcsTUFBTSxRQUFRLEdBQUcsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLEVBQUUsMkJBQTJCLENBQUMsQ0FBQztRQUMvRixJQUFBLDJCQUFtQixFQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUM3QixFQUFFLEVBQUUsS0FBSztnQkFDVCxN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QUM7SUFDSCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiAgQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIikuIFlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqICB3aXRoIHRoZSBMaWNlbnNlLiBBIGNvcHkgb2YgdGhlIExpY2Vuc2UgaXMgbG9jYXRlZCBhdFxuICpcbiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogIG9yIGluIHRoZSAnbGljZW5zZScgZmlsZSBhY2NvbXBhbnlpbmcgdGhpcyBmaWxlLiBUaGlzIGZpbGUgaXMgZGlzdHJpYnV0ZWQgb24gYW4gJ0FTIElTJyBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTXG4gKiAgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZXhwcmVzcyBvciBpbXBsaWVkLiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnNcbiAqICBhbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLypcbiAqICBUaGUgZnVuY3Rpb25zIGZvdW5kIGhlcmUgaW4gdGhlIGNvcmUgbGlicmFyeSBhcmUgZm9yIGludGVybmFsIHVzZSBhbmQgY2FuIGJlIGNoYW5nZWRcbiAqICBvciByZW1vdmVkIG91dHNpZGUgb2YgYSBtYWpvciByZWxlYXNlLiBXZSByZWNvbW1lbmQgYWdhaW5zdCBjYWxsaW5nIHRoZW0gZGlyZWN0bHkgZnJvbSBjbGllbnQgY29kZS5cbiAqL1xuXG5pbXBvcnQgKiBhcyBrZW5kcmEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWtlbmRyYSc7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgeyBhZGRDZm5HdWFyZFN1cHByZXNzUnVsZXMsIGFkZENmblN1cHByZXNzUnVsZXMsIGNvbnNvbGlkYXRlUHJvcHMsIGdlbmVyYXRlUGh5c2ljYWxLZW5kcmFJbmRleE5hbWUsIG92ZXJyaWRlUHJvcHMgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgQXdzIH0gZnJvbSAnYXdzLWNkay1saWInO1xuXG4vLyBOb3RlOiBUbyBlbnN1cmUgQ0RLdjIgY29tcGF0aWJpbGl0eSwga2VlcCB0aGUgaW1wb3J0IHN0YXRlbWVudCBmb3IgQ29uc3RydWN0IHNlcGFyYXRlXG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IERlZmF1bHRLZW5kcmFJbmRleFByb3BzIH0gZnJvbSAnLi9rZW5kcmEtZGVmYXVsdHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkS2VuZHJhSW5kZXhQcm9wcyB7XG4gIHJlYWRvbmx5IGtlbmRyYUluZGV4UHJvcHM/OiBrZW5kcmEuQ2ZuSW5kZXhQcm9wcyB8IGFueTtcbiAgLyoqXG4gICAqIEV4aXN0aW5nIGluc3RhbmNlIG9mIEtlbmRyYSBJbmRleCBvYmplY3QsIFByb3ZpZGluZyBib3RoIHRoaXMgYW5kIGtlbmRyYUluZGV4UHJvcHMgd2lsbCBjYXVzZSBhbiBlcnJvci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBOb25lXG4gICAqL1xuICByZWFkb25seSBleGlzdGluZ0luZGV4T2JqPzoga2VuZHJhLkNmbkluZGV4O1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbCBUaGlzIGlzIGFuIGludGVybmFsIGNvcmUgZnVuY3Rpb24gYW5kIHNob3VsZCBub3QgYmUgY2FsbGVkIGRpcmVjdGx5IGJ5IFNvbHV0aW9ucyBDb25zdHJ1Y3RzIGNsaWVudHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZEtlbmRyYUluZGV4KHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBCdWlsZEtlbmRyYUluZGV4UHJvcHMpOiBrZW5kcmEuQ2ZuSW5kZXgge1xuICAvLyBDb25kaXRpb25hbCBsYW1iZGEgZnVuY3Rpb24gY3JlYXRpb25cbiAgaWYgKHByb3BzLmV4aXN0aW5nSW5kZXhPYmopIHtcbiAgICAvLyBUaGUgY2xpZW50IHByb3ZpZGVkIGFuIEluZGV4LCBzbyB3ZSdsbCBkbyBub3RoaW5nIGFuZCByZXR1cm4gaXQgdG8gdGhlbVxuICAgIHJldHVybiBwcm9wcy5leGlzdGluZ0luZGV4T2JqO1xuICB9IGVsc2Uge1xuXG4gICAgbGV0IGluZGV4Um9sZUFybjogc3RyaW5nID0gXCJcIjtcblxuICAgIC8vIElmIHRoZSBjbGllbnQgcHJvdmlkZWQgYSByb2xlLCB0aGVuIGRvbid0IGJvdGhlciBjcmVhdGluZyBhIG5ldyBvbmUgdGhhdCB3ZSBkb24ndCBuZWVkXG4gICAgaWYgKCFwcm9wcy5rZW5kcmFJbmRleFByb3BzPy5yb2xlQXJuKSB7XG4gICAgICBpbmRleFJvbGVBcm4gPSBDcmVhdGVLZW5kcmFJbmRleExvZ2dpbmdSb2xlKHNjb3BlLCBpZCk7XG4gICAgfVxuICAgIGNvbnN0IGRlZmF1bHRJbmRleFByb3BlcnRpZXMgPSBEZWZhdWx0S2VuZHJhSW5kZXhQcm9wcyhpZCwgaW5kZXhSb2xlQXJuKTtcblxuICAgIGNvbnN0IGNvbnNvbGlkYXRlZEluZGV4UHJvcGVydGllcyA9IGNvbnNvbGlkYXRlUHJvcHMoZGVmYXVsdEluZGV4UHJvcGVydGllcywgcHJvcHMua2VuZHJhSW5kZXhQcm9wcyk7XG4gICAgY29uc3QgbmV3SW5kZXggPSBuZXcga2VuZHJhLkNmbkluZGV4KHNjb3BlLCBga2VuZHJhLWluZGV4LSR7aWR9YCwgY29uc29saWRhdGVkSW5kZXhQcm9wZXJ0aWVzKTtcbiAgICBhZGRDZm5TdXBwcmVzc1J1bGVzKG5ld0luZGV4LCBbe1xuICAgICAgaWQ6IFwiVzgwXCIsXG4gICAgICByZWFzb246IFwiV2UgY29uc3VsdGVkIHRoZSBLZW5kcmEgVEZDIGFuZCB0aGV5IGNvbmZpcm1lZCB0aGUgZGVmYXVsdCBlbmNyeXB0aW9uIGlzIHN1ZmZpY2llbnQgZm9yIGdlbmVyYWwgdXNlIGNhc2VzXCJcbiAgICB9XSk7XG5cbiAgICByZXR1cm4gbmV3SW5kZXg7XG4gIH1cbn1cblxuLyoqXG4gKiBAaW50ZXJuYWwgVGhpcyBpcyBhbiBpbnRlcm5hbCBjb3JlIGZ1bmN0aW9uIGFuZCBzaG91bGQgbm90IGJlIGNhbGxlZCBkaXJlY3RseSBieSBTb2x1dGlvbnMgQ29uc3RydWN0cyBjbGllbnRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQWRkTXVsdGlwbGVLZW5kcmFEYXRhU291cmNlcyhzY29wZTogQ29uc3RydWN0LFxuICBpZDogc3RyaW5nLFxuICBrZW5kcmFJbmRleDoga2VuZHJhLkNmbkluZGV4LFxuICBjbGllbnREYXRhU291cmNlUHJvcHM6IFBhcnRpYWw8a2VuZHJhLkNmbkRhdGFTb3VyY2VQcm9wcz5bXSk6IGtlbmRyYS5DZm5EYXRhU291cmNlW10ge1xuXG4gIGNvbnN0IHJldHVybkRhdGFTb3VyY2VzOiBrZW5kcmEuQ2ZuRGF0YVNvdXJjZVtdID0gW107XG4gIGNsaWVudERhdGFTb3VyY2VQcm9wcy5mb3JFYWNoKChwcm9wcywgaW5kZXgpID0+IHtcbiAgICByZXR1cm5EYXRhU291cmNlcy5wdXNoKEFkZEtlbmRyYURhdGFTb3VyY2Uoc2NvcGUsIGAke2lkfSR7aW5kZXh9YCwga2VuZHJhSW5kZXgsIHByb3BzKSk7XG4gIH0pO1xuICByZXR1cm4gcmV0dXJuRGF0YVNvdXJjZXM7XG59XG5cbi8qKlxuICogQGludGVybmFsIFRoaXMgaXMgYW4gaW50ZXJuYWwgY29yZSBmdW5jdGlvbiBhbmQgc2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkgYnkgU29sdXRpb25zIENvbnN0cnVjdHMgY2xpZW50cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEFkZEtlbmRyYURhdGFTb3VyY2Uoc2NvcGU6IENvbnN0cnVjdCxcbiAgaWQ6IHN0cmluZywgaW5kZXg6IGtlbmRyYS5DZm5JbmRleCxcbiAgY2xpZW50RGF0YVNvdXJjZVByb3BzOiBrZW5kcmEuQ2ZuRGF0YVNvdXJjZVByb3BzIHwgYW55KToga2VuZHJhLkNmbkRhdGFTb3VyY2Uge1xuXG4gIGlmICAoY2xpZW50RGF0YVNvdXJjZVByb3BzLnR5cGUgPT09ICdTMycpIHtcbiAgICByZXR1cm4gQ3JlYXRlUzNEYXRhU291cmNlKHNjb3BlLCBpbmRleCwgaWQsIGNsaWVudERhdGFTb3VyY2VQcm9wcyk7XG4gIH0gZWxzZSB7XG4gICAgaWYgKGNsaWVudERhdGFTb3VyY2VQcm9wcy5pbmRleElkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgRGF0YVNvdXJjZSBwcm9wIHNwZWNpZmllZCAtIENvbnN0cnVjdCBtdXN0IHNldCB0aGUgaW5kZXhJZCBwcm9wJyk7XG4gICAgfVxuICAgIHJldHVybiBuZXcga2VuZHJhLkNmbkRhdGFTb3VyY2Uoc2NvcGUsIGBrZW5kcmEtZGF0YS1zb3VyY2UtJHtpZH1gLCB7XG4gICAgICAuLi5jbGllbnREYXRhU291cmNlUHJvcHMsXG4gICAgICBpbmRleElkOiBpbmRleC5hdHRySWRcbiAgICB9KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBDcmVhdGVTM0RhdGFTb3VyY2Uoc2NvcGU6IENvbnN0cnVjdCxcbiAgdGFyZ2V0SW5kZXg6IGtlbmRyYS5DZm5JbmRleCxcbiAgaWQ6IHN0cmluZyxcbiAgY2xpZW50UHJvcHM6IFBhcnRpYWw8a2VuZHJhLkNmbkRhdGFTb3VyY2VQcm9wcz4pOiBrZW5kcmEuQ2ZuRGF0YVNvdXJjZSB7XG5cbiAgLy8gV2UgZ28gdGhyb3VnaCBzb21lIGhvb3BzIGhlcmUgdG8gZXh0cmFjdCB0aGUgdmFyaW91cyBpbnB1dHMsIGJlY2F1c2Ugd2UgbmVlZCB0byBuYXJyb3dcbiAgLy8gdGhlIHR5cGUgdG8gcmVtb3ZlIHRoZSB1bmlvbiB3aXRoIElSZXNvbHZhYmxlXG4gIGNvbnN0IGRhdGFTb3VyY2VDb25maWcgPSBjbGllbnRQcm9wcy5kYXRhU291cmNlQ29uZmlndXJhdGlvbiBhcyBrZW5kcmEuQ2ZuRGF0YVNvdXJjZS5EYXRhU291cmNlQ29uZmlndXJhdGlvblByb3BlcnR5O1xuICBpZiAoIWRhdGFTb3VyY2VDb25maWcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0Vycm9yIC0gYW4gUzMgS2VuZHJhIERhdGFTb3VyY2UgcmVxdWlyZXMgYW4gRGF0YVNvdXJjZUNvbmZpZ3VyYXRpb24gcHJvcCcpO1xuICB9XG5cbiAgY29uc3QgczNEYXRhU291cmNlQ29uZmlnID0gZGF0YVNvdXJjZUNvbmZpZy5zM0NvbmZpZ3VyYXRpb24gYXMga2VuZHJhLkNmbkRhdGFTb3VyY2UuUzNEYXRhU291cmNlQ29uZmlndXJhdGlvblByb3BlcnR5O1xuXG4gIGlmICghczNEYXRhU291cmNlQ29uZmlnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdFcnJvciAtIGFuIFMzIEtlbmRyYSBEYXRhU291cmNlIHJlcXVpcmVzIGFuIERhdGFTb3VyY2VDb25maWd1cmF0aW9uLlMzQ29uZmlndXJhdGlvbiBwcm9wJyk7XG4gIH1cblxuICAvLyBObyBCdWNrZXQgbmFtZSBpcyBhbiBlcnJvclxuICBpZiAoIXMzRGF0YVNvdXJjZUNvbmZpZy5idWNrZXROYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdFcnJvciAtIGFuIFMzIEtlbmRyYSBEYXRhU291cmNlIHJlcXVpcmVzIHRoZSBEYXRhU291cmNlQ29uZmlndXJhdGlvbi5TM0NvbmZpZ3VyYXRpb24uYnVja2V0TmFtZSBwcm9wJyk7XG4gIH1cblxuICAvLyBJZiB0aGVyZSdzIG5vIHJvbGUsIG1ha2UgYSByb2xlIGFuZCBwdXQgaXQgaW50byBkZWZhdWx0UHJvcHNcbiAgLy8gUHV0IGJ1Y2tldCBuYW1lIGluIGRlZmF1bHQgcHJvcHNcbiAgbGV0IGRlZmF1bHRQcm9wczoga2VuZHJhLkNmbkRhdGFTb3VyY2VQcm9wcyA9IHtcbiAgICBpbmRleElkOiB0YXJnZXRJbmRleC5yZWYsXG4gICAgbmFtZTogZ2VuZXJhdGVQaHlzaWNhbEtlbmRyYUluZGV4TmFtZSgnJywgWydzMy1kYXRhc291cmNlJywgaWRdKSxcbiAgICB0eXBlOiAnUzMnXG4gIH07XG5cbiAgLy8gUmV0dXJuIGNvbnNvbGlkYXRlZCBkZWZhdWx0IGFuZCB1c2VyIHByb3BzXG4gIGlmICghY2xpZW50UHJvcHMucm9sZUFybikge1xuICAgIGNvbnN0IHMzQ3Jhd2xQb2xpY3kgPSBuZXcgaWFtLlBvbGljeURvY3VtZW50KHtcbiAgICAgIHN0YXRlbWVudHM6IFtcbiAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgIFwiczM6R2V0T2JqZWN0XCJcbiAgICAgICAgICBdLFxuICAgICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgICAgYGFybjphd3M6czM6Ojoke3MzRGF0YVNvdXJjZUNvbmZpZy5idWNrZXROYW1lfS8qYFxuICAgICAgICAgIF0sXG4gICAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XXG4gICAgICAgIH0pLFxuICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgICAgXCJzMzpMaXN0QnVja2V0XCJcbiAgICAgICAgICBdLFxuICAgICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgICAgYGFybjphd3M6czM6Ojoke3MzRGF0YVNvdXJjZUNvbmZpZy5idWNrZXROYW1lfWBcbiAgICAgICAgICBdLFxuICAgICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPV1xuICAgICAgICB9KSxcbiAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgICBcImtlbmRyYTpCYXRjaFB1dERvY3VtZW50XCIsXG4gICAgICAgICAgICBcImtlbmRyYTpCYXRjaERlbGV0ZURvY3VtZW50XCJcbiAgICAgICAgICBdLFxuICAgICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgICAgdGFyZ2V0SW5kZXguYXR0ckFyblxuICAgICAgICAgIF1cbiAgICAgICAgfSksXG4gICAgICBdXG4gICAgfSk7XG5cbiAgICBjb25zdCBkYXRhU291cmNlUm9sZTogaWFtLlJvbGUgPSBuZXcgaWFtLlJvbGUoc2NvcGUsIGBkYXRhLXNvdXJjZS1yb2xlLSR7aWR9YCwge1xuICAgICAgYXNzdW1lZEJ5OiBuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoJ2tlbmRyYS5hbWF6b25hd3MuY29tJyksXG4gICAgICBkZXNjcmlwdGlvbjogJ1BvbGljeSBmb3IgS2VuZHJhIFMzIERhdGEgU291cmNlJyxcbiAgICAgIGlubGluZVBvbGljaWVzOiB7XG4gICAgICAgIHMzQ3Jhd2xQb2xpY3ksXG4gICAgICB9LFxuICAgIH0pO1xuICAgIGRlZmF1bHRQcm9wcyA9IG92ZXJyaWRlUHJvcHMoZGVmYXVsdFByb3BzLCB7IHJvbGVBcm46IGRhdGFTb3VyY2VSb2xlLnJvbGVBcm4gfSk7XG4gICAgYWRkQ2ZuR3VhcmRTdXBwcmVzc1J1bGVzKGRhdGFTb3VyY2VSb2xlLCBbXCJJQU1fTk9fSU5MSU5FX1BPTElDWV9DSEVDS1wiXSk7XG4gIH1cblxuICBjb25zdCBjb25zb2xpZGF0ZWRQcm9wczoga2VuZHJhLkNmbkRhdGFTb3VyY2VQcm9wcyA9IGNvbnNvbGlkYXRlUHJvcHMoZGVmYXVsdFByb3BzLCBjbGllbnRQcm9wcyk7XG5cbiAgcmV0dXJuIG5ldyBrZW5kcmEuQ2ZuRGF0YVNvdXJjZShzY29wZSwgYGRhdGEtc291cmNlLSR7aWR9YCwgY29uc29saWRhdGVkUHJvcHMpO1xuXG59XG5cbmZ1bmN0aW9uIENyZWF0ZUtlbmRyYUluZGV4TG9nZ2luZ1JvbGUoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGFsbG93S2VuZHJhVG9Mb2dQb2xpY3kgPSBuZXcgaWFtLlBvbGljeURvY3VtZW50KHtcbiAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICBcImNsb3Vkd2F0Y2g6UHV0TWV0cmljRGF0YVwiXG4gICAgICAgIF0sXG4gICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgY29uZGl0aW9uczoge1xuICAgICAgICAgIFN0cmluZ0VxdWFsczoge1xuICAgICAgICAgICAgXCJjbG91ZHdhdGNoOm5hbWVzcGFjZVwiOiBcIkFXUy9LZW5kcmFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSksXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIHJlc291cmNlczogW2Bhcm46YXdzOmxvZ3M6JHtBd3MuUkVHSU9OfToke0F3cy5BQ0NPVU5UX0lEfTpsb2ctZ3JvdXA6L2F3cy9rZW5kcmEvKmBdLFxuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgXCJsb2dzOkNyZWF0ZUxvZ0dyb3VwXCJcbiAgICAgICAgXSxcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgfSksXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIHJlc291cmNlczogW2Bhcm46JHtBd3MuUEFSVElUSU9OfTpsb2dzOiR7QXdzLlJFR0lPTn06JHtBd3MuQUNDT1VOVF9JRH06bG9nLWdyb3VwOi9hd3Mva2VuZHJhLypgXSxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgIFwibG9nczpEZXNjcmliZUxvZ0dyb3Vwc1wiXG4gICAgICAgIF0sXG4gICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgIH0pLFxuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICByZXNvdXJjZXM6IFtgYXJuOiR7QXdzLlBBUlRJVElPTn06bG9nczoke0F3cy5SRUdJT059OiR7QXdzLkFDQ09VTlRfSUR9OmxvZy1ncm91cDovYXdzL2tlbmRyYS8qOmxvZy1zdHJlYW06KmBdLFxuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgJ2xvZ3M6Q3JlYXRlTG9nU3RyZWFtJyxcbiAgICAgICAgICAnbG9nczpQdXRMb2dFdmVudHMnLFxuICAgICAgICAgICdsb2dzOkRlc2NyaWJlTG9nU3RyZWFtJyxcbiAgICAgICAgXSxcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgfSksXG4gICAgXSxcbiAgfSk7XG5cbiAgY29uc3QgaW5kZXhSb2xlOiBpYW0uUm9sZSA9IG5ldyBpYW0uUm9sZShzY29wZSwgYGtlbmRyYS1pbmRleC1yb2xlLSR7aWR9YCwge1xuICAgIGFzc3VtZWRCeTogbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdrZW5kcmEuYW1hem9uYXdzLmNvbScpLFxuICAgIGRlc2NyaXB0aW9uOiAnQWxsb3cgS2VuZHJhIGluZGV4IHRvIHdyaXRlIENsb3VkV2F0Y2ggTG9ncycsXG4gICAgaW5saW5lUG9saWNpZXM6IHtcbiAgICAgIEFsbG93TG9nZ2luZzogYWxsb3dLZW5kcmFUb0xvZ1BvbGljeSxcbiAgICB9LFxuICB9KTtcbiAgYWRkQ2ZuU3VwcHJlc3NSdWxlcyhpbmRleFJvbGUsIFt7XG4gICAgaWQ6IFwiVzExXCIsXG4gICAgcmVhc29uOiBcIlB1dE1ldHJpY0RhdGEgZG9lcyBub3QgYWxsb3cgcmVzb3VyY2Ugc3BlY2lmaWNhdGlvbiwgXCIgK1xuICAgICAgXCJzY29wZSBpcyBuYXJyb3dlZCBieSB0aGUgbmFtZXNwYWNlIGNvbmRpdGlvbi4gXCIgK1xuICAgICAgXCJodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vc2VydmljZS1hdXRob3JpemF0aW9uL2xhdGVzdC9yZWZlcmVuY2UvbGlzdF9hbWF6b25jbG91ZHdhdGNoLmh0bWxcIlxuICB9XSk7XG4gIGFkZENmbkd1YXJkU3VwcHJlc3NSdWxlcyhpbmRleFJvbGUsIFtcIklBTV9OT19JTkxJTkVfUE9MSUNZX0NIRUNLXCJdKTtcblxuICByZXR1cm4gaW5kZXhSb2xlLnJvbGVBcm47XG59XG5cbi8vIEBzdW1tYXJ5IENvbmZpcm0gZWFjaCBlbnRyeSBpcyBhIGNvcnJlY3QgdmFsdWUsIHVwcGVyY2FzZSBlYWNoIGVudHJ5XG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplS2VuZHJhUGVybWlzc2lvbnMocmF3UGVybWlzc2lvbnM6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICBjb25zdCB2YWxpZFBlcm1pc3Npb25zID0gW1wiUkVBRFwiLCBcIlNVQk1JVEZFRURCQUNLXCIsIFwiV1JJVEVcIl07XG5cbiAgY29uc3QgcmVzdWx0ID0gcmF3UGVybWlzc2lvbnMubWFwPHN0cmluZz4oKHMpID0+IHtcbiAgICBjb25zdCB1cHBlckNhc2VWYWx1ZSA9IHMudG9VcHBlckNhc2UoKTtcbiAgICBpZiAoIXZhbGlkUGVybWlzc2lvbnMuaW5jbHVkZXModXBwZXJDYXNlVmFsdWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgaW5kZXhQZXJtaXNzaW9uIHZhbHVlIC0gdmFsaWQgdmFsdWVzIGFyZSBcIlJFQURcIiwgXCJTVUJNSVRGRUVEQkFDS1wiIGFuZCBcIldSSVRFXCJgKTtcbiAgICB9XG4gICAgcmV0dXJuIHVwcGVyQ2FzZVZhbHVlO1xuICB9KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cbiJdfQ==