AWSTemplateFormatVersion: 2010-09-09 Description: This stack will be used to deploy the AWS DMS automation framework for existing VPC (qs-1qcbthea2) Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Network configuration Parameters: - AvailabilityZones - KeyPairName - RemoteAccessCIDR - Label: default: Migration Setup Parameters: - MigNotify - TaskName - DBInstanceClass - SampleDbPassword - Label: default: AWS DMS configuration for new replication instance Parameters: - DmsEngineVersion - DmsInstanceType - DmsMultiAz - Label: default: AWS Quick Start configuration Parameters: - QSS3BucketName - QSS3KeyPrefix # Parameter Labels ParameterLabels: DmsEngineVersion: default: AWS DMS Engine version DmsInstanceType: default: Instance type DmsMultiAz: default: Multi AZ SampleDbPassword: default: Sample DB password DBInstanceClass: default: Sample DB instance class MigNotify: default: Notification email TaskName: default: Task name AvailabilityZones: default: Availability Zones KeyPairName: default: Key pair name RemoteAccessCIDR: default: Remote access CIDR QSS3BucketName: default: Quickstart S3 Bucket Name QSS3KeyPrefix: default: Quickstart S3 Prefix Parameters: SampleDbPassword: AllowedPattern: >- ^(?=^.{8,255}$)(?=.*[a-z])(?=.*[A-Z])(?=.*\d)((?=.*[^A-Za-z0-9])(?!.*[@/"'])).*$ ConstraintDescription: "Min 8 chars. Must include 1 uppercase, 1 lowercase, 1 number, 1 (non / @ \" ') symbol" Description: "The database admin account password. The password must have a minimum of 8 characters and must include 1 uppercase letter, 1 lowercase letter, 1 number, and 1 (non / @ \" ') symbol." MaxLength: "64" MinLength: "8" NoEcho: "True" Type: String DBInstanceClass: Type: String Description: The instance size of the source database that will host the sample code. AllowedValues: - db.r5.large - db.r5.xlarge - db.r5.2xlarge - db.r5.4xlarge - db.r5.12xlarge - db.r5.24xlarge - db.r4.large - db.r4.xlarge - db.r4.2xlarge - db.r4.4xlarge - db.r4.8xlarge - db.r4.16xlarge ConstraintDescription: "Must select a valid database instance type." Default: db.r5.large MigNotify: Type: String Description: The email address that receives notifications on the migration status. TaskName: Type: String Description: The name of the AWS DMS task. If left empty, the stack name is used. Default: '' AvailabilityZones: Description: >- List of Availability Zones to use for the subnets in the VPC. Only two Availability Zones are used for this deployment, and the logical order of your selections is preserved. Type: 'List' KeyPairName: ConstraintDescription: "Name of an existing EC2 key pair." Description: The name of an existing public/private key pair, for connecting to your instance. Type: "AWS::EC2::KeyPair::KeyName" RemoteAccessCIDR: AllowedPattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/([0-9]|[1-2][0-9]|3[0-2]))$" ConstraintDescription: "CIDR block parameter must be in the form x.x.x.x/x" Description: "Allowed CIDR block for external SSH access." Default: 10.0.0.0/16 Type: String QSS3BucketName: AllowedPattern: "^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" ConstraintDescription: "Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-)." Default: aws-quickstart Description: "S3 bucket name for the Quick Start assets. Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-)." Type: String QSS3KeyPrefix: AllowedPattern: "^[0-9a-zA-Z-/]*$" ConstraintDescription: "Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/)." Default: quickstart-aws-dms-automation/ Description: "S3 key prefix for the Quick Start assets. Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/)." Type: String DmsEngineVersion: Default: 3.1.4 Type: String Description: AWS DMS replication engine version. AllowedValues: - 3.1.4 - 3.1.3 - 2.4.5 - 2.4.4 - 2.4.3 DmsInstanceType: Default: dms.c4.large Type: String Description: AWS DMS replication instance size. AllowedValues: - dms.t2.micro - dms.t2.small - dms.t2.medium - dms.t2.large - dms.c4.large - dms.c4.xlarge - dms.c4.2xlarge - dms.c4.4xlarge DmsMultiAz: Default: 'true' Type: String Description: AWS DMS replication instance deployment across multiple Availability Zones. AllowedValues: - 'true' - 'false' Resources: VPCStack: Type: 'AWS::CloudFormation::Stack' DependsOn: - CopyFiles Properties: TemplateURL: !Sub https://${QSS3BucketName}.s3.amazonaws.com/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template Parameters: AvailabilityZones: !Join - ',' - !Ref AvailabilityZones NumberOfAZs: '2' BastionStack: Type: 'AWS::CloudFormation::Stack' DependsOn: CopyFiles Properties: TemplateURL: !Sub https://${QSS3BucketName}.s3.amazonaws.com/${QSS3KeyPrefix}submodules/quickstart-linux-bastion/templates/linux-bastion.template Parameters: KeyPairName: !Ref KeyPairName PublicSubnet1ID: !GetAtt VPCStack.Outputs.PublicSubnet1ID PublicSubnet2ID: !GetAtt VPCStack.Outputs.PublicSubnet2ID RemoteAccessCIDR: !Ref RemoteAccessCIDR VPCID: !GetAtt VPCStack.Outputs.VPCID SampleSecurityGroup: Type: "AWS::EC2::SecurityGroup" Properties: GroupDescription: "Allow access to sample resources" SecurityGroupEgress: - CidrIp: 0.0.0.0/0 FromPort: -1 IpProtocol: '-1' ToPort: -1 SecurityGroupIngress: - CidrIp: !Ref RemoteAccessCIDR FromPort: 1521 IpProtocol: tcp ToPort: 1521 - CidrIp: !Ref RemoteAccessCIDR FromPort: 5432 IpProtocol: tcp ToPort: 5432 VpcId: !GetAtt VPCStack.Outputs.VPCID Tags: - Key: Name Value: !Sub SampleSGGroup-${AWS::StackName} SampleSecurityGroupIngress: Properties: GroupId: !GetAtt 'SampleSecurityGroup.GroupId' IpProtocol: '-1' SourceSecurityGroupId: !Ref SampleSecurityGroup Description: 'Self Reference' Type: 'AWS::EC2::SecurityGroupIngress' AuroraStack: Type: AWS::CloudFormation::Stack DependsOn: CopyFiles Properties: TemplateURL: !Sub https://${QSS3BucketName}.s3.amazonaws.com/${QSS3KeyPrefix}submodules/quickstart-amazon-aurora-postgresql/templates/aurora_postgres.template.yaml Parameters: Subnet1ID: !GetAtt VPCStack.Outputs.PrivateSubnet1AID Subnet2ID: !GetAtt VPCStack.Outputs.PrivateSubnet2AID VPCID: !GetAtt VPCStack.Outputs.VPCID CustomDBSecurityGroup: !GetAtt 'SampleSecurityGroup.GroupId' DBInstanceClass: !Ref DBInstanceClass DBMasterUserPassword: !Ref SampleDbPassword NotificationList: !Ref MigNotify DMSCodePiplineStack: Type: 'AWS::CloudFormation::Stack' Properties: TemplateURL: !Sub https://${QSS3BucketName}.s3.amazonaws.com/${QSS3KeyPrefix}templates/dms-automation-code-pipeline.template.yaml Parameters: MigNotify: !Ref MigNotify TaskName: !Ref TaskName CodeBuildVpc: !GetAtt VPCStack.Outputs.VPCID CodeBuildSubnet: !GetAtt VPCStack.Outputs.PrivateSubnet1AID CodeBuildSecurityGroup: !GetAtt 'SampleSecurityGroup.GroupId' S3BucketName: !Ref S3Bucket S3BucketKey: !Sub ${QSS3KeyPrefix}scripts/test.zip TargetEndpoint: !GetAtt AuroraStack.Outputs.RDSEndPointAddress TargetDbName: 'AuroraPostgresDB' TargetDbUser: 'pgadmin' TargetDbPassword: !Ref SampleDbPassword DmsSourceArn: !GetAtt DMSReplicationStack.Outputs.SourceEndpointArn DmsTargetArn: !GetAtt DMSReplicationStack.Outputs.TargetEndpointArn DmsReplicationArn: !GetAtt DMSReplicationStack.Outputs.ReplicationInstanceArn CreateSample: 'yes' FullLoadOnly: 'no' SourceEndpoint: !GetAtt DMSSampleSourceSetup.Outputs.SampleSourceEndpoint SourceDbName: 'ORCL' SourceDbPassword: !Ref SampleDbPassword SourceDbUser: 'master' DMSSampleSourceSetup: Type: AWS::CloudFormation::Stack DependsOn: CopyFiles Properties: TemplateURL: !Sub https://${QSS3BucketName}.s3.amazonaws.com/${QSS3KeyPrefix}templates/dms-automation-sample-source.template.yaml Parameters: VPCID: !GetAtt VPCStack.Outputs.VPCID Subnet1ID: !GetAtt VPCStack.Outputs.PrivateSubnet1AID Subnet2ID: !GetAtt VPCStack.Outputs.PrivateSubnet2AID DBInstanceClass: !Ref DBInstanceClass DBMasterUserPassword: !Ref SampleDbPassword CustomDBSecurityGroup: !GetAtt SampleSecurityGroup.GroupId DMSReplicationStack: # Condition: CreateReplicationInst Type: AWS::CloudFormation::Stack DependsOn: CopyFiles Properties: TemplateURL: !Sub https://${QSS3BucketName}.s3.amazonaws.com/${QSS3KeyPrefix}templates/dms-automation-replication-setup.template.yaml Parameters: CreateNewReplicationInstance: 'yes' ReplInstanceArn: '' PrivateSubnet1: !GetAtt VPCStack.Outputs.PrivateSubnet1AID PrivateSubnet2: !GetAtt VPCStack.Outputs.PrivateSubnet2AID SecurityGroup: !GetAtt 'SampleSecurityGroup.GroupId' MultiAz: !Ref DmsMultiAz InstanceType: !Ref DmsInstanceType EngineVersion: !Ref DmsEngineVersion SourceDBName: 'ORCL' SourceEngine: 'oracle' SourcePassword: !Ref SampleDbPassword SourcePort: '1521' SourceEndpointServer: !GetAtt DMSSampleSourceSetup.Outputs.SampleSourceEndpoint SourceUser: 'master' TargetDBName: 'AuroraPostgresDB' TargetEngine: 'aurora-postgresql' TargetPassword: !Ref SampleDbPassword TargetPort: '5432' TargetEndpointServer: !GetAtt AuroraStack.Outputs.RDSEndPointAddress TargetUser: 'pgadmin' S3Bucket: Type: AWS::S3::Bucket Properties: VersioningConfiguration: Status: Enabled CopyS3FunctionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - 'sts:AssumeRole' ManagedPolicyArns: - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' Path: / Policies: - PolicyName: s3-access PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 's3:PutObject' - 's3:GetObject' - 's3:DeleteObject' - 's3:ListBucketVersion*' - 's3:ListBucket' - 's3:DeleteObjectVersion' - 's3:GetObjectVersion*' Resource: - !Sub 'arn:${AWS::Partition}:s3:::${S3Bucket}' - !Sub 'arn:${AWS::Partition}:s3:::${S3Bucket}/*' - !Sub 'arn:${AWS::Partition}:s3:::${QSS3BucketName}' - !Sub 'arn:${AWS::Partition}:s3:::${QSS3BucketName}/*' CopyFiles: Type: 'Custom::CopyFiles' Properties: ServiceToken: !GetAtt - CopyS3Function - Arn Bucket: !Ref S3Bucket Source: !Ref QSS3BucketName Prefix: !Ref QSS3KeyPrefix Objects: - scripts/test.zip CopyS3Function: Type: 'AWS::Lambda::Function' Properties: Code: ZipFile: | import cfnresponse import boto3 import traceback import json import time def lambda_handler(event, context): try: print('Received event: %s' % json.dumps(event, indent=2)) bucket = event['ResourceProperties']['Bucket'] source_bucket = event['ResourceProperties']['Source'] source_bucket_prefix = event['ResourceProperties']['Prefix'] objects = event['ResourceProperties']['Objects'] if event['RequestType'] == 'Delete': s3 = boto3.resource('s3') bucket = s3.Bucket(bucket) bucket.object_versions.all().delete() print('Delete stack in progress the bucket is emptied') elif event['RequestType'] == 'Update': print('Stack is getting updated nothing will be done') elif event['RequestType'] == 'Create': s3 = boto3.client('s3') for o in objects: key = source_bucket_prefix + o copy_source={ 'Bucket': source_bucket, 'Key': key } s3.copy_object(CopySource=copy_source, Bucket=bucket, Key=key) cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, '') except: print(traceback.print_exc()) cfnresponse.send(event, context, cfnresponse.FAILED, {}, '') Role: !GetAtt - CopyS3FunctionRole - Arn Runtime: python3.7 Handler: index.lambda_handler Timeout: 600