gcp-cloudscheduler-attach-sa-via-update

Update the serviceAccountEmail field of an HTTP job's oidcToken/oauthToken to swap the execution identity (jobs.update + actAs on new SA).

derived gcp emits CanAttachIdentity

match

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

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

where

node_type(?job) == Scheduler

emit

source typeIdentity
target typeMessaging
source<principal>
target<Cloud Scheduler job (Scheduler node)>
permissionscloudscheduler.jobs.update iam.serviceAccounts.actAs
conditionsiam_permission role_compatibility service_state
state logicACTIVE when the principal holds cloudscheduler.jobs.update on the job AND actAs on the new SA AND the job is ENABLED (or PAUSED and can be run via jobs.run). CONDITIONAL(service_state) when the job is PAUSED. POTENTIAL(role_compatibility) when actAs on the new SA is unknown/unresolved. BLOCKED by IAM deny or org policy on either permission.

Narrative

{principal.name} can change {job.name}'s OIDC/OAuth2 service account to {sa.name} (cloudscheduler.jobs.update + iam.serviceAccounts.actAs) - attaching {sa.name} as the execution identity for all future scheduled invocations.

Raw rule rules/derived/gcp/cloudscheduler.yaml

id: gcp-cloudscheduler-attach-sa-via-update
emits: CanAttachIdentity
description: Update the serviceAccountEmail field of an HTTP job's oidcToken/oauthToken to swap the execution
  identity (jobs.update + actAs on new SA).
match:
- - principal: null
  - CanModifyConfiguration
  - job: null
- - principal: null
  - CanPassIdentity
  - sa: null
where:
- node_type(?job) == Scheduler
emit:
  source_type: Identity
  target_type: Messaging
  source: <principal>
  target: <Cloud Scheduler job (Scheduler node)>
  permissions:
  - cloudscheduler.jobs.update
  - iam.serviceAccounts.actAs
  conditions:
  - iam_permission
  - role_compatibility
  - service_state
  state_logic: ACTIVE when the principal holds cloudscheduler.jobs.update on the job AND actAs on the
    new SA AND the job is ENABLED (or PAUSED and can be run via jobs.run). CONDITIONAL(service_state)
    when the job is PAUSED. POTENTIAL(role_compatibility) when actAs on the new SA is unknown/unresolved.
    BLOCKED by IAM deny or org policy on either permission.
  derived_from:
  - ?principal CanModifyConfiguration ?job (gcp-cloudscheduler-update-config)
  - ?principal CanPassIdentity ?sa (gcp-cloudscheduler-passidentity-actas)
  false_positive_note: Records the attach capability itself; downstream CanExecuteAs follows from gcp-cloudscheduler-execute-as-via-sa-swap
    once the job fires. Requires actAs on the NEW SA, not the existing SA. The attach is ACTIVE when actAs
    is confirmed; downstream CanExecuteAs is still gated on a run path (scheduled invocation or cloudscheduler.jobs.run).
  narrative: "{principal.name} can change {job.name}'s OIDC/OAuth2 service account to {sa.name} (cloudscheduler.jobs.update\
    \ + iam.serviceAccounts.actAs) \u2014 attaching {sa.name} as the execution identity for all future\
    \ scheduled invocations."
move · open · esc close