gcp-dataproc-public-master-ui

Dataproc cluster master VM with a public IP and permissive dataproc-* firewall rules exposes the YARN UI / Spark History Server to the internet.

derived gcp emits ExposedToInternet

match (record)

{ "field": "config.gceClusterConfig.internalIpOnly", "resource_type": "google.dataproc.Cluster" }

where

config.gceClusterConfig.internalIpOnly == false (default: cluster VMs have public IPs) AND a compute.Firewall rule in the dataproc-* set allows ingress from 0.0.0.0/0 or ::/0 on relevant ports (YARN: 8088, Spark History Server: 18080, or other UI ports) AND Component Gateway is NOT enabled (when enabled, web UIs are proxied behind auth)

emit

source typeAnalyticsService
target typeAnonymousIdentity
source<Dataproc cluster>
target<AnonymousIdentity>
conditionsnetwork_reachability
state logicACTIVE when both conditions hold: (a) the cluster has public IPs (internalIpOnly == false) AND (b) firewall rules allow internet ingress on the YARN or Spark UI ports AND (c) the Component Gateway is not enabled (Component Gateway proxies UIs behind IAP/auth). CONDITIONAL(network_reachability) when firewalls exist but are ambiguous. BLOCKED when internalIpOnly == true or when no firewall rule allows internet ingress.

Narrative

{cluster.name}'s master VM has a public IP (internalIpOnly == false) and the Dataproc firewall rules allow internet ingress on the YARN/Spark UI ports; the cluster management UI is reachable from the public internet without authentication.

Raw rule rules/derived/gcp/dataproc.yaml

id: gcp-dataproc-public-master-ui
emits: ExposedToInternet
description: Dataproc cluster master VM with a public IP and permissive dataproc-* firewall rules exposes
  the YARN UI / Spark History Server to the internet.
match_record:
  resource_type: google.dataproc.Cluster
  field: config.gceClusterConfig.internalIpOnly
where:
- 'config.gceClusterConfig.internalIpOnly == false (default: cluster VMs have public IPs)'
- 'AND a compute.Firewall rule in the dataproc-* set allows ingress from 0.0.0.0/0 or ::/0 on relevant
  ports (YARN: 8088, Spark History Server: 18080, or other UI ports)'
- AND Component Gateway is NOT enabled (when enabled, web UIs are proxied behind auth)
emit:
  source_type: AnalyticsService
  target_type: AnonymousIdentity
  source: <Dataproc cluster>
  target: <AnonymousIdentity>
  permissions: []
  conditions:
  - network_reachability
  state_logic: 'ACTIVE when both conditions hold: (a) the cluster has public IPs (internalIpOnly == false)
    AND (b) firewall rules allow internet ingress on the YARN or Spark UI ports AND (c) the Component
    Gateway is not enabled (Component Gateway proxies UIs behind IAP/auth). CONDITIONAL(network_reachability)
    when firewalls exist but are ambiguous. BLOCKED when internalIpOnly == true or when no firewall rule
    allows internet ingress.'
  false_positive_note: "Do NOT emit for clusters with internalIpOnly == true (private clusters: no public\
    \ IPs, master UI accessible only via Cloud IAP tunnel or internal VPC). Do NOT emit for Component\
    \ Gateway-enabled clusters (the gateway enforces authentication via Cloud IAP; the underlying ports\
    \ are not directly reachable from the internet). Verify the dataproc-* firewall rules \u2014 Dataproc\
    \ creates rules named dataproc-CLUSTER_NAME-* scoped to the cluster's network tag; confirm internet\
    \ ingress (0.0.0.0/0 source) is actually present on the relevant port. A VPC-SC perimeter does not\
    \ protect against direct VM port access."
  narrative: '{cluster.name}''s master VM has a public IP (internalIpOnly == false) and the Dataproc firewall
    rules allow internet ingress on the YARN/Spark UI ports; the cluster management UI is reachable from
    the public internet without authentication.'
move · open · esc close