Back to Checks
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 CloudRun
prowler aws --checks redshift_cluster_public_accessRecommendation
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-accessibleTerraform
# 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 exposureOther
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