Back to Checks
aws

Redshift cluster is not publicly exposed to the Internet

redshift_cluster_public_access
Service: redshiftSeverity: critical
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:AwsRedshiftCluster

Amazon Redshift clusters with publicly accessible endpoints in public subnets and security groups allowing TCP from 0.0.0.0/0 or ::/0 are identified as internet-exposed.

Public endpoints without internet reachability due to private subnets or restrictive rules are recognized separately.

Risk

Internet-exposed Redshift endpoints allow direct DB access from any host, impacting:

  • Confidentiality: credential brute force, unauthorized queries, data exfiltration
  • Integrity: unauthorized writes or schema changes
  • Availability: scanning/abuse leading to connection exhaustion or disruption

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks redshift_cluster_public_access

Recommendation

Prefer private connectivity: disable public access, place clusters in private subnets, and apply least privilege security groups limited to trusted CIDRs or VPC sources. Use defense in depth with VPN/peering/endpoints, strong authentication, and monitoring. Avoid 0.0.0.0/0 or ::/0 to database ports.

Remediation

CLI

aws redshift modify-cluster --cluster-identifier <CLUSTER_ID> --no-publicly-accessible

Terraform

# Redshift cluster not publicly accessible
resource "aws_redshift_cluster" "<example_resource_name>" {
  cluster_identifier  = "<example_resource_id>"
  node_type           = "dc2.large"
  cluster_type        = "single-node"
  master_username     = "<example_username>"
  master_password     = "<example_password>"

  publicly_accessible = false  # Critical: disables public access to prevent Internet exposure
}

NativeIaC

# CloudFormation: Redshift cluster not publicly accessible
Resources:
  <example_resource_name>:
    Type: AWS::Redshift::Cluster
    Properties:
      ClusterType: single-node
      DBName: <example_db_name>
      MasterUsername: <example_username>
      MasterUserPassword: <example_password>
      NodeType: dc2.large
      PubliclyAccessible: false  # Critical: disables public access to prevent Internet exposure

Other

1Open the AWS Management Console and go to Amazon Redshift
2Select your cluster
3Click Edit (or Actions > Modify)
4Set Publicly accessible to Off/No
5Save changes and apply the modification

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.ec2.ec2_client import ec2_client
from prowler.providers.aws.services.ec2.lib.security_groups import check_security_group
from prowler.providers.aws.services.redshift.redshift_client import redshift_client
from prowler.providers.aws.services.vpc.vpc_client import vpc_client


class redshift_cluster_public_access(Check):
    def execute(self):
        findings = []
        for cluster in redshift_client.clusters:
            report = Check_Report_AWS(metadata=self.metadata(), resource=cluster)
            report.status = "PASS"
            report.status_extended = (
                f"Redshift Cluster {cluster.id} is not publicly accessible."
            )
            # 1. Check if Redshift Cluster is publicly accessible
            if cluster.endpoint_address and cluster.public_access:
                report.status_extended = f"Redshift Cluster {cluster.id} has the endpoint {cluster.endpoint_address} set as publicly accessible but is not publicly exposed."
                # 2. Check if Redshift Cluster is in a public subnet
                if any(
                    subnet in vpc_client.vpc_subnets
                    and vpc_client.vpc_subnets[subnet].public
                    for subnet in cluster.subnets
                ):
                    report.status_extended = f"Redshift Cluster {cluster.id} has the endpoint {cluster.endpoint_address} set as publicly accessible in a public subnet but is not publicly exposed."
                    # 3. Check if any Redshift Cluster Security Group is publicly open
                    for sg_id in getattr(cluster, "vpc_security_groups", []):
                        sg_arn = f"arn:{redshift_client.audited_partition}:ec2:{cluster.region}:{redshift_client.audited_account}:security-group/{sg_id}"
                        if sg_arn in ec2_client.security_groups:
                            for ingress_rule in ec2_client.security_groups[
                                sg_arn
                            ].ingress_rules:
                                if check_security_group(
                                    ingress_rule, "tcp", any_address=True
                                ):
                                    report.status = "FAIL"
                                    report.status_extended = f"Redshift Cluster {cluster.id} has the endpoint {cluster.endpoint_address} set as publicly accessible and it is exposed to the Internet by security group ({sg_id}) in a public subnet."
                                    break
                        if report.status == "FAIL":
                            break

            findings.append(report)

        return findings