Skip to content

DMS replication instances should not be publicly accessible

DMS replication instances process and transfer data between source and target databases, often including sensitive production data. A publicly accessible replication instance exposes migration traffic to the internet, creating a direct attack surface where an adversary could intercept credentials, exploit unpatched vulnerabilities, or access data in transit.

Keeping replication instances private forces all connectivity through VPC networking, VPN tunnels, or AWS PrivateLink, where security groups and NACLs provide enforceable boundaries.

Retrofit consideration

Changing publicly_accessible from true to false on a running aws_dms_replication_instance issues a ModifyReplicationInstance API call that can interrupt active replication tasks and, depending on instance class and workload timing, may trigger a restart. Confirm that private connectivity (VPC peering, VPN, or Direct Connect) is in place before making the change, and schedule it during a maintenance window.

Implementation

Choose the approach that matches how you manage Terraform.

Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.

module "dms" {
  source  = "soc2.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "pcidss.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "hipaa.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "nist80053.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "fedrampmoderate.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "cisv80ig1.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "nist800171.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "cisacyberessentials.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "nydfs23.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "ffiec.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "acscessentialeight.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "cfrpart11.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "rbicybersecurity.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "rbiitfnbfc.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "fedramplow.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "hipaasecurity2003.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "nistcsfv11.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "nist80053rev4.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

module "dms" {
  source  = "pcidssv321.compliance.tf/terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]
}

If you use terraform-aws-modules/dms/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.

module "dms" {
  source  = "terraform-aws-modules/dms/aws"
  version = ">=2.0.0"

  create_iam_roles                     = false
  repl_instance_class                  = "dms.t3.small"
  repl_instance_id                     = "abc123"
  repl_instance_vpc_security_group_ids = ["sg-abc12345"]
  repl_subnet_group_description        = "DMS Subnet group for pofix testing"
  repl_subnet_group_name               = "abc123"
  repl_subnet_group_subnet_ids         = ["subnet-abc123", "subnet-def456"]

  repl_instance_publicly_accessible = false
}

Use AWS provider resources directly. See docs for the resources involved: aws_dms_replication_instance.

resource "aws_dms_replication_instance" "this" {
  replication_instance_class = "dms.t3.small"
  replication_instance_id    = "pofix-abc123"

  publicly_accessible = false
}

What this control checks

The policy checks the publicly_accessible argument on aws_dms_replication_instance. The argument must be explicitly false or omitted entirely (the default is false). Setting publicly_accessible = true assigns a public IP to the instance and fails the control. For a fully private configuration, pair this with a replication_subnet_group_id pointing to an aws_dms_replication_subnet_group whose subnets have no internet gateway route, and use vpc_security_group_ids to restrict inbound traffic to the required database ports from known CIDR ranges.

Common pitfalls

  • Default subnet group may use public subnets

    Omit replication_subnet_group_id and DMS falls back to the default VPC subnet group, which may include public subnets. Even with publicly_accessible = false, placing an instance in a public subnet with a permissive security group weakens your posture. Always pin the instance to an explicit aws_dms_replication_subnet_group backed by private subnets.

  • Modify can interrupt replication

    Active replication tasks can be interrupted when you toggle publicly_accessible on a running instance. The underlying ModifyReplicationInstance call may trigger a restart depending on instance class and workload timing. Schedule this change during a maintenance window, not mid-migration.

  • Security group still matters when private

    Removing the public IP is not enough on its own. An overly broad security group rule, such as 0.0.0.0/0 inbound on a database port, referenced in vpc_security_group_ids can still allow lateral movement from within the VPC. Scope ingress rules to specific database ports and source CIDRs.

Audit evidence

Config rule evaluation results showing all aws_dms_replication_instance resources as COMPLIANT, or equivalent output from a CSPM tool scanning the account. Console screenshots of the DMS replication instance details page showing "Publicly Accessible" as "No" work as supplementary evidence.

CloudTrail entries for CreateReplicationInstance and ModifyReplicationInstance should show PubliclyAccessible set to false. For audits covering an extended period, periodic compliance scan reports demonstrating continuous compliance over the review window round out the evidence package.

Framework-specific interpretation

SOC 2: CC6.1 and CC6.6 both address system boundaries and network-level access controls. Disabling public accessibility enforces a network perimeter around data in transit through DMS, which is what examiners expect to see against these criteria.

PCI DSS v4.0: Requirement 1.3 mandates denying all traffic not necessary for the CDE. A publicly accessible replication instance moving cardholder data doesn't meet that bar.

HIPAA Omnibus Rule 2013: A DMS instance migrating health records with a public IP may not satisfy the access control requirements at 45 CFR 164.312(a)(1), which limits ePHI access to authorized persons and processes. Internet-accessible migration infrastructure is a recognized audit finding in healthcare environments.

NIST SP 800-53 Rev 5: Three controls converge here: SC-7 (Boundary Protection), AC-4 (Information Flow Enforcement), and AC-17 (Remote Access). Keeping migration traffic off the public internet and inside controlled network segments is the boundary protection model all three describe.

FedRAMP Moderate Baseline Rev 4: SC-7 and AC-4 require that system components not be directly reachable from the internet unless explicitly authorized. DMS instances handling federal data belong in private subnets with no public IP assigned, and this control enforces exactly that.

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: dms_replication_instance_not_publicly_accessible

  • AWS Config Managed Rule: DMS_REPLICATION_NOT_PUBLIC

  • Checkov Check: CKV_AWS_89

  • Powerpipe Control: aws_compliance.control.dms_replication_instance_not_publicly_accessible

  • Prowler Check: dms_instance_no_public_access

  • AWS Security Hub Control: DMS.1

  • KICS Query: 030d3b18-1821-45b4-9e08-50efbe7becbb

Last reviewed: 2026-03-09