--- AWSTemplateFormatVersion: 2010-09-09 Description: "Creates resources necessary to demonstrate AWS DMS Time Travel" Parameters: DoesDMSVPCRoleExist: Default: N Type: String Description: If the IAM role dms-vpc-role already exists, choose Y AllowedValues: - Y - N ConstraintDescription: Permitted values are is Y or N DoesDMSCloudWatchLogRoleExist: Default: N Type: String Description: If the IAM role dms-cloudwatch-logs-role already exists, choose Y AllowedValues: - Y - N ConstraintDescription: Permitted values are is Y or N DoesDMSTTRoleExist: Default: N Type: String Description: If the IAM role dms-tt-s3-access-role already exists, choose Y AllowedValues: - Y - N ConstraintDescription: Permitted values are is Y or N VPCCIDR: Type: String Description: VPC CIDR Default: "10.1.0.0/26" PrivateSubnetOneCIDR: Type: String Description: Subnet One CIDR Default: "10.1.0.0/28" PrivateSubnetTwoCIDR: Type: String Description: Subnet One CIDR Default: "10.1.0.16/28" PublicSubnetOneCIDR: Type: String Description: Public Subnet One CIDR Default: "10.1.0.32/28" DBInstanceClass: Description: RDS Instance Class Type: String Default: db.r5.large AllowedValues: - db.r5.large - db.r5.xlarge - db.r5.2xlarge - db.r5.4xlarge - db.r5.8xlarge InstanceType: Description: EC2 instance type Type: String Default: t2.medium AllowedValues: - t2.medium - t2.large - r5.large - r5.xlarge - r5.2xlarge - r5.4xlarge ConstraintDescription: must be a valid EC2 instance type. AutoHibernateTimeout: Description: How many minutes idle before shutting down the IDE. Options, 1day, 1week, Never (0) Type: Number Default: 1440 AllowedValues: - 1440 - 10080 - 0 Conditions: NotExistsDMSVPCRole: !Equals - !Ref DoesDMSVPCRoleExist - N NotExistsDMSCloudWatchLogRole: !Equals - !Ref DoesDMSCloudWatchLogRoleExist - N NotExistsDMSTTRole: !Equals - !Ref DoesDMSTTRoleExist - N Resources: Cloud9IDE: Type: AWS::Cloud9::EnvironmentEC2 Properties: Description: "Cloud9 IDE to interact with source and target databases" InstanceType: !Ref InstanceType ImageId: amazonlinux-2-x86_64 AutomaticStopTimeMinutes: !Ref "AutoHibernateTimeout" Name: DMSTimeTravelCloud9 SubnetId: !Ref PublicSubnetOne DMSVPCRole: Type: 'AWS::IAM::Role' Condition: NotExistsDMSVPCRole Properties: RoleName: 'dms-vpc-role' AssumeRolePolicyDocument: Statement: - Principal: Service: 'dms.amazonaws.com' Action: - 'sts:AssumeRole' Effect: Allow Path: / ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole' DMSCloudWatchLogsRole: Type: 'AWS::IAM::Role' Condition: NotExistsDMSCloudWatchLogRole Properties: RoleName: 'dms-cloudwatch-logs-role' AssumeRolePolicyDocument: Statement: - Principal: Service: 'dms.amazonaws.com' Action: - 'sts:AssumeRole' Effect: Allow Path: / ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AmazonDMSCloudWatchLogsRole' S3EncryptionKey: Type: AWS::KMS::Key Properties: Description: An symmetric CMK for SNS EnableKeyRotation: true KeyPolicy: Version: '2012-10-17' Id: keyForSNS Statement: - Sid: Delegate administration of key to the account principal Effect: Allow Principal: AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' Action: kms:* Resource: '*' DMSS3Role: Type: 'AWS::IAM::Role' Condition: NotExistsDMSTTRole Properties: RoleName: 'dms-tt-s3-access-role' AssumeRolePolicyDocument: Statement: - Principal: Service: 'dms.amazonaws.com' Action: - 'sts:AssumeRole' Effect: Allow Path: / Policies: - PolicyName: DMSS3Policy PolicyDocument: Version: 2012-10-17 Statement: Action: - 's3:PutObject' - 's3:ListBucket' - 's3:DeleteObject' Effect: Allow Resource: - !Sub 'arn:aws:s3:::bucket-${AWS::AccountId}-${AWS::Region}-dms-time-travel' - !Sub 'arn:aws:s3:::bucket-${AWS::AccountId}-${AWS::Region}-dms-time-travel/*' - PolicyName: DMSKMSPolicy PolicyDocument: Version: 2012-10-17 Statement: Action: - 'kms:GenerateDataKey' - 'kms:Decrypt' Effect: Allow Resource: - !GetAtt S3EncryptionKey.Arn VPCFlowLogsRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Sid: "" Effect: "Allow" Principal: Service: "vpc-flow-logs.amazonaws.com" Action: "sts:AssumeRole" Policies: - PolicyName: "vpc-flow-logs-rds" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" - "logs:DescribeLogGroups" - "logs:DescribeLogStreams" Resource: !GetAtt VPCFlowLogsGroupRDS.Arn FlowLogsKey: Type: AWS::KMS::Key Properties: Description: An symmetric CMK for encrypting flow logs EnableKeyRotation: true KeyPolicy: Version: "2012-10-17" Id: keyForFlowLogs Statement: - Sid: Enable IAM User Permissions Effect: Allow Principal: AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root" Action: kms:* Resource: "*" - Sid: Allow log encryption Effect: Allow Principal: Service: !Sub logs.${AWS::Region}.amazonaws.com Action: - kms:Encrypt* - kms:Decrypt* - kms:ReEncrypt* - kms:GenerateDataKey* - kms:Describe* Resource: "*" Condition: ArnEquals: kms:EncryptionContext:aws:logs:arn: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:VPCFlowLogsDMSTimeTravel VPC: Type: AWS::EC2::VPC Properties: EnableDnsSupport: true EnableDnsHostnames: true CidrBlock: !Ref VPCCIDR Tags: - Key: Name Value: "DMS-TimeTravel-VPC" VPCFlowLogsGroupRDS: Type: "AWS::Logs::LogGroup" Properties: LogGroupName: "VPCFlowLogsDMSTimeTravel" KmsKeyId: !GetAtt FlowLogsKey.Arn RetentionInDays: 7 VPCFlowLog: Type: AWS::EC2::FlowLog Properties: LogGroupName: "VPCFlowLogsDMSTimeTravel" ResourceId: !Ref VPC ResourceType: VPC TrafficType: ALL DeliverLogsPermissionArn: !GetAtt VPCFlowLogsRole.Arn PublicSubnetOne: Type: AWS::EC2::Subnet Properties: VpcId: !Ref "VPC" CidrBlock: !Ref PublicSubnetOneCIDR AvailabilityZone: !Select - 1 - Fn::GetAZs: !Ref "AWS::Region" Tags: - Key: Name Value: "Public Subnet One" InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: Fn::Join: - "-" - - Ref: AWS::StackName - InternetGateway AttachGateway: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref "VPC" InternetGatewayId: !Ref InternetGateway PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref "VPC" Tags: - Key: Name Value: Fn::Join: - "-" - - Ref: AWS::StackName - PublicRouteTable PublicRoute: Type: AWS::EC2::Route DependsOn: AttachGateway Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PublicSubnetRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnetOne RouteTableId: !Ref PublicRouteTable PrivateSubnetOne: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Select - 0 - Fn::GetAZs: !Ref "AWS::Region" VpcId: !Ref "VPC" CidrBlock: !Ref PrivateSubnetOneCIDR Tags: - Key: Name Value: "Private Subnet One" PrivateSubnetTwo: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Select - 1 - Fn::GetAZs: !Ref "AWS::Region" VpcId: !Ref "VPC" CidrBlock: !Ref PrivateSubnetTwoCIDR Tags: - Key: Name Value: "Private Subnet Two" PrivateRouteTable: Type: "AWS::EC2::RouteTable" Properties: VpcId: !Ref VPC Tags: - Key: Name Value: "RDS Route Table" PrivateSubnetOneRouteTableAssociation: Type: "AWS::EC2::SubnetRouteTableAssociation" Properties: SubnetId: !Ref PrivateSubnetOne RouteTableId: !Ref PrivateRouteTable PrivateSubnetTwoRouteTableAssociation: Type: "AWS::EC2::SubnetRouteTableAssociation" Properties: SubnetId: !Ref PrivateSubnetTwo RouteTableId: !Ref PrivateRouteTable SourceRDSSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Private SG For internal communication VpcId: !Ref "VPC" SourceRDSSecurityGroupIngress1: Type: AWS::EC2::SecurityGroupIngress Properties: Description: Allow Cloud9 Instance & DMS to connect GroupId: !Ref SourceRDSSecurityGroup IpProtocol: "tcp" FromPort: 5432 ToPort: 5432 CidrIp: !Ref VPCCIDR SourceRDSSecurityGroupEgress: Type: AWS::EC2::SecurityGroupEgress Properties: Description: To communicate within the SG GroupId: !Ref SourceRDSSecurityGroup IpProtocol: "tcp" FromPort: 0 ToPort: 0 DestinationSecurityGroupId: !GetAtt SourceRDSSecurityGroup.GroupId TargetRDSSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Private SG For internal communication VpcId: !Ref "VPC" TargetRDSSecurityGroupIngress1: Type: AWS::EC2::SecurityGroupIngress Properties: Description: Allow Cloud9 Instance & DMS to connect GroupId: !Ref TargetRDSSecurityGroup IpProtocol: "tcp" FromPort: 3306 ToPort: 3306 CidrIp: !Ref VPCCIDR TargetRDSSecurityGroupEgress: Type: AWS::EC2::SecurityGroupEgress Properties: Description: To communicate within the SG GroupId: !Ref TargetRDSSecurityGroup IpProtocol: "tcp" FromPort: 0 ToPort: 0 DestinationSecurityGroupId: !GetAtt TargetRDSSecurityGroup.GroupId DBSecretsKey: Type: AWS::KMS::Key Properties: Description: An symmetric CMK for Secrets Manager EnableKeyRotation: true KeyPolicy: Version: "2012-10-17" Id: keyForSecrets Statement: - Sid: Enable IAM User Permissions Effect: Allow Principal: AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root" Action: kms:* Resource: "*" SourceDBSecret: Type: "AWS::SecretsManager::Secret" Properties: Name: /dms-source/dbsecret Description: Generates random value for db password and stores in secrets manager KmsKeyId: !Ref DBSecretsKey GenerateSecretString: SecretStringTemplate: '{"username": "dbadmin", "port": "5432", "host": " "}' GenerateStringKey: "password" PasswordLength: 20 ExcludeCharacters: "\"% @/\\;.:+'" TargetDBSecret: Type: "AWS::SecretsManager::Secret" Properties: Name: /dms-target/dbsecret Description: Generates random value for db password and stores in secrets manager KmsKeyId: !Ref DBSecretsKey GenerateSecretString: SecretStringTemplate: '{"username": "dbadmin", "port": "3306", "host": " "}' GenerateStringKey: "password" PasswordLength: 20 ExcludeCharacters: "\"% @/\\;.:+'" SourceRDSDBInstance: Type: "AWS::RDS::DBInstance" Properties: DeletionProtection: true AllocatedStorage: 100 AvailabilityZone: !GetAtt PrivateSubnetOne.AvailabilityZone DBInstanceClass: !Ref DBInstanceClass DBParameterGroupName: !Ref SourceRDSDBParameterGroup DBSubnetGroupName: !Ref SourceDBSubnetGroup MasterUsername: !Sub '{{resolve:secretsmanager:${SourceDBSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${SourceDBSecret}::password}}' DBName: "dmssource" Port: 5432 Engine: postgres EngineVersion: '13.3' VPCSecurityGroups: [!Ref SourceRDSSecurityGroup] PubliclyAccessible: false StorageEncrypted: true SourceRDSDBParameterGroup: Type: 'AWS::RDS::DBParameterGroup' Properties: Description: PostgreSQL Parameter Group Family: postgres13 Parameters: rds.logical_replication: 1 wal_sender_timeout: 0 TargetRDSDBInstance: Type: "AWS::RDS::DBInstance" Properties: DeletionProtection: true AllocatedStorage: 100 AvailabilityZone: !GetAtt PrivateSubnetOne.AvailabilityZone DBInstanceClass: !Ref DBInstanceClass DBParameterGroupName: !Ref TargetRDSDBParameterGroup DBSubnetGroupName: !Ref TargetDBSubnetGroup MasterUsername: !Sub '{{resolve:secretsmanager:${TargetDBSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${TargetDBSecret}::password}}' DBName: "dmstarget" Port: 3306 Engine: mysql EngineVersion: '8.0.28' VPCSecurityGroups: [!Ref TargetRDSSecurityGroup] PubliclyAccessible: false StorageEncrypted: true TargetRDSDBParameterGroup: Type: 'AWS::RDS::DBParameterGroup' Properties: Description: MySQL Parameter Group Family: mysql8.0 Parameters: sql_mode: IGNORE_SPACE max_allowed_packet: '1073741824' innodb_buffer_pool_size: '{DBInstanceClassMemory*3/4}' SourceDBSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: DBSubnetGroupDescription: String DBSubnetGroupName: source-db-subnet-group SubnetIds: [!Ref PrivateSubnetOne, !Ref PrivateSubnetTwo] TargetDBSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: DBSubnetGroupDescription: String DBSubnetGroupName: target-db-subnet-group SubnetIds: [!Ref PrivateSubnetOne, !Ref PrivateSubnetTwo] SMRDSAttachmentSource: Type: AWS::SecretsManager::SecretTargetAttachment Properties: SecretId: !Ref SourceDBSecret TargetId: !Ref SourceRDSDBInstance TargetType: AWS::RDS::DBInstance SMRDSAttachmentTarget: Type: AWS::SecretsManager::SecretTargetAttachment Properties: SecretId: !Ref TargetDBSecret TargetId: !Ref TargetRDSDBInstance TargetType: AWS::RDS::DBInstance DMSReplicationInstance: Type: "AWS::DMS::ReplicationInstance" Properties: ReplicationInstanceClass: dms.t3.medium PubliclyAccessible: false EngineVersion: "3.4.6" ReplicationInstanceIdentifier: "time-travel-dms-instance" ReplicationSubnetGroupIdentifier: !Ref DMSSubnetGroup VpcSecurityGroupIds: [ !Ref DMSSecurityGroup ] Tags: - Key: Name Value: "DMS Replication Instance" DMSSourceEndpoint: Type: AWS::DMS::Endpoint Properties: EndpointIdentifier: "postgres-source-endpoint" EndpointType: "source" EngineName: "postgres" Password: !Sub '{{resolve:secretsmanager:${SourceDBSecret}::password}}' Port: 5432 ServerName: !GetAtt SourceRDSDBInstance.Endpoint.Address Username: dbadmin DatabaseName: dmssource DMSTargetEndpoint: Type: AWS::DMS::Endpoint Properties: EndpointIdentifier: "mysql-target-endpoint" EndpointType: "target" EngineName: "mysql" Password: !Sub '{{resolve:secretsmanager:${TargetDBSecret}::password}}' Port: 3306 ServerName: !GetAtt TargetRDSDBInstance.Endpoint.Address Username: dbadmin DatabaseName: dmstarget DMSReplicationTask: Type: AWS::DMS::ReplicationTask Properties: MigrationType: "full-load-and-cdc" ReplicationInstanceArn: !Ref DMSReplicationInstance ReplicationTaskIdentifier: "replicate-products" SourceEndpointArn: !Ref DMSSourceEndpoint ReplicationTaskSettings: !Sub '{ "Logging": { "EnableLogging": true, "LogComponents": [ { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "TRANSFORMATION" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "SOURCE_UNLOAD" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "IO" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "TARGET_LOAD" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "PERFORMANCE" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "SOURCE_CAPTURE" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "SORTER" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "REST_SERVER" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "VALIDATOR_EXT" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "TARGET_APPLY" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "TASK_MANAGER" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "TABLES_MANAGER" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "METADATA_MANAGER" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "FILE_FACTORY" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "COMMON" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "ADDONS" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "DATA_STRUCTURE" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "COMMUNICATION" }, { "Severity": "LOGGER_SEVERITY_DEFAULT", "Id": "FILE_TRANSFER" } ], "CloudWatchLogGroup": null, "CloudWatchLogStream": null }, "StreamBufferSettings": { "StreamBufferCount": 3, "CtrlStreamBufferSizeInMB": 5, "StreamBufferSizeInMB": 8 }, "ErrorBehavior": { "FailOnNoTablesCaptured": false, "ApplyErrorUpdatePolicy": "LOG_ERROR", "FailOnTransactionConsistencyBreached": false, "RecoverableErrorThrottlingMax": 1800, "DataErrorEscalationPolicy": "SUSPEND_TABLE", "ApplyErrorEscalationCount": 0, "RecoverableErrorStopRetryAfterThrottlingMax": false, "RecoverableErrorThrottling": true, "ApplyErrorFailOnTruncationDdl": false, "DataTruncationErrorPolicy": "LOG_ERROR", "ApplyErrorInsertPolicy": "LOG_ERROR", "EventErrorPolicy": "IGNORE", "ApplyErrorEscalationPolicy": "LOG_ERROR", "RecoverableErrorCount": -1, "DataErrorEscalationCount": 0, "TableErrorEscalationPolicy": "STOP_TASK", "RecoverableErrorInterval": 5, "ApplyErrorDeletePolicy": "IGNORE_RECORD", "TableErrorEscalationCount": 0, "FullLoadIgnoreConflicts": true, "DataErrorPolicy": "LOG_ERROR", "TableErrorPolicy": "SUSPEND_TABLE" }, "ValidationSettings": { "ValidationPartialLobSize": 0, "PartitionSize": 10000, "RecordFailureDelayLimitInMinutes": 0, "SkipLobColumns": false, "FailureMaxCount": 10000, "HandleCollationDiff": false, "ValidationQueryCdcDelaySeconds": 0, "ValidationMode": "ROW_LEVEL", "TableFailureMaxCount": 1000, "RecordFailureDelayInMinutes": 5, "MaxKeyColumnSize": 8096, "EnableValidation": true, "ThreadCount": 5, "RecordSuspendDelayInMinutes": 30, "ValidationOnly": false }, "TTSettings": { "TTS3Settings": { "EnableDeletingFromS3OnTaskDelete": false, "BucketName": "bucket-${AWS::AccountId}-${AWS::Region}-dms-time-travel", "BucketFolder": "myttfolder", "ServiceAccessRoleArn": "arn:aws:iam::${AWS::AccountId}:role/dms-tt-s3-access-role", "EncryptionMode": "SSE_KMS", "ServerSideEncryptionKmsKeyId": "${S3EncryptionKey.Arn}" }, "TTRecordSettings": { "OperationsToLog": "INSERT", "EnableRawData": true, "MaxRecordSize": 64 }, "EnableTT": true }, "FullLoadSettings": { "CommitRate": 10000, "StopTaskCachedChangesApplied": false, "StopTaskCachedChangesNotApplied": false, "MaxFullLoadSubTasks": 8, "TransactionConsistencyTimeout": 600, "CreatePkAfterFullLoad": false, "TargetTablePrepMode": "DROP_AND_CREATE" }, "TargetMetadata": { "ParallelApplyBufferSize": 0, "ParallelApplyQueuesPerThread": 0, "ParallelApplyThreads": 0, "TargetSchema": "", "InlineLobMaxSize": 0, "ParallelLoadQueuesPerThread": 0, "SupportLobs": true, "LobChunkSize": 0, "TaskRecoveryTableEnabled": false, "ParallelLoadThreads": 0, "LobMaxSize": 32, "BatchApplyEnabled": false, "FullLobMode": false, "LimitedSizeLobMode": true, "LoadMaxFileSize": 0, "ParallelLoadBufferSize": 0 }, "BeforeImageSettings": null, "ControlTablesSettings": { "historyTimeslotInMinutes": 5, "HistoryTimeslotInMinutes": 5, "StatusTableEnabled": false, "SuspendedTablesTableEnabled": false, "HistoryTableEnabled": false, "ControlSchema": "", "FullLoadExceptionTableEnabled": false }, "LoopbackPreventionSettings": null, "CharacterSetSettings": null, "FailTaskWhenCleanTaskResourceFailed": false, "ChangeProcessingTuning": { "StatementCacheSize": 50, "CommitTimeout": 1, "BatchApplyPreserveTransaction": true, "BatchApplyTimeoutMin": 1, "BatchSplitSize": 0, "BatchApplyTimeoutMax": 30, "MinTransactionSize": 1000, "MemoryKeepTime": 60, "BatchApplyMemoryLimit": 500, "MemoryLimitTotal": 1024 }, "ChangeProcessingDdlHandlingPolicy": { "HandleSourceTableDropped": true, "HandleSourceTableTruncated": true, "HandleSourceTableAltered": true }, "PostProcessingRules": null }' TableMappings: '{ "rules": [ { "rule-type": "selection", "rule-id": "1", "rule-name": "1", "object-locator": { "schema-name": "public", "table-name": "%" }, "rule-action": "include", "filters": [] } ] }' TargetEndpointArn: !Ref DMSTargetEndpoint DMSSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: DMS Security Group VpcId: !Ref 'VPC' DMSSecurityGroupEgress1: Type: AWS::EC2::SecurityGroupEgress Properties: Description: To communicate with Redis GroupId: !Ref DMSSecurityGroup IpProtocol: "tcp" FromPort: 5432 ToPort: 5432 CidrIp: !Ref VPCCIDR DMSSecurityGroupEgress2: Type: AWS::EC2::SecurityGroupEgress Properties: Description: To communicate with Redis GroupId: !Ref DMSSecurityGroup IpProtocol: "tcp" FromPort: 3306 ToPort: 3306 CidrIp: !Ref VPCCIDR DMSSubnetGroup: Type: AWS::DMS::ReplicationSubnetGroup Properties: ReplicationSubnetGroupDescription: "DMS Subnet Group" ReplicationSubnetGroupIdentifier: "dms-subnet-group" SubnetIds: [!Ref PrivateSubnetOne, !Ref PrivateSubnetTwo] Tags: - Key: Name Value: "DMS Subnet Group" DMSTimeTravelBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub bucket-${AWS::AccountId}-${AWS::Region}-dms-time-travel BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 DMSTimeTravelBucketPolicy: Type: AWS::S3::BucketPolicy Properties: PolicyDocument: Id: MyPolicy Version: 2012-10-17 Statement: - Sid: HttpsOnly Action: s3:* Effect: Deny Principal: "*" Resource: - !Join ['',['arn:aws:s3:::',!Ref DMSTimeTravelBucket,'/*']] - !Join ['',['arn:aws:s3:::',!Ref DMSTimeTravelBucket]] Condition: Bool: aws:SecureTransport: false Bucket: !Ref DMSTimeTravelBucket