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).
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 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. |
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."