constructor()

in packages/apps/core/devops/lib/devops.ts [114:339]


  constructor(scope: Construct, id: string, props: MdaaDevopsL3ConstructProps) {
    super(scope, id, props);
    this.props = props;

    const pipelineRole = new MdaaRole(this, 'pipeline-role', {
      roleName: 'pipeline',
      naming: this.props.naming,
      assumedBy: new ServicePrincipal('codepipeline.amazonaws.com'),
    });

    const mdaaRepo = Repository.fromRepositoryName(this, 'mdaa-import-repo', this.props.mdaaCodeCommitRepo);
    const configsRepo = Repository.fromRepositoryName(this, 'configs-import-repo', this.props.configsCodeCommitRepo);

    const kmsKey = new MdaaKmsKey(this, 'kms-key', {
      naming: this.props.naming,
      keyUserRoleIds: [pipelineRole.roleId],
    });

    const devOpsBucket = new MdaaBucket(this, 'pipeline-bucket', {
      naming: this.props.naming,
      encryptionKey: kmsKey,
    });

    MdaaNagSuppressions.addCodeResourceSuppressions(
      devOpsBucket,
      [
        {
          id: 'NIST.800.53.R5-S3BucketReplicationEnabled',
          reason: 'Bucket does not contain data assets. Replication not required.',
        },
        {
          id: 'HIPAA.Security-S3BucketReplicationEnabled',
          reason: 'Bucket does not contain data assets. Replication not required.',
        },
        {
          id: 'PCI.DSS.321-S3BucketReplicationEnabled',
          reason: 'Bucket does not contain data assets. Replication not required.',
        },
      ],
      true,
    );

    const codeCommitEventRole = new MdaaRole(this, 'codecommit-event-role', {
      roleName: 'codecommit-event',
      naming: this.props.naming,
      assumedBy: new ServicePrincipal('events.amazonaws.com'),
    });

    const codeCommitReadPolicy = new PolicyDocument({
      statements: [
        new PolicyStatement({
          effect: Effect.ALLOW,
          actions: ['codecommit:GetBranch', 'codecommit:GetCommit', 'codecommit:GetRepository', 'codecommit:GitPull'],
          resources: [mdaaRepo.repositoryArn, configsRepo.repositoryArn],
        }),
      ],
    });

    const codeCommitActionRole = new MdaaRole(this, 'codecommit-action-role', {
      roleName: 'codecommit-action',
      naming: this.props.naming,
      assumedBy: new AccountPrincipal(this.account),
      inlinePolicies: { codecommit_read: codeCommitReadPolicy },
    });

    const codeBuildActionRole = new MdaaRole(this, 'codebuild-action-role', {
      roleName: 'codebuild-action',
      naming: this.props.naming,
      assumedBy: new CompositePrincipal(
        new ServicePrincipal('codebuild.amazonaws.com'),
        new AccountPrincipal(this.account),
      ),
      managedPolicies: [ManagedPolicy.fromAwsManagedPolicyName('AWSCloudFormationReadOnlyAccess')],
    });

    const codeBuildActionPolicy = new Policy(this, 'codebuild-policy');
    const cdkLookupRole = this.importCdkRole(this, 'lookup', this.props.cdkBootstrapContext);
    const cdkDeployRole = this.importCdkRole(this, 'deploy', this.props.cdkBootstrapContext);
    const cdkExecRole = this.importCdkRole(this, 'exec', this.props.cdkBootstrapContext);
    const cdkFilePublishingRole = this.importCdkRole(this, 'file-publishing', this.props.cdkBootstrapContext);
    const cdkImagePublishingRole = this.importCdkRole(this, 'image-publishing', this.props.cdkBootstrapContext);
    const cdkBucket = Bucket.fromBucketName(
      this,
      `cdk-bucket-import`,
      `cdk-${this.props.cdkBootstrapContext ?? MdaaDevopsL3Construct.DEFAULT_CDK_BOOTSTRAP_CONTEXT}-assets-${
        this.account
      }-${this.region}`,
    );

    codeBuildActionPolicy.addStatements(
      new PolicyStatement({
        sid: 'ASSUMECDKROLES',
        actions: ['sts:AssumeRole'],
        resources: [
          cdkLookupRole.roleArn,
          cdkDeployRole.roleArn,
          cdkFilePublishingRole.roleArn,
          cdkImagePublishingRole.roleArn,
          cdkExecRole.roleArn,
        ],
        effect: Effect.ALLOW,
      }),
    );

    codeBuildActionPolicy.addStatements(
      new PolicyStatement({
        sid: 'S3List',
        actions: ['s3:ListAllMyBuckets'],
        resources: ['*'],
        effect: Effect.ALLOW,
      }),
      new PolicyStatement({
        sid: 'CloudFormationChangeSets',
        actions: [
          'cloudformation:CreateChangeSet',
          'cloudformation:DescribeChangeSet',
          'cloudformation:DeleteChangeSet',
        ],
        resources: ['*'],
        effect: Effect.ALLOW,
      }),
    );

    codeBuildActionPolicy.addStatements(
      new PolicyStatement({
        sid: 'CDKS3',
        actions: ['s3:Get*', 's3:Put*', 's3:List*'],
        resources: [cdkBucket.bucketArn, cdkBucket.arnForObjects('*')],
        effect: Effect.ALLOW,
      }),
    );

    MdaaNagSuppressions.addCodeResourceSuppressions(
      codeBuildActionPolicy,
      [
        { id: 'AwsSolutions-IAM5', reason: 'Permissions are scoped least privilege for deployment time.' },
        { id: 'NIST.800.53.R5-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
        { id: 'HIPAA.Security-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
        { id: 'PCI.DSS.321-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
      ],
      true,
    );
    codeBuildActionPolicy.attachToRole(codeBuildActionRole);
    const manualActionRole = new MdaaRole(this, 'manual-action-role', {
      roleName: 'manual-action',
      naming: this.props.naming,
      assumedBy: new AccountPrincipal(this.account),
    });

    const assumeActionRoleGrant = codeBuildActionRole.grantAssumeRole(pipelineRole);

    Object.entries(this.props.pipelines ?? {}).forEach(entry => {
      const pipelineProps: MdaaPipelineProps = {
        pipelineType: PipelineType.V2,
        naming: this.props.naming.withModuleName(`devops-${entry[0]}`),
        pipelineName: this.props.naming.resourceName(entry[0]),
        ...entry[1],
        role: pipelineRole,
        artifactBucket: devOpsBucket,
        codeCommitActionRole: codeCommitActionRole,
        codeCommitEventRole: codeCommitEventRole,
        codeBuildActionRole: codeBuildActionRole,
        mdaaRepo: mdaaRepo,
        configsRepo: configsRepo,
        kmsKey: kmsKey,
        manualActionRole: manualActionRole,
        install: [...(this.props.install ?? []), ...(entry[1].install ?? [])],
        pre: [...(this.props.pre ?? []), ...(entry[1].pre ?? [])],
        post: [...(this.props.post ?? []), ...(entry[1].post ?? [])],
        preDeploy: { ...this.props.preDeploy, ...entry[1].preDeploy },
        preDeployValidate:
          this.props.preDeployValidate || entry[1].preDeployValidate
            ? { ...this.props.preDeployValidate, ...entry[1].preDeployValidate }
            : undefined,
        deploy: { ...this.props.deploy, ...entry[1].deploy },
        postDeployValidate:
          this.props.postDeployValidate || entry[1].postDeployValidate
            ? { ...this.props.postDeployValidate, ...entry[1].postDeployValidate }
            : undefined,
      };

      const pipeline = new MdaaPipeline(this, `mdaa-pipeline-${entry[0]}`, pipelineProps);
      assumeActionRoleGrant.applyBefore(pipeline);
    });

    MdaaNagSuppressions.addCodeResourceSuppressions(
      pipelineRole,
      [
        { id: 'AwsSolutions-IAM5', reason: 'Permissions are scoped least privilege for deployment time.' },
        { id: 'NIST.800.53.R5-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
        { id: 'HIPAA.Security-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
        { id: 'PCI.DSS.321-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
      ],
      true,
    );
    MdaaNagSuppressions.addCodeResourceSuppressions(
      codeBuildActionRole,
      [
        { id: 'AwsSolutions-IAM4', reason: 'AWSCloudFormationReadOnlyAccess is Read Only Access' },
        { id: 'AwsSolutions-IAM5', reason: 'Permissions are scoped least privilege for deployment time.' },
        { id: 'NIST.800.53.R5-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
        { id: 'HIPAA.Security-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
        { id: 'PCI.DSS.321-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
      ],
      true,
    );
    MdaaNagSuppressions.addCodeResourceSuppressions(
      codeCommitActionRole,
      [
        { id: 'AwsSolutions-IAM5', reason: 'Permissions are scoped least privilege for deployment time.' },
        { id: 'NIST.800.53.R5-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
        { id: 'HIPAA.Security-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
        { id: 'PCI.DSS.321-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
      ],
      true,
    );
    MdaaNagSuppressions.addCodeResourceSuppressions(
      codeCommitEventRole,
      [
        { id: 'NIST.800.53.R5-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
        { id: 'HIPAA.Security-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
        { id: 'PCI.DSS.321-IAMNoInlinePolicy', reason: 'Inline policy appropriate.' },
      ],
      true,
    );
  }