EMR Cluster without Public IP.
Amazon EMR clusters in non-terminated states are assessed for public IP assignment on cluster nodes (primary and workers). The finding identifies clusters whose instances are reachable via public IPs rather than private VPC addresses.
Risk
Publicly reachable EMR nodes expose admin UIs and SSH to the Internet, enabling brute force and service exploits. A compromised primary node can alter jobs and exfiltrate data from S3/HDFS, degrading confidentiality and integrity, and disrupt workloads, impacting availability.
Run this check with Prowler
Run in Prowler Cloudprowler aws --checks emr_cluster_master_nodes_no_public_ipRecommendation
Run EMR in private subnets without public IPs. Use VPC endpoints for AWS services and NAT only when needed. Enforce least privilege security groups, avoid 0.0.0.0/0, and prefer SSM or a bastion for admin access. Keep EMR block public access enabled and favor private connectivity for external dependencies.
Remediation
Terraform
# Terraform: Launch EMR in a private subnet (no public IPs)
resource "aws_emr_cluster" "<example_resource_name>" {
name = "<example_resource_name>"
release_label = "emr-6.10.0"
master_instance_type = "m5.xlarge"
core_instance_type = "m5.xlarge"
service_role = "EMR_DefaultRole"
ec2_attributes {
instance_profile = "EMR_EC2_DefaultRole"
subnet_id = "<example_resource_id>" # CRITICAL: private subnet ensures no public IPs
}
}NativeIaC
# CloudFormation: Launch EMR in a private subnet (no public IPs)
Resources:
<example_resource_name>:
Type: AWS::EMR::Cluster
Properties:
Name: <example_resource_name>
ReleaseLabel: emr-6.10.0
ServiceRole: EMR_DefaultRole
JobFlowRole: EMR_EC2_DefaultRole
Instances:
Ec2SubnetId: <example_resource_id> # CRITICAL: use a PRIVATE subnet to prevent public IPs
InstanceGroups:
- InstanceRole: MASTER
InstanceType: m5.xlarge
InstanceCount: 1
- InstanceRole: CORE
InstanceType: m5.xlarge
InstanceCount: 1Other
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.emr.emr_client import emr_client
from prowler.providers.aws.services.emr.emr_service import ClusterStatus
class emr_cluster_master_nodes_no_public_ip(Check):
def execute(self):
findings = []
for cluster in emr_client.clusters.values():
if cluster.status not in (
ClusterStatus.TERMINATED,
ClusterStatus.TERMINATED_WITH_ERRORS,
):
report = Check_Report_AWS(metadata=self.metadata(), resource=cluster)
if cluster.public:
report.status = "FAIL"
report.status_extended = (
f"EMR Cluster {cluster.id} has a Public IP."
)
else:
report.status = "PASS"
report.status_extended = (
f"EMR Cluster {cluster.id} does not have a Public IP."
)
findings.append(report)
return findingsReferences
- https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-vpc-subnet.html
- https://aws.amazon.com/blogs/aws/new-launch-amazon-emr-clusters-in-private-subnets/
- https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html
- https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-clusters-in-a-vpc.html
- https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-vpc-launching-job-flows.html