constructor()

in packages/constructs/L3/ai/gaia-l3-construct/lib/rag-engines/kendra-retrieval/index.ts [29:201]


  constructor(scope: Construct, id: string, props: KendraRetrievalProps) {
    super(scope, id, props);

    const createWorkflow = new CreateKendraWorkspace(this, 'CreateKendraWorkspace', {
      ...props,
      config: props.config,
      shared: props.shared,
      ragDynamoDBTables: props.ragDynamoDBTables,
    });

    if (props.config.rag?.engines.kendra?.createIndex) {
      const indexName = props.naming.resourceName('gaiachatbot-workspaces');

      const customDataSource = props.config.rag?.engines.kendra?.s3DataSourceConfig;
      let dataBucket: s3.IBucket;
      if (customDataSource !== undefined) {
        dataBucket = s3.Bucket.fromBucketName(this, 'CustomKedraDataBucket', customDataSource.bucketName);
      } else {
        dataBucket = new MdaaBucket(this, 'KendraDataBucket', {
          encryptionKey: props.encryptionKey,
          naming: props.naming,
          bucketName: `${props.naming.props.org}-${props.naming.props.domain}-${props.naming.props.env}-kendra-default-source-bucket`,
        });
      }

      MdaaNagSuppressions.addCodeResourceSuppressions(
        dataBucket,
        [
          { id: 'NIST.800.53.R5-S3BucketReplicationEnabled', reason: 'MDAA does not enforce bucket replication.' },
          { id: 'HIPAA.Security-S3BucketReplicationEnabled', reason: 'MDAA does not enforce bucket replication.' },
          { id: 'PCI.DSS.321-S3BucketReplicationEnabled', reason: 'MDAA does not enforce bucket replication.' },
        ],
        true,
      );

      const kendraRole = new MdaaRole(this, 'KendraRole', {
        naming: props.naming,
        assumedBy: new iam.ServicePrincipal('kendra.amazonaws.com'),
        roleName: 'KendraRole',
      });

      kendraRole.addToPolicy(
        new iam.PolicyStatement({
          actions: ['logs:*', 'cloudwatch:*'],
          resources: [`arn:aws:logs:${this.region}:${this.account}:log-group:/aws/kendra/*`],
        }),
      );

      dataBucket.grantRead(kendraRole);

      const kendraIndex = new kendra.CfnIndex(this, 'Index', {
        edition: 'DEVELOPER_EDITION',
        name: indexName,
        roleArn: kendraRole.roleArn,
        serverSideEncryptionConfiguration: {
          kmsKeyId: props.encryptionKey.keyId,
        },
        documentMetadataConfigurations: [
          {
            name: 'workspace_id',
            type: 'STRING_VALUE',
            search: {
              displayable: true,
              facetable: true,
              searchable: true,
            },
          },
          {
            name: 'document_type',
            type: 'STRING_VALUE',
            search: {
              displayable: true,
              facetable: true,
              searchable: true,
            },
          },
        ],
      });

      let s3DataSource: kendra.CfnDataSource;
      if (customDataSource !== undefined) {
        s3DataSource = new kendra.CfnDataSource(this, 'CustomKendraS3DataSource', {
          type: 'S3',
          name: 'CustomKendraS3DataSource',
          indexId: kendraIndex.ref,
          description: `S3 Data Source for Kendra Index for bucket ${customDataSource.bucketName}`,
          dataSourceConfiguration: {
            s3Configuration: {
              bucketName: customDataSource.bucketName,
              inclusionPrefixes: customDataSource.includedDirectories,
              documentsMetadataConfiguration: {
                s3Prefix:
                  customDataSource?.metadataDirectory !== undefined ? customDataSource.metadataDirectory : 'metadata',
              },
            },
          },
          roleArn: kendraRole.roleArn,
        });
        kendraRole.addToPolicy(
          new iam.PolicyStatement({
            actions: ['kms:Decrypt', 'kms:GenerateDataKey', 'kms:DescribeKey'],
            resources: [customDataSource.kmsKeyArn],
          }),
        );
      } else {
        s3DataSource = new kendra.CfnDataSource(this, 'DefaultKendraS3DataSource', {
          type: 'S3',
          name: 'DefaultKendraS3DataSource',
          indexId: kendraIndex.ref,
          description: 'S3 Data Source for Kendra Index',
          dataSourceConfiguration: {
            s3Configuration: {
              bucketName: dataBucket.bucketName,
              inclusionPrefixes: ['documents'],
              documentsMetadataConfiguration: {
                s3Prefix: 'metadata',
              },
            },
          },
          roleArn: kendraRole.roleArn,
        });
      }

      kendraRole.addToPolicy(
        new iam.PolicyStatement({
          actions: ['kendra:BatchDeleteDocument'],
          resources: [kendraIndex.attrArn, s3DataSource.attrArn],
        }),
      );

      MdaaNagSuppressions.addCodeResourceSuppressions(
        kendraRole,
        [
          {
            id: 'AwsSolutions-IAM5',
            reason:
              'DDB index names not known at deployment time. KMS Permissions are appropriately scoped. S3 Bucket managed and dedicated to Kendra index',
          },
          {
            id: 'NIST.800.53.R5-IAMNoInlinePolicy',
            reason: 'Permissions are role specific. Inline policy use appropriate.',
          },
          {
            id: 'HIPAA.Security-IAMNoInlinePolicy',
            reason: 'Permissions are role specific. Inline policy use appropriate.',
          },
          {
            id: 'PCI.DSS.321-IAMNoInlinePolicy',
            reason: 'Permissions are role specific. Inline policy use appropriate.',
          },
          {
            id: 'NIST.800.53.R5-IAMPolicyNoStatementsWithFullAccess',
            reason: 'Permission bound by cloudwatch namespace.  Other policies further restrict log group access',
          },
          {
            id: 'HIPAA.Security-IAMPolicyNoStatementsWithFullAccess',
            reason: 'Permission bound by cloudwatch namespace.  Other policies further restrict log group access',
          },
          {
            id: 'PCI.DSS.321-IAMPolicyNoStatementsWithFullAccess',
            reason: 'Permission bound by cloudwatch namespace.  Other policies further restrict log group access',
          },
        ],
        true,
      );

      this.kendraIndex = kendraIndex;
      this.kendraS3DataSource = s3DataSource;
      this.kendraS3DataSourceBucket = dataBucket;
    }

    this.createKendraWorkspaceWorkflow = createWorkflow.stateMachine;
  }