constructor()

in source/lib/stage-three.ts [46:166]


    constructor(scope: cdk.Construct, id: string, props: StageThreeProps) {
        super(scope, id);

        // -------------------------------------------------------------------------------------------
        // Treehash Calc Request Queue
        const treehashCalcQueue = new sqs.Queue(this, 'treehash-calc-queue',
            {
                queueName: `${cdk.Aws.STACK_NAME}-treehash-calc-queue`,
                retentionPeriod: cdk.Duration.days(14),
                visibilityTimeout: cdk.Duration.seconds(905)
            }
        );
        CfnNagSuppressor.addSuppression(treehashCalcQueue, 'W48', 'Non sensitive metadata - encryption is not required and cost inefficient');
        treehashCalcQueue.addToResourcePolicy(iamSec.IamPermissions.sqsDenyInsecureTransport(treehashCalcQueue));
        this.treehashCalcQueue = treehashCalcQueue;

        // -------------------------------------------------------------------------------------------
        // Archive Notification Queue
        const archiveNotificationQueue = new sqs.Queue(this, 'archive-notification-queue',
            {
                queueName: `${cdk.Aws.STACK_NAME}-archive-notification-queue`,
                visibilityTimeout: cdk.Duration.seconds(905)
            }
        );
        CfnNagSuppressor.addSuppression(archiveNotificationQueue, 'W48', 'Non sensitive metadata - encryption is not required and cost inefficient');
        archiveNotificationQueue.addToResourcePolicy(iamSec.IamPermissions.sqsDenyInsecureTransport(archiveNotificationQueue));
        props.archiveNotificationTopic.addSubscription(new subscriptions.SqsSubscription(archiveNotificationQueue));
        this.archiveNotificationQueue = archiveNotificationQueue;

        // -------------------------------------------------------------------------------------------
        // Chunk Copy Queue
        const chunkCopyQueue = new sqs.Queue(this, 'chunk-copy-queue',
            {
                queueName: `${cdk.Aws.STACK_NAME}-chunk-copy-queue`,
                visibilityTimeout: cdk.Duration.seconds(905)
            }
        );
        CfnNagSuppressor.addSuppression(chunkCopyQueue, 'W48', 'Non sensitive metadata - encryption is not required and cost inefficient');
        chunkCopyQueue.addToResourcePolicy(iamSec.IamPermissions.sqsDenyInsecureTransport(chunkCopyQueue));

        // -------------------------------------------------------------------------------------------
        // Split Archive into Chunks
        const splitArchiveRole = new iam.Role(this, 'splitArchiveRole', {
            assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com')
        });

        // Declaring the policy granting access to the stream explicitly to minimize permissions
        splitArchiveRole.addToPrincipalPolicy(iamSec.IamPermissions.lambdaLogGroup(`${cdk.Aws.STACK_NAME}-splitArchive`));
        splitArchiveRole.addToPrincipalPolicy(iamSec.IamPermissions.glacier(props.sourceVault));
        splitArchiveRole.addToPrincipalPolicy(iamSec.IamPermissions.sqsSubscriber(archiveNotificationQueue));

        props.stagingBucket.grantReadWrite(splitArchiveRole);
        props.statusTable.grantReadWriteData(splitArchiveRole);
        chunkCopyQueue.grantSendMessages(splitArchiveRole);
        treehashCalcQueue.grantSendMessages(splitArchiveRole);

        const defaultSplitArchivePolicy = splitArchiveRole.node.findChild('DefaultPolicy').node.defaultChild as cdk.CfnResource;
        CfnNagSuppressor.addCfnSuppression(defaultSplitArchivePolicy, 'W76', 'Policy is auto-generated by CDK');

        const splitArchive = new lambda.Function(this, 'SplitArchive', {
            functionName: `${cdk.Aws.STACK_NAME}-splitArchive`,
            runtime: lambda.Runtime.NODEJS_14_X,
            handler: 'index.handler',
            memorySize: 256,
            timeout: cdk.Duration.minutes(15),
            reservedConcurrentExecutions: 45,
            code: lambda.Code.fromAsset(path.join(__dirname, '../lambda/splitArchive')),
            role: splitArchiveRole.withoutPolicyUpdates(),
            environment:
                {
                    STAGING_BUCKET: props.stagingBucket.bucketName,
                    STAGING_BUCKET_PREFIX: 'stagingdata',
                    STATUS_TABLE: props.statusTable.tableName,
                    SQS_CHUNK: chunkCopyQueue.queueName,
                    SQS_HASH: treehashCalcQueue.queueName
                }
        });
        splitArchive.node.addDependency(splitArchiveRole);
        splitArchive.addEventSource(new SqsEventSource(archiveNotificationQueue, {batchSize: 1}));
        CfnNagSuppressor.addLambdaSuppression(splitArchive);

        // -------------------------------------------------------------------------------------------
        // Copy Chunk
        const copyChunkRole = new iam.Role(this, 'CopyChunkRole', {
            assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com')
        });

        copyChunkRole.addToPrincipalPolicy(iamSec.IamPermissions.lambdaLogGroup(`${cdk.Aws.STACK_NAME}-copyChunk`));
        copyChunkRole.addToPrincipalPolicy(iamSec.IamPermissions.glacier(props.sourceVault));
        copyChunkRole.addToPrincipalPolicy(iamSec.IamPermissions.sqsSubscriber(chunkCopyQueue));

        const defaultCopyChunkPolicy = copyChunkRole.node.findChild('DefaultPolicy').node.defaultChild as cdk.CfnResource;
        CfnNagSuppressor.addCfnSuppression(defaultCopyChunkPolicy, 'W76', 'Policy is auto-generated by CDK');

        props.stagingBucket.grantReadWrite(copyChunkRole);
        props.statusTable.grantReadWriteData(copyChunkRole);
        props.metricTable.grantReadWriteData(copyChunkRole);
        treehashCalcQueue.grantSendMessages(copyChunkRole);

        const copyChunk = new lambda.Function(this, 'CopyChunk', {
            functionName: `${cdk.Aws.STACK_NAME}-copyChunk`,
            runtime: lambda.Runtime.NODEJS_14_X,
            handler: 'index.handler',
            memorySize: 1024,
            timeout: cdk.Duration.minutes(15),
            reservedConcurrentExecutions: 35,
            role: copyChunkRole.withoutPolicyUpdates(),
            code: lambda.Code.fromAsset(path.join(__dirname, '../lambda/copyChunk')),
            environment:
                {
                    VAULT: props.sourceVault,
                    STAGING_BUCKET: props.stagingBucket.bucketName,
                    STAGING_BUCKET_PREFIX: 'stagingdata',
                    STATUS_TABLE: props.statusTable.tableName,
                    METRIC_TABLE: props.metricTable.tableName,
                    SQS_HASH: treehashCalcQueue.queueName
                }
        });
        CfnNagSuppressor.addLambdaSuppression(copyChunk);
        copyChunk.addEventSource(new SqsEventSource(chunkCopyQueue, {batchSize: 1}));
    }