gcp-dataflow-create-workload-as

Create a new Dataflow job whose workers run as a passable SA (dataflow.jobs.create + iam.serviceAccounts.actAs).

derived gcp emits CanCreateWorkloadAs

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

?principal CanPassIdentity ?sa

where

?principal has effective dataflow.jobs.create on the project node_type(?sa) in [ServiceAccount, MachineIdentity]

emit

source typeIdentity
target typeIdentity
source<principal>
target<worker service account>
permissionsdataflow.jobs.create iam.serviceAccounts.actAs
conditionsiam_permission role_compatibility
state logicACTIVE when both dataflow.jobs.create and iam.serviceAccounts.actAs on ?sa are confirmed in the effective grant. The job runs immediately on creation (no invoke step); there is no trigger_exists gate. POTENTIAL(iam_permission) if actAs on ?sa is not confirmed. BLOCKED if a deny policy applies to either permission. Downstream CanExecuteAs is derived by can-execute-as execute-as-via-new-workload (CITED, not re-derived here).

Narrative

{principal.name} can create a Dataflow job (dataflow.jobs.create) bound to worker service account {sa.name} (iam.serviceAccounts.actAs), submitting attacker- controlled pipeline transforms that execute as {sa.name}.

Raw rule rules/derived/gcp/dataflow.yaml

id: gcp-dataflow-create-workload-as
emits: CanCreateWorkloadAs
description: Create a new Dataflow job whose workers run as a passable SA (dataflow.jobs.create + iam.serviceAccounts.actAs).
match:
- - ?principal
  - CanPassIdentity
  - ?sa
where:
- ?principal has effective dataflow.jobs.create on the project
- node_type(?sa) in [ServiceAccount, MachineIdentity]
emit:
  source_type: Identity
  target_type: Identity
  source: <principal>
  target: <worker service account>
  permissions:
  - dataflow.jobs.create
  - iam.serviceAccounts.actAs
  conditions:
  - iam_permission
  - role_compatibility
  state_logic: ACTIVE when both dataflow.jobs.create and iam.serviceAccounts.actAs on ?sa are confirmed
    in the effective grant. The job runs immediately on creation (no invoke step); there is no trigger_exists
    gate. POTENTIAL(iam_permission) if actAs on ?sa is not confirmed. BLOCKED if a deny policy applies
    to either permission. Downstream CanExecuteAs is derived by can-execute-as execute-as-via-new-workload
    (CITED, not re-derived here).
  confidence: 0.95
  derived_from:
  - <CanPassIdentity edge_id for ?principal -> ?sa>
  - <dataflow.jobs.create effective permission>
  false_positive_note: "Job creation requires both permissions to be in the effective grant. An attacker\
    \ with only dataflow.jobs.create but without actAs on a usable SA cannot start a job (API returns\
    \ a permission error). actAs is per-SA. The escalation consequence (CanExecuteAs) is produced by can-execute-as\
    \ / can-control off this CanCreateWorkloadAs \u2014 cite those linchpins, do not re-derive."
  narrative: '{principal.name} can create a Dataflow job (dataflow.jobs.create) bound to worker service
    account {sa.name} (iam.serviceAccounts.actAs), submitting attacker- controlled pipeline transforms
    that execute as {sa.name}.'
move · open · esc close