AWSTemplateFormatVersion: 2010-09-09 Description: This stack will be used to deploy the AWS DMS automation framework for existing VPC (qs-1qcbtheaa) Metadata: LICENSE: Apache License Version 2.0 'AWS::CloudFormation::Interface': ParameterGroups: - Label: default: DMS Replication Instance Configuration Parameters: - CreateNewReplicationInstance - ReplInstanceArn - PrivateSubnet1 - PrivateSubnet2 - SecurityGroup - InstanceType - EngineVersion - MultiAz - Label: default: Source Database Configuration Parameters: - SourceDBName - SourceEngine - SourcePassword - SourcePort - SourceEndpointServer - SourceUser - Label: default: Target Database Configuration Parameters: - TargetDBName - TargetEngine - TargetPassword - TargetPort - TargetEndpointServer - TargetUser ParameterLabels: CreateNewReplicationInstance: default: Create New Replication Instance? ReplInstanceArn: default: Existing DMS Replication Instance Arn SourceDBName: default: Source Database Name SourceEngine: default: Source Database Engine SourcePassword: default: Source Database Password SourcePort: default: Source Database Port SourceEndpointServer: default: Source Database Endpoint SourceUser: default: Source Database Username TargetDBName: default: Target Database Name TargetEngine: default: Target Database Engine TargetPassword: default: Target Database Password TargetPort: default: Target Database Port TargetEndpointServer: default: Target Database Endpoint TargetUser: default: Target Database Username EngineVersion: default: Replication Engine Version InstanceType: default: Instance Type MultiAz: default: Enable MultiAZ SecurityGroup: default: Security Group PrivateSubnet1: default: Private Subnet 1 PrivateSubnet2: default: Private Subnet 2 Parameters: CreateNewReplicationInstance: Type: String Default: 'yes' AllowedValues: - 'yes' - 'no' Description: Please specify if you want to create new replication instance ReplInstanceArn: Type: String Description: Arn of the DMS replication instance EngineVersion: AllowedValues: - 3.1.4 - 3.1.3 - 2.4.5 - 2.4.4 - 2.4.3 Default: 3.1.4 Description: DMS replication engine version Type: String InstanceType: 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 Default: dms.c4.large Description: DMS replication instance type Type: String MultiAz: AllowedValues: - 'true' - 'false' Default: 'false' Description: Enable MultiAZ Type: String SecurityGroup: Description: 'Security group ID for DMS replication instance (e.g., sg-1234abcd)' Type: 'AWS::EC2::SecurityGroup::Id' PrivateSubnet1: Description: Choose a private subnet for DMS replication instance Type: 'AWS::EC2::Subnet::Id' PrivateSubnet2: Description: Choose a private subnet for DMS replication instance Type: 'AWS::EC2::Subnet::Id' SourceDBName: Type: String Description: Name of the database in source server SourceEngine: Type: String Description: Database engine running on the source Default: oracle AllowedValues: - mysql - oracle - postgres - mariadb - db2 - azuredb - sybase - sqlserver SourcePassword: Type: String Description: Source database password NoEcho: 'true' SourcePort: Type: String Description: Port on which the source database is running SourceEndpointServer: Type: String Description: Source database hostname, endpoint URL or IP address SourceUser: Type: String Description: Source database user name TargetDBName: Type: String Description: Name of the database in target server TargetEngine: Type: String Description: Database engine running on the target AllowedValues: - mysql - oracle - postgres - mariadb - aurora - aurora-postgresql - redshift - sqlserver Default: aurora-postgresql TargetPassword: Type: String Description: Target database password NoEcho: 'true' TargetPort: Type: String Description: Port on which the target database is running TargetEndpointServer: Type: String Description: Target database hostname, endpoint URL or IP address TargetUser: Type: String Description: Target database user name Conditions: CreateReplicationInstance: !Equals - !Ref CreateNewReplicationInstance - 'yes' Resources: CheckDmsIam: Type: Custom::DmsIam Condition: CreateReplicationInstance Properties: ServiceToken: !GetAtt CheckDmsTaskRolesFunc.Arn CheckDmsTaskRoles: Condition: CreateReplicationInstance Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: 'sts:AssumeRole' ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' Path: / Policies: - PolicyName: dms-iam-access PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'iam:GetRole' - 'iam:CreateRole' - 'iam:AttachRolePolicy' Resource: !Sub 'arn:aws:iam::${AWS::AccountId}:role/dms*' CheckDmsTaskRolesFunc: Condition: CreateReplicationInstance Type: 'AWS::Lambda::Function' Properties: Description: Checks the IAM role for DMS and creates them if they dont exist Handler: index.lambda_handler Runtime: python3.7 Role: !GetAtt CheckDmsTaskRoles.Arn Timeout: 900 Code: ZipFile: | import cfnresponse import json import boto3 import botocore # import cfnresponse iam = boto3.client('iam') roles = ['dms-vpc-role','dms-cloudwatch-logs-role'] assume_doc = { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "dms.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } def lambda_handler(event, context): try: if event['RequestType'] == 'Create': for role_name in roles: try: role = iam.get_role(RoleName=role_name) except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'NoSuchEntity': print(role_name + ' role does not exist. Creating them now') create_role = iam.create_role(RoleName=role_name,AssumeRolePolicyDocument=json.dumps(assume_doc)) else: cfnresponse.send(event, context, cfnresponse.FAILED, {}, '') try: if role_name == 'dms-vpc-role': policy1 = iam.attach_role_policy(RoleName = role_name,PolicyArn = 'arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole') elif role_name == 'dms-cloudwatch-logs-role': policy2 = iam.attach_role_policy(RoleName = role_name,PolicyArn = 'arn:aws:iam::aws:policy/service-role/AmazonDMSCloudWatchLogsRole') except Exception as e: print(e) cfnresponse.send(event, context, cfnresponse.FAILED, {}, '') cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, '') elif (event['RequestType'] == 'Delete') or (event['RequestType'] == 'Update'): print('nothing will be done') cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, '') except Exception as e: print(e) cfnresponse.send(event, context, cfnresponse.FAILED, {}, '') ReplicationInstance: Condition: CreateReplicationInstance Properties: EngineVersion: !Ref EngineVersion MultiAZ: !Ref MultiAz PubliclyAccessible: false ReplicationInstanceClass: !Ref InstanceType ReplicationSubnetGroupIdentifier: !Ref ReplicationSubnetGroup Tags: - Key: Name Value: !Sub '${AWS::StackName}-ReplicationSetup' - Key: Product Value: DMS-Automation-ReplicationSetup - Key: Solution Value: DMS-Automation-ReplicationSetup VpcSecurityGroupIds: - !Ref SecurityGroup Type: 'AWS::DMS::ReplicationInstance' SourceEndpoint: Type: 'AWS::DMS::Endpoint' Properties: DatabaseName: !Ref SourceDBName EndpointType: source EngineName: !Ref SourceEngine Password: !Ref SourcePassword Port: !Ref SourcePort ServerName: !Ref SourceEndpointServer Tags: - Key: Name Value: !Sub '${AWS::StackName}-ReplicationSetup' - Key: Product Value: DMS-Automation-ReplicationSetup - Key: Solution Value: DMS-Automation-ReplicationSetup Username: !Ref SourceUser TargetEndpoint: Type: 'AWS::DMS::Endpoint' Properties: DatabaseName: !Ref TargetDBName EndpointType: target EngineName: !Ref TargetEngine Password: !Ref TargetPassword Port: !Ref TargetPort ServerName: !Ref TargetEndpointServer Tags: - Key: Name Value: !Sub '${AWS::StackName}-ReplicationSetup' - Key: Product Value: DMS-Automation-ReplicationSetup - Key: Solution Value: DMS-Automation-ReplicationSetup Username: !Ref TargetUser ReplicationSubnetGroup: Condition: CreateReplicationInstance DependsOn: CheckDmsIam Properties: ReplicationSubnetGroupDescription: DMS Automation Subnets SubnetIds: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 Tags: - Key: Name Value: !Sub '${AWS::StackName}-ReplicationSetup' - Key: Product Value: DMS-Automation-ReplicationSetup - Key: Solution Value: DMS-Automation-ReplicationSetup Type: 'AWS::DMS::ReplicationSubnetGroup' Outputs: SourceEndpointArn: Description: DMS Source Endpoint Arn Value: !Ref SourceEndpoint TargetEndpointArn: Description: DMS Target Endpoint Arn Value: !Ref TargetEndpoint ReplicationInstanceArn: Description: DMS Replication Instance Arn Value: !If [CreateReplicationInstance, !Ref ReplicationInstance, !Ref ReplInstanceArn]