constructor()

in source/lib/amazon-s3-glacier-refreezer-stack.ts [37:263]


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

        //---------------------------------------------------------------------
        // Amazon S3 Glacier CloudFormation Configuration
        const statisticsMapping = new cdk.CfnMapping(this, 'AnonymousStatisticsMap', {
            mapping: {
                'SendAnonymousStatistics': {
                    'Data': 'Yes'
                }
            }
        });

        //---------------------------------------------------------------------
        // Amazon S3 Glacier CloudFormation Configuration
        const sourceVault = new cdk.CfnParameter(this, 'SourceVault', {
            type: 'String',
            allowedPattern: '.+'
        });

        const destinationBucket = new cdk.CfnParameter(this, 'DestinationBucket', {
            type: 'String',
            allowedPattern: '.+'
        });

        const destinationStorageClass = new cdk.CfnParameter(this, 'DestinationStorageClass', {
            type: 'String',
            default: 'STANDARD',
            allowedValues: ['STANDARD', 'INTELLIGENT_TIERING', 'STANDARD_IA', 'ONEZONE_IA', 'GLACIER_IR', 'GLACIER', 'DEEP_ARCHIVE']
        });

        const glacierRetrievalTier = new cdk.CfnParameter(this, 'GlacierRetrievalTier', {
            type: 'String',
            default: 'Bulk',
            allowedValues: ['Bulk', 'Standard', 'Expedited']
        });

        const filelistS3location = new cdk.CfnParameter(this, 'FilelistS3Location', {
            type: 'String',
            default: ''
        });

        const cloudtrailExportConfirmation = new cdk.CfnParameter(this, 'CloudTrailExportConfirmation', {
            type: 'String',
            allowedValues: ['Yes', 'No']
        });

        const snsTopicForVaultConfirmation = new cdk.CfnParameter(this, 'SNSTopicForVaultConfirmation', {
            type: 'String',
            allowedValues: ['Yes', 'No']
        });

        //---------------------------------------------------------------------
        // Template metadata
        this.templateOptions.metadata = {
            'AWS::CloudFormation::Interface': {
                ParameterGroups: [
                    {
                        Label: {default: 'Required input parameters'},
                        Parameters: [sourceVault.logicalId, destinationBucket.logicalId, destinationStorageClass.logicalId, glacierRetrievalTier.logicalId]
                    },
                    {
                        Label: {default: 'Confirmation to avoid excessive costs'},
                        Parameters: [cloudtrailExportConfirmation.logicalId, snsTopicForVaultConfirmation.logicalId]
                    },
                    {
                        Label: {default: '[OPTIONAL] External filenames override for ArchiveDescription'},
                        Parameters: [filelistS3location.logicalId]
                    }
                ],
                ParameterLabels: {
                    [sourceVault.logicalId]: {
                        default: 'Source Glacier vault name'
                    },
                    [destinationBucket.logicalId]: {
                        default: 'S3 destination bucket name'
                    },
                    [destinationStorageClass.logicalId]: {
                        default: 'S3 destination storage class'
                    },

                    [glacierRetrievalTier.logicalId]: {
                        default: 'Glacier retrieval tier'
                    },
                    [filelistS3location.logicalId]: {
                        default: 'Amazon S3 location of the CSV file as BUCKET/FILEPATH'
                    },
                    [cloudtrailExportConfirmation.logicalId]: {
                        default: 'Have you checked that there is only one Cloudtrail export to S3 bucket configured in your account?'
                    },
                    [snsTopicForVaultConfirmation.logicalId]: {
                        default: 'Has default SNS notification topic on the vault been disabled or is it acceptable to receive notification for ALL archives in the vault?'
                    }
                }
            }
        };

        //---------------------------------------------------------------------
        // Staging S3 Bucket
        const stagingBucket = new StagingBucket(this, 'stagingBucket');

        //---------------------------------------------------------------------
        // Glue/Athena Data Structures
        const glueDataCatalog = new GlueDataCatalog(this, 'glueDataCatalog',
            {
                stagingBucket: stagingBucket.Bucket
            });

        //---------------------------------------------------------------------
        // DynamoDB Data Structures
        const dynamoDataCatalog = new DynamoDataCatalog(this, 'dynamoDataCatalog');

        //---------------------------------------------------------------------
        // IAM Permissions
        const iamPermissions = new IamPermissions(this, 'iamPermissions');

        // -------------------------------------------------------------------------------------------
        // Archive Notification Topic
        // Declaring at the stack level as it is shared between at Monitoring, Stage Two and  and Stage Three

        const archiveNotificationTopic = new sns.Topic(this, 'ArchiveNotifications');
        // overriding CDK name with CFN ID to enforce a random topic name generation
        // so even if the same stack name has been reused, each deployment will be isolated
        // Used as a safeguard for deployments and metric isolation
        (archiveNotificationTopic.node.defaultChild as sns.CfnTopic).overrideLogicalId(`archiveNotifications`);
        CfnNagSuppressor.addSuppression(archiveNotificationTopic, 'W47', 'Non sensitive metadata - encryption is not required and cost inefficient');
        archiveNotificationTopic.addToResourcePolicy(iamSec.IamPermissions.snsGlacierPublisher(archiveNotificationTopic));
        archiveNotificationTopic.addToResourcePolicy(iamSec.IamPermissions.snsDenyInsecureTransport(archiveNotificationTopic));

        //---------------------------------------------------------------------
        // Monitoring
        const monitoring = new Monitoring(this, `monitoring`, {
            statusTable: dynamoDataCatalog.statusTable,
            metricTable: dynamoDataCatalog.metricTable,
            archiveNotificationTopic
        })

        //---------------------------------------------------------------------
        // Anonymous Statistics

        // This solution includes an option to send anonymous operational metrics to
        // AWS. We use this data to better understand how customers use this
        // solution and related services and products

        const statistics = new AnonymousStatistics(this, `statistics`, {
            solutionId: props.solutionId,
            retrievalTier: glacierRetrievalTier.valueAsString,
            destinationStorageClass: destinationStorageClass.valueAsString,
            sendAnonymousSelection: statisticsMapping.findInMap('SendAnonymousStatistics', 'Data')
        })

        //---------------------------------------------------------------------
        // Stage Three: Copy Archives to Staging
        const stageThree = new StageThree(this, 'stageThree', {
            stagingBucket: stagingBucket.Bucket,
            sourceVault: sourceVault.valueAsString,
            statusTable: dynamoDataCatalog.statusTable,
            metricTable: dynamoDataCatalog.metricTable,
            archiveNotificationTopic
        });

        //---------------------------------------------------------------------
        // Stage Two: Request Archive Retrieval
        const stageTwo = new StageTwo(this, 'stageTwo', {
            stagingBucket: stagingBucket.Bucket,
            glacierSourceVault: sourceVault.valueAsString,
            glacierRetrievalTier: glacierRetrievalTier.valueAsString,
            glueDataCatalog: glueDataCatalog,
            dynamoDataCatalog: dynamoDataCatalog,
            sendAnonymousStats: statistics.sendAnonymousStats,
            archiveNotificationTopic
        });
        stageTwo.node.addDependency(monitoring);

        //---------------------------------------------------------------------
        // Stage One: Get Inventory
        const stageOne = new StageOne(this, 'stageOne', {
            stagingBucket: stagingBucket.Bucket,
            sourceGlacierVault: sourceVault.valueAsString,
            destinationBucket: destinationBucket.valueAsString,
            destinationStorageClass: destinationStorageClass.valueAsString,
            glacierRetrievalTier: glacierRetrievalTier.valueAsString,
            filelistS3location: filelistS3location.valueAsString,
            cloudtrailExportConfirmation: cloudtrailExportConfirmation.valueAsString,
            snsTopicForVaultConfirmation: snsTopicForVaultConfirmation.valueAsString,
            stageTwoOrchestrator: stageTwo.stageTwoOrchestrator
        });
        stageOne.node.addDependency(monitoring);

        //---------------------------------------------------------------------
        // Stage Four: Validate SHA256 Treehash and move archives from Staging to Destination
        const stageFour = new StageFour(this, 'stageFour', {
            stagingBucket: stagingBucket.Bucket,
            statusTable: dynamoDataCatalog.statusTable,
            treehashCalcQueue: stageThree.treehashCalcQueue,
            destinationBucket: destinationBucket.valueAsString,
            destinationStorageClass: destinationStorageClass.valueAsString,
            archiveNotificationQueue: stageThree.archiveNotificationQueue,
            metricTable: dynamoDataCatalog.metricTable
        });

        //---------------------------------------------------------------------
        // Tags
        cdk.Tags.of(this).add("solution", "amazon-s3-glacier-refreezer")

        //---------------------------------------------------------------------
        // Stack Outputs
        new cdk.CfnOutput(this, 'CloudTrailExportConfirmationSelection', {
            description: 'Selected option for CloudTrail Export confirmation',
            value: cloudtrailExportConfirmation.valueAsString
        });

        new cdk.CfnOutput(this, 'SNSTopicForVaultConfirmationSelection', {
            description: 'Selected option for SNS Topic for Vault confirmation',
            value: snsTopicForVaultConfirmation.valueAsString
        });

        new cdk.CfnOutput(this, 'StagingBucketName', {
            description: 'Staging Bucket Name',
            value: stagingBucket.Bucket.bucketName
        });

        new cdk.CfnOutput(this, 'dashboardUrl', {
            description: 'Progress Dashboard URL',
            value: `https://${cdk.Aws.REGION}.console.aws.amazon.com/cloudwatch/home?region=${cdk.Aws.REGION}#dashboards:name=${monitoring.dashboardName};accountId=${cdk.Aws.ACCOUNT_ID}`
        });
    }