gcp-gcf-execute-as-via-config

Update the runtime SA of an existing function to a more-privileged actAs-able SA.

derived gcp emits CanExecuteAs

match

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

{'principal': None} CanModifyConfiguration {'function': None} {'principal': None} CanPassIdentity {'sa': None}

where

node_type(?function) == ServerlessFunction ?principal has iam.serviceAccounts.actAs on ?sa ?sa.privilege_level >= ?principal.privilege_level

optional

Present → upgrade the emitted state; absent → downgrade (not a hard requirement).

{'principal': None} CanInvoke {'function': None}

emit

source typeIdentity
target typeIdentity
source<principal>
target<chosen service account>
permissionscloudfunctions.functions.update iam.serviceAccounts.actAs
state logicACTIVE if matched(optional[0]) or trigger_exists(?function) else CONDITIONAL(trigger_exists)

Narrative

{principal.name} can repoint {function.name} to {sa.name} (cloudfunctions.functions.update + iam.serviceAccounts.actAs) and run it, executing as {sa.name}.

Raw rule rules/derived/gcp/gcf.yaml

id: gcp-gcf-execute-as-via-config
emits: CanExecuteAs
description: Update the runtime SA of an existing function to a more-privileged actAs-able SA.
match:
- - principal: null
  - CanModifyConfiguration
  - function: null
- - principal: null
  - CanPassIdentity
  - sa: null
optional:
- - principal: null
  - CanInvoke
  - function: null
where:
- node_type(?function) == ServerlessFunction
- ?principal has iam.serviceAccounts.actAs on ?sa
- ?sa.privilege_level >= ?principal.privilege_level
emit:
  source_type: Identity
  target_type: Identity
  source: <principal>
  target: <chosen service account>
  permissions:
  - cloudfunctions.functions.update
  - iam.serviceAccounts.actAs
  state_logic: ACTIVE if matched(optional[0]) or trigger_exists(?function) else CONDITIONAL(trigger_exists)
  conditions_from:
  - function: null
  - sa: null
  false_positive_note: Requires actAs on the target SA (per-SA). Combined with code control (attacker
    sets source too), so runtime SA choice is attacker-controlled.
  narrative: '{principal.name} can repoint {function.name} to {sa.name} (cloudfunctions.functions.update
    + iam.serviceAccounts.actAs) and run it, executing as {sa.name}.'
move · open · esc close