constructor()

in source/infrastructure/lib/common-resources.ts [50:166]


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

    const logGroupResourceArn = Stack.of(this).formatArn({ service: 'logs', resource: 'log-group:', resourceName: 'aws/lambda/*' })
    this.cloudWatchLogsPolicy = new Policy(this, 'CloudWatchLogsPolicy', {
      statements: [
        new PolicyStatement({
          effect: Effect.ALLOW,
          actions: [
            'logs:CreateLogGroup',
            'logs:CreateLogStream',
            'logs:PutLogEvents'
          ],
          resources: [
            logGroupResourceArn
          ]
        })
      ]
    });

    props.dltEcsTaskExecutionRole.attachInlinePolicy(this.cloudWatchLogsPolicy);

    this.s3LogsBucket = new Bucket(this, 'LogsBucket', {
      accessControl: BucketAccessControl.LOG_DELIVERY_WRITE,
      blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
      encryption: BucketEncryption.S3_MANAGED,
      removalPolicy: RemovalPolicy.RETAIN
    });
    Tags.of(this.s3LogsBucket).add('SolutionId', props.solutionId);

    const s3LogsBucketResource = this.s3LogsBucket.node.defaultChild as CfnResource;
    s3LogsBucketResource.addMetadata('cfn_nag', {
      rules_to_suppress: [{
        id: 'W35',
        reason: 'This is the logging bucket, it does not require logging.'
      }, {
        id: 'W51',
        reason: 'Since the bucket does not allow the public access, it does not require to have bucket policy.'
      }]
    })

    this.sourceBucket = Bucket.fromBucketName(this, 'SourceCodeBucket', props.sourceCodeBucket);
    const sourceBucketArn = this.sourceBucket.arnForObjects('*');

    const customResourceRole = new Role(this, 'CustomResourceLambdaRole', {
      assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
      inlinePolicies: {
        'CustomResourcePolicy': new PolicyDocument({
          statements: [
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: ['s3:GetObject'],
              resources: [
                sourceBucketArn
              ]
            })
          ]
        })
      }
    });
    customResourceRole.attachInlinePolicy(this.cloudWatchLogsPolicy);

    this.customResourceLambda = new LambdaFunction(this, 'CustomResourceLambda', {
      description: 'CFN Lambda backed custom resource to deploy assets to s3',
      handler: 'index.handler',
      role: customResourceRole,
      code: Code.fromBucket(this.sourceBucket, `${props.sourceCodePrefix}/custom-resource.zip`),
      runtime: Runtime.NODEJS_14_X,
      timeout: Duration.seconds(120),
      environment: {
        METRIC_URL: props.metricsUrl,
        SOLUTION_ID: props.solutionId,
        VERSION: props.solutionVersion
      }
    });

    Tags.of(this.customResourceLambda).add('SolutionId', props.solutionId);
    const customResource = this.customResourceLambda.node.defaultChild as CfnResource;
    customResource.addMetadata('cfn_nag', {
      rules_to_suppress: [{
        id: 'W58',
        reason: 'CloudWatchLogsPolicy covers a permission to write CloudWatch logs.'
      }, {
        id: 'W89',
        reason: 'VPC not needed for lambda'
      }, {
        id: 'W92',
        reason: 'Does not run concurrent executions'
      },]
    })

    const uuidGenerator = new CustomResource(this, 'UUID', {
      serviceToken: this.customResourceLambda.functionArn,
      resourceType: 'Custom::UUID',
      properties: {
        Resource: 'UUID'
      }
    });

    this.uuid = uuidGenerator.getAtt('UUID').toString();


    const sendAnonymousMetrics = new CustomResource(this, 'AnonymousMetric', {
      serviceToken: this.customResourceLambda.functionArn,
      resourceType: 'Custom::AnonymousMetric',
      properties: {
        Resource: 'AnonymousMetric',
        Region: Aws.REGION,
        SolutionId: props.solutionId,
        UUID: this.uuid,
        VERSION: props.solutionVersion,
        existingVPC: props.existingVpc
      }
    });
    const cfnSendAnonymousMetrics = sendAnonymousMetrics.node.defaultChild as CfnCustomResource;
    cfnSendAnonymousMetrics.cfnOptions.condition = props.sendAnonymousUsageCondition;
  }