DMS Replication Instance Is Not Publicly Exposed to the Internet
Overview
This check identifies AWS Database Migration Service (DMS) replication instances that are publicly accessible from the internet. A replication instance is considered exposed when both of these conditions are true:
- The
PubliclyAccessiblesetting is enabled - An attached security group allows inbound traffic from any address (
0.0.0.0/0or::/0)
DMS replication instances handle sensitive database migration traffic. Keeping them private protects your data during migration.
Risk
Severity: Critical
Publicly accessible replication instances create serious security risks:
- Data theft: Migration data and database credentials can be intercepted or stolen
- Data tampering: Attackers may alter migration tasks or inject malicious records into your databases
- Service disruption: DDoS attacks can halt replication and delay your migration cutover
Remediation Steps
Prerequisites
You need permission to modify DMS replication instances and EC2 security groups in your AWS account.
Required IAM permissions
Your IAM user or role needs these permissions:
dms:DescribeReplicationInstancesdms:ModifyReplicationInstanceec2:DescribeSecurityGroupsec2:RevokeSecurityGroupIngressec2:AuthorizeSecurityGroupIngress
AWS Console Method
Step 1: Identify exposed replication instances
- Open the AWS DMS Console
- Review each replication instance
- Click on an instance to view its details
- Note instances where Publicly accessible shows "Yes"
Step 2: Fix security group rules (quick fix)
For each exposed instance:
- In the instance details, find VPC security groups
- Click on each security group ID to open it in a new tab
- Select the Inbound rules tab
- Look for rules with source
0.0.0.0/0or::/0 - Click Edit inbound rules
- Delete or replace overly permissive rules:
- Remove rules allowing all IPs
- Add rules that only allow specific IP addresses or CIDR ranges that need access
- Click Save rules
Step 3: Disable public accessibility (recommended)
For a more secure configuration, disable public access entirely:
- Return to the DMS Replication Instances page
- Select the instance checkbox
- Click Actions > Modify
- Scroll to Network and security
- Set Publicly accessible to No
- Click Modify
Important: Disabling public access causes the instance to restart. Plan for a brief interruption to any running migration tasks.
AWS CLI (optional)
List all replication instances and their public access status:
aws dms describe-replication-instances \
--region us-east-1 \
--query 'ReplicationInstances[*].[ReplicationInstanceIdentifier,PubliclyAccessible,VpcSecurityGroups[*].VpcSecurityGroupId]' \
--output table
Get the ARN of a specific replication instance:
aws dms describe-replication-instances \
--region us-east-1 \
--filters Name=replication-instance-id,Values=<your-instance-id> \
--query 'ReplicationInstances[0].ReplicationInstanceArn' \
--output text
Check security group rules for overly permissive access:
aws ec2 describe-security-groups \
--region us-east-1 \
--group-ids <security-group-id> \
--query 'SecurityGroups[*].IpPermissions[?contains(IpRanges[*].CidrIp, `0.0.0.0/0`)]' \
--output json
Remove an overly permissive inbound rule:
aws ec2 revoke-security-group-ingress \
--region us-east-1 \
--group-id <security-group-id> \
--protocol tcp \
--port <port-number> \
--cidr 0.0.0.0/0
Modify the replication instance to disable public access:
aws dms modify-replication-instance \
--region us-east-1 \
--replication-instance-arn <replication-instance-arn> \
--no-publicly-accessible \
--apply-immediately
Replace:
<your-instance-id>with your replication instance identifier<security-group-id>with the VPC security group ID<port-number>with the port to restrict<replication-instance-arn>with the full ARN of the instance
CloudFormation (optional)
Use this template to create a secure DMS replication instance with public access disabled:
AWSTemplateFormatVersion: '2010-09-09'
Description: Secure DMS Replication Instance
Parameters:
ReplicationInstanceIdentifier:
Type: String
Description: Unique identifier for the replication instance
ReplicationInstanceClass:
Type: String
Default: dms.t3.micro
Description: Instance class for the replication instance
SubnetGroupIdentifier:
Type: String
Description: Identifier for the replication subnet group
VpcSecurityGroupIds:
Type: List<AWS::EC2::SecurityGroup::Id>
Description: List of VPC security group IDs
Resources:
SecureDMSReplicationInstance:
Type: AWS::DMS::ReplicationInstance
Properties:
ReplicationInstanceIdentifier: !Ref ReplicationInstanceIdentifier
ReplicationInstanceClass: !Ref ReplicationInstanceClass
PubliclyAccessible: false
ReplicationSubnetGroupIdentifier: !Ref SubnetGroupIdentifier
VpcSecurityGroupIds: !Ref VpcSecurityGroupIds
Outputs:
ReplicationInstanceArn:
Description: ARN of the replication instance
Value: !Ref SecureDMSReplicationInstance
Key security settings:
PubliclyAccessible: falseensures the instance stays privateReplicationSubnetGroupIdentifiershould reference private subnetsVpcSecurityGroupIdsshould reference security groups with restrictive rules
Terraform (optional)
Use this configuration to create a secure DMS replication instance:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
variable "replication_instance_id" {
description = "Unique identifier for the replication instance"
type = string
}
variable "replication_instance_class" {
description = "Instance class for the replication instance"
type = string
default = "dms.t3.micro"
}
variable "replication_subnet_group_id" {
description = "Identifier for the replication subnet group"
type = string
}
variable "vpc_security_group_ids" {
description = "List of VPC security group IDs"
type = list(string)
}
resource "aws_dms_replication_instance" "secure_instance" {
replication_instance_id = var.replication_instance_id
replication_instance_class = var.replication_instance_class
publicly_accessible = false
replication_subnet_group_id = var.replication_subnet_group_id
vpc_security_group_ids = var.vpc_security_group_ids
tags = {
Name = var.replication_instance_id
}
}
output "replication_instance_arn" {
description = "ARN of the replication instance"
value = aws_dms_replication_instance.secure_instance.replication_instance_arn
}
Key security settings:
publicly_accessible = falsekeeps the instance privatereplication_subnet_group_idshould reference private subnetsvpc_security_group_idsshould list security groups with least-privilege rules
Verification
After making changes, verify the fix:
- Return to the DMS Replication Instances page
- Click on your replication instance
- Confirm Publicly accessible shows "No"
- Check that attached security groups no longer have
0.0.0.0/0inbound rules
CLI verification commands
Check public accessibility status:
aws dms describe-replication-instances \
--region us-east-1 \
--filters Name=replication-instance-id,Values=<your-instance-id> \
--query 'ReplicationInstances[0].PubliclyAccessible' \
--output text
Expected output: False
Verify security group has no open inbound rules:
aws ec2 describe-security-groups \
--region us-east-1 \
--group-ids <security-group-id> \
--query 'SecurityGroups[*].IpPermissions[?IpRanges[?CidrIp==`0.0.0.0/0`]]' \
--output json
Expected output: [] (empty array)
Run the Prowler check to confirm the fix:
prowler aws --checks dms_instance_no_public_access
Additional Resources
- AWS DMS Replication Instance Documentation
- AWS DMS Security Best Practices
- VPC Security Groups for DMS
- AWS Security Hub DMS Controls
Notes
-
Downtime consideration: Modifying the
PubliclyAccessiblesetting causes the replication instance to restart. Schedule this change during a maintenance window if migrations are running. -
Private subnet requirement: For instances with public access disabled, ensure your replication subnet group uses private subnets with proper routing to reach source and target databases.
-
Alternative connectivity: If you need to access DMS from on-premises networks, use AWS VPN, VPC peering, AWS Direct Connect, or AWS PrivateLink instead of public internet access.
-
Security group best practices: Only allow inbound traffic from specific IP ranges that genuinely need access. Common patterns include allowing only the source database IP and target database IP.
-
Compliance frameworks: This check maps to AWS Foundational Security Best Practices, PCI DSS, C5, and KISA-ISMS-P requirements.