private createClusterUsers()

in packages/constructs/L3/analytics/datawarehouse-l3-construct/lib/datawarehouse-l3-construct.ts [541:672]


  private createClusterUsers(cluster: Cluster, warehouseKmsKey: MdaaKmsKey) {
    this.props.databaseUsers?.forEach(databaseUser => {
      //Redshift is going to force usernames to lower case.
      //Need to make sure username matches between cluster and secret contents.
      const username = databaseUser.userName.toLowerCase();
      if (username != databaseUser.userName) {
        console.log(`Modified configured username ${databaseUser.userName} to ${username} for Redshift compatability`);
      }
      const userProps: UserProps = {
        cluster: cluster,
        databaseName: databaseUser.dbName,
        username: username,
        adminUser: cluster.secret,
        encryptionKey: warehouseKmsKey,
        excludeCharacters: databaseUser.excludeCharacters,
      };
      const user = new User(this.scope, 'redshiftdbserviceuser-' + username, userProps);

      new StringParameter(user, 'ssmsecret' + username, {
        parameterName: this.props.naming.ssmPath(`datawarehouse/secret/${username}`, false),
        stringValue: user.secret.secretName,
      }); // This causes param collision with two warehouses in the same domain

      new StringParameter(user, 'ssmsecretarn' + username, {
        parameterName: this.props.naming.ssmPath(`datawarehouse/secretarn/${username}`, false),
        stringValue: user.secret.secretArn,
      }); // This causes param collision with two warehouses in the same domain

      //Redshift DatabaseSecret construct does not currently set the masterarn on the secret string,
      //which is required by the multi user rotation function
      const cfnUserSecret = user.secret.node.defaultChild as CfnSecret;
      const secretStringTemplateString = (cfnUserSecret.generateSecretString as CfnSecret.GenerateSecretStringProperty)
        .secretStringTemplate;
      const secretStringTemplate = secretStringTemplateString ? JSON.parse(secretStringTemplateString) : undefined;
      const secretStringTemplateWithMasterArn = {
        ...secretStringTemplate,
        masterarn: cluster.secret?.secretArn,
      };
      cfnUserSecret.addPropertyOverride(
        'GenerateSecretString.SecretStringTemplate',
        JSON.stringify(secretStringTemplateWithMasterArn),
      );

      if (databaseUser.secretRotationDays > 0) {
        const multiUserRotationOptions: RotationMultiUserOptions = {
          secret: user.secret,
          automaticallyAfter: Duration.days(databaseUser.secretRotationDays),
        };
        cluster.addRotationMultiUser('multiuserrotation' + username, multiUserRotationOptions);
      }

      const secretAccessRoles = databaseUser.secretAccessRoles
        ? [
            ...this.props.roleHelper.resolveRoleRefsWithOrdinals(databaseUser.secretAccessRoles, 'SecretAccessRole'),
            ...this.props.roleHelper.resolveRoleRefsWithOrdinals(this.props.dataAdminRoleRefs, 'DataAdmin'),
          ]
        : this.props.roleHelper.resolveRoleRefsWithOrdinals(this.props.dataAdminRoleRefs, 'DataAdmin');

      this.assignSecretAcessPolicies(secretAccessRoles, warehouseKmsKey, user.secret);

      this.scope.node.children.forEach(child => {
        if (child.node.id.startsWith('Query Redshift Database') || child.node.id.startsWith('redshiftdbserviceuser-')) {
          MdaaNagSuppressions.addCodeResourceSuppressions(
            child,
            [
              { id: 'AwsSolutions-IAM4', reason: 'Role is for Custom Resource Provider.' },
              {
                id: 'NIST.800.53.R5-IAMNoInlinePolicy',
                reason: 'Role is for Custom Resource Provider. Inline policy automatically added.',
              },
              {
                id: 'HIPAA.Security-IAMNoInlinePolicy',
                reason: 'Role is for Custom Resource Provider. Inline policy automatically added.',
              },
              {
                id: 'PCI.DSS.321-IAMNoInlinePolicy',
                reason: 'Role is for Custom Resource Provider. Inline policy automatically added.',
              },
              { id: 'AwsSolutions-IAM5', reason: 'Role is for Custom Resource Provider.' },
              { id: 'AwsSolutions-L1', reason: 'Role is for Custom Resource Provider.' },
              {
                id: 'NIST.800.53.R5-LambdaDLQ',
                reason:
                  'Lambda Function is created by aws-redshift-alpha cdk module and error handling will be handled by CloudFormation',
              },
              {
                id: 'NIST.800.53.R5-LambdaInsideVPC',
                reason:
                  'Lambda Function is created by aws-redshift-alpha cdk module and will interact only with Redshift/SecretsManager',
              },
              {
                id: 'NIST.800.53.R5-LambdaConcurrency',
                reason:
                  'Lambda Function is created by aws-redshift-alpha cdk module and will only execute during stack deployement. Reserved concurrency not appropriate.',
              },
              {
                id: 'HIPAA.Security-LambdaDLQ',
                reason:
                  'Lambda Function is created by aws-redshift-alpha cdk module and error handling will be handled by CloudFormation',
              },
              {
                id: 'PCI.DSS.321-LambdaDLQ',
                reason:
                  'Lambda Function is created by aws-redshift-alpha cdk module and error handling will be handled by CloudFormation',
              },
              {
                id: 'HIPAA.Security-LambdaInsideVPC',
                reason:
                  'Lambda Function is created by aws-redshift-alpha cdk module and will interact only with Redshift/SecretsManager',
              },
              {
                id: 'PCI.DSS.321-LambdaInsideVPC',
                reason:
                  'Lambda Function is created by aws-redshift-alpha cdk module and will interact only with Redshift/SecretsManager',
              },
              {
                id: 'HIPAA.Security-LambdaConcurrency',
                reason:
                  'Lambda Function is created by aws-redshift-alpha cdk module and will only execute during stack deployement. Reserved concurrency not appropriate.',
              },
              {
                id: 'PCI.DSS.321-LambdaConcurrency',
                reason:
                  'Lambda Function is created by aws-redshift-alpha cdk module and will only execute during stack deployement. Reserved concurrency not appropriate.',
              },
            ],
            true,
          );
        }
      });
    });
  }