From 573975f3fec1ff4569578e1794c4ee96fed3f072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Wed, 29 Oct 2025 20:37:14 +0100 Subject: [PATCH] chore(aws): enhance metadata for `emr` service (#9002) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 1 + ...account_public_block_enabled.metadata.json | 34 +++++++++++------- ...er_master_nodes_no_public_ip.metadata.json | 35 +++++++++++++------ ...r_cluster_publicly_accesible.metadata.json | 29 +++++++++------ 4 files changed, 64 insertions(+), 35 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index ec00670b35..15fe3addd8 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -71,6 +71,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS CloudFront service metadata to new format [(#8829)](https://github.com/prowler-cloud/prowler/pull/8829) - Deprecate user authentication for M365 provider [(#8865)](https://github.com/prowler-cloud/prowler/pull/8865) - Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) +- Update AWS EMR service metadata to new format [(#9002)](https://github.com/prowler-cloud/prowler/pull/9002) - Update AWS EventBridge service metadata to new format [(#9003)](https://github.com/prowler-cloud/prowler/pull/9003) - Update AWS Firehose service metadata to new format [(#9004)](https://github.com/prowler-cloud/prowler/pull/9004) - Update AWS FMS service metadata to new format [(#9005)](https://github.com/prowler-cloud/prowler/pull/9005) diff --git a/prowler/providers/aws/services/emr/emr_cluster_account_public_block_enabled/emr_cluster_account_public_block_enabled.metadata.json b/prowler/providers/aws/services/emr/emr_cluster_account_public_block_enabled/emr_cluster_account_public_block_enabled.metadata.json index 14616f99c2..bdfd336d86 100644 --- a/prowler/providers/aws/services/emr/emr_cluster_account_public_block_enabled/emr_cluster_account_public_block_enabled.metadata.json +++ b/prowler/providers/aws/services/emr/emr_cluster_account_public_block_enabled/emr_cluster_account_public_block_enabled.metadata.json @@ -1,26 +1,34 @@ { "Provider": "aws", "CheckID": "emr_cluster_account_public_block_enabled", - "CheckTitle": "EMR Account Public Access Block enabled.", - "CheckType": [], + "CheckTitle": "EMR account has Block Public Access enabled", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices" + ], "ServiceName": "emr", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:emr:region:account-id", + "ResourceIdTemplate": "", "Severity": "high", - "ResourceType": "AwsAccount", - "Description": "EMR Account Public Access Block enabled.", - "Risk": "EMR Clusters must have Account Public Access Block enabled.", - "RelatedUrl": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + "ResourceType": "Other", + "Description": "Amazon EMR account-level **Block Public Access** configuration is assessed per Region. When `BlockPublicSecurityGroupRules` is enabled, clusters cannot use security groups that allow inbound public sources (`0.0.0.0/0`, `::/0`) except on permitted ports.", + "Risk": "Public EMR-facing rules enable Internet reachability to cluster nodes and UIs, inviting brute force and remote exploits.\n\nAttackers can exfiltrate job data, alter processing, or pivot into the VPC, degrading **confidentiality**, **integrity**, and **availability** through data theft, tampering, and service disruption.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/EMR/block-public-access.html", + "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + "https://github.com/cloudmatos/matos/tree/master/remediations/aws/emr/block-emr-public-access" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "https://github.com/cloudmatos/matos/tree/master/remediations/aws/emr/block-emr-public-access", - "Terraform": "" + "CLI": "aws emr put-block-public-access-configuration --block-public-access-configuration BlockPublicSecurityGroupRules=true", + "NativeIaC": "```yaml\n# CloudFormation: Enable EMR Block Public Access (account/Region level)\nResources:\n EmrBpaRole:\n Type: AWS::IAM::Role\n Properties:\n AssumeRolePolicyDocument:\n Version: '2012-10-17'\n Statement:\n - Effect: Allow\n Principal:\n Service: lambda.amazonaws.com\n Action: sts:AssumeRole\n Policies:\n - PolicyName: EmrBpaPut\n PolicyDocument:\n Version: '2012-10-17'\n Statement:\n - Effect: Allow\n Action: elasticmapreduce:PutBlockPublicAccessConfiguration\n Resource: \"*\"\n\n EmrBpaFunction:\n Type: AWS::Lambda::Function\n Properties:\n Role: !GetAtt EmrBpaRole.Arn\n Runtime: python3.12\n Handler: index.handler\n Code:\n ZipFile: |\n import boto3, json, urllib.request\n def handler(event, context):\n try:\n boto3.client('emr').put_block_public_access_configuration(\n BlockPublicAccessConfiguration={\n 'BlockPublicSecurityGroupRules': True # CRITICAL: enables EMR Block Public Access\n }\n )\n status='SUCCESS'\n except Exception:\n status='FAILED'\n body=json.dumps({\n 'Status': status,\n 'PhysicalResourceId': 'EmrBPA', # respond to CFN\n 'StackId': event['StackId'],\n 'RequestId': event['RequestId'],\n 'LogicalResourceId': event['LogicalResourceId']\n }).encode()\n req=urllib.request.Request(event['ResponseURL'], data=body, method='PUT')\n req.add_header('content-type','')\n req.add_header('content-length',str(len(body)))\n urllib.request.urlopen(req)\n\n EmrBpa:\n Type: Custom::EmrBpa\n Properties:\n ServiceToken: !GetAtt EmrBpaFunction.Arn # Invokes Lambda to apply the setting\n```", + "Other": "1. In the AWS Console, go to Amazon EMR\n2. Select the target Region (top-right)\n3. In the left menu under \"EMR on EC2\", click \"Block public access\"\n4. Click \"Edit\" and choose \"Turn on\"\n5. Click \"Save\"", + "Terraform": "```hcl\n# Enable EMR Block Public Access (account/Region level)\nresource \"aws_emr_block_public_access_configuration\" \"example_resource_name\" {\n block_public_security_group_rules = true # CRITICAL: enables Block Public Access\n}\n```" }, "Recommendation": { - "Text": "Enable EMR Account Public Access Block.", - "Url": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html" + "Text": "Keep EMR **Block Public Access** enabled and minimize exceptions; allow only required ports and restrict sources.\n\nApply **least privilege** on security groups, place clusters in private subnets, and use bastion hosts or Session Manager. Combine with **VPC** controls and monitoring for **defense in depth**.", + "Url": "https://hub.prowler.com/check/emr_cluster_account_public_block_enabled" } }, "Categories": [ diff --git a/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.metadata.json b/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.metadata.json index 0cc84e87a6..a0dcf93999 100644 --- a/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.metadata.json +++ b/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.metadata.json @@ -2,28 +2,41 @@ "Provider": "aws", "CheckID": "emr_cluster_master_nodes_no_public_ip", "CheckTitle": "EMR Cluster without Public IP.", - "CheckType": [], + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "TTPs/Initial Access" + ], "ServiceName": "emr", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:emr:region:account-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "EMR Cluster without Public IP.", - "Risk": "EMR Cluster should not have Public IP.", - "RelatedUrl": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + "Description": "**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**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "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" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: Launch EMR in a private subnet (no public IPs)\nResources:\n :\n Type: AWS::EMR::Cluster\n Properties:\n Name: \n ReleaseLabel: emr-6.10.0\n ServiceRole: EMR_DefaultRole\n JobFlowRole: EMR_EC2_DefaultRole\n Instances:\n Ec2SubnetId: # CRITICAL: use a PRIVATE subnet to prevent public IPs\n InstanceGroups:\n - InstanceRole: MASTER\n InstanceType: m5.xlarge\n InstanceCount: 1\n - InstanceRole: CORE\n InstanceType: m5.xlarge\n InstanceCount: 1\n```", + "Other": "1. In the AWS Console, go to EMR > Clusters, select the non-compliant cluster (with Public IP) and choose Terminate.\n2. Click Create cluster.\n3. Under Networking, select your VPC and choose a private Subnet (no auto-assign public IPv4).\n4. Create the cluster. Its instances will launch without public IPs.", + "Terraform": "```hcl\n# Terraform: Launch EMR in a private subnet (no public IPs)\nresource \"aws_emr_cluster\" \"\" {\n name = \"\"\n release_label = \"emr-6.10.0\"\n master_instance_type = \"m5.xlarge\"\n core_instance_type = \"m5.xlarge\"\n\n service_role = \"EMR_DefaultRole\"\n ec2_attributes {\n instance_profile = \"EMR_EC2_DefaultRole\"\n subnet_id = \"\" # CRITICAL: private subnet ensures no public IPs\n }\n}\n```" }, "Recommendation": { - "Text": "Only make acceptable EMR clusters public.", - "Url": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html" + "Text": "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.", + "Url": "https://hub.prowler.com/check/emr_cluster_master_nodes_no_public_ip" } }, - "Categories": [], + "Categories": [ + "internet-exposed" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json b/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json index f5b9a6aad7..5e044bec0c 100644 --- a/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json +++ b/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json @@ -1,26 +1,33 @@ { "Provider": "aws", "CheckID": "emr_cluster_publicly_accesible", - "CheckTitle": "Publicly accessible EMR Cluster.", - "CheckType": [], + "CheckTitle": "EMR cluster is not publicly accessible", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "TTPs/Initial Access" + ], "ServiceName": "emr", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:emr:region:account-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "Publicly accessible EMR Cluster.", - "Risk": "EMR Clusters should not be publicly accessible.", - "RelatedUrl": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + "Description": "**Amazon EMR clusters** are assessed for **public network exposure** by examining master and core/task node security groups for inbound rules that allow any source (`0.0.0.0/0` or `::/0`).\n\nOnly active clusters are considered, and findings identify exposure via the specific security groups attached to the cluster nodes.", + "Risk": "**Open Internet ingress** to EMR nodes enables direct access to services and UIs, facilitating brute force, RCE, and data theft. Adversaries can pivot inside the VPC, alter jobs and outputs (**integrity**), exfiltrate datasets (**confidentiality**), or abuse compute for mining, degrading **availability**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "https://docs.prowler.com/checks/aws/networking-policies/ensure-that-amazon-emr-clusters-security-groups-are-not-open-to-the-world#terraform" + "NativeIaC": "```yaml\n# CloudFormation: Security Group without public ingress for EMR nodes\nResources:\n :\n Type: AWS::EC2::SecurityGroup\n Properties:\n GroupDescription: SG for EMR without public access\n VpcId: \n SecurityGroupIngress:\n - IpProtocol: tcp\n FromPort: 22\n ToPort: 22\n CidrIp: 10.0.0.0/8 # CRITICAL: restrict source; do not use 0.0.0.0/0 or ::/0 to avoid public access\n```", + "Other": "1. In AWS Console, go to EMR > Clusters and open the affected cluster\n2. In the cluster details, note the Security Groups for Master and Core/Task under Network and security\n3. Open the EC2 Console > Security Groups and select each noted group\n4. Edit Inbound rules and remove any rule with Source 0.0.0.0/0 or ::/0\n5. If access is required, re-add only from specific CIDR(s) you control, then Save", + "Terraform": "```hcl\n# Restrict EMR SG ingress to avoid 0.0.0.0/0 or ::/0\nresource \"aws_security_group_rule\" \"\" {\n type = \"ingress\"\n from_port = 22\n to_port = 22\n protocol = \"tcp\"\n security_group_id = \"\" # EMR master/core SG\n cidr_blocks = [\"10.0.0.0/8\"] # CRITICAL: restrict source; not 0.0.0.0/0 or ::/0\n}\n```" }, "Recommendation": { - "Text": "Only make acceptable EMR clusters public.", - "Url": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html" + "Text": "Apply **least privilege** and **defense in depth**:\n- Place clusters in private subnets; avoid public IPs\n- Deny `0.0.0.0/0` and `::/0` in node security groups; allow trusted CIDRs only\n- Keep EMR **Block Public Access** enabled with minimal exceptions\n- Use **bastion/SSM**, private connectivity, and logging for hardened access", + "Url": "https://hub.prowler.com/check/emr_cluster_publicly_accesible" } }, "Categories": [