---
title: EMR without VPC
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: >-
  Docs > Datadog Security > Code Security > Infrastructure as Code (IaC)
  Security > IaC Security Rules > EMR without VPC
---

> For the complete documentation index, see [llms.txt](https://docs.datadoghq.com/llms.txt).

# EMR without VPC

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com, us2.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md). ({% placeholder "user-datadog-site-name" /%}).
{% /alert %}

{% /callout %}

## Metadata{% #metadata %}

**Id:** `terraform-aws-emr-without-vpc` 

**Provider:** AWS

**Platform:** Terraform

**Severity:** Low

**Category:** Networking and Firewall

#### Learn More{% #learn-more %}

- [Provider Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/emr_cluster#subnet_id)

### Description{% #description %}

This check ensures that Amazon Elastic MapReduce (EMR) clusters are deployed within a Virtual Private Cloud (VPC) by specifying a `subnet_id` in the Terraform resource. Launching EMR clusters without associating them to a VPC, as shown by omitting the `subnet_id` attribute in the `aws_emr_cluster` resource, exposes the cluster to public networks and increases the risk of unauthorized access or data compromise. By deploying EMR clusters in a VPC, network access control can be properly enforced through security groups and network ACLs, limiting exposure to only trusted sources. Failure to launch EMR clusters inside a VPC can lead to serious security vulnerabilities, including unauthorized data access, data exfiltration, or service disruption.

## Compliant Code Examples{% #compliant-code-examples %}

```terraform
# This configuration's subnet_id is a cross-resource reference to a
# not-yet-created subnet (aws_subnet.main). On the HCL path the parser
# keeps the unresolved "${aws_subnet.main.id}" as a literal string, so
# common_lib.valid_key finds the key present. On the plan-JSON path
# (negative2.json, a genuine create plan for this exact configuration) the
# value itself is unresolved and absent from planned_values, but the rule
# now also checks _dd_tfplan_meta.configuration_expressions to confirm
# subnet_id is configured-but-unresolved rather than missing.
resource "aws_emr_cluster" "negative1" {
  name          = "emr-test-arn"
  release_label = "emr-4.6.0"
  subnet_id = aws_subnet.main.id
}
```

## Non-Compliant Code Examples{% #non-compliant-code-examples %}

```terraform
resource "aws_emr_cluster" "positive1" {
  name          = "emr-test-arn"
  release_label = "emr-4.6.0"
}
```

```terraform
# Guard-rail case: ec2_attributes is populated (instance_profile is set),
# but subnet_id/subnet_ids is genuinely never configured -- not a
# cross-resource reference left unresolved. Must still be flagged: the
# rule's configuration_expressions check only suppresses the finding when
# subnet_id/subnet_ids is actually present as a key the user wrote.
resource "aws_iam_role" "emr_service_role" {
  name = "emr-service-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action    = "sts:AssumeRole"
      Effect    = "Allow"
      Principal = { Service = "elasticmapreduce.amazonaws.com" }
    }]
  })
}

resource "aws_emr_cluster" "positive2" {
  name          = "emr-test-no-subnet"
  release_label = "emr-4.6.0"
  service_role  = aws_iam_role.emr_service_role.arn
  ec2_attributes {
    instance_profile = "test-profile"
  }
}
```
