gcp-appengine-execute-as-actas
Deploy a version with a custom, more-privileged runtime SA via actAs.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
?sa is role-compatible as an App Engine runtime SA (same project)
?sa.privilege_level >= ?principal.privilege_level
the ?sa bound by
CanPassIdentity is the SAME ?sa attached to the deployed version; the deploy path can set version.serviceAccount = ?sa
?principal's iam.serviceAccounts.actAs grant is scoped to THIS ?sa (per-SA actAs), not merely to the appspot SA
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | <principal> |
| target | <chosen service account> |
| permissions | iam.serviceAccounts.actAs appengine.versions.create |
| conditions | role_compatibility iam_permission |
| state logic | CONDITIONAL(iam_permission) until per-SA actAs on ?sa is confirmed AND the deploy path can set version.serviceAccount=?sa; ACTIVE only once both hold. |
Narrative
{principal.name} can deploy an App Engine version bound to {sa.name} (per-SA actAs + appengine.versions.create) and execute code as that SA, provided actAs is scoped to {sa.name}.
Raw rule rules/derived/gcp/appengine.yaml
id: gcp-appengine-execute-as-actas
emits: CanExecuteAs
description: Deploy a version with a custom, more-privileged runtime SA via actAs.
match:
- - principal: null
- CanPassIdentity
- sa: null
- - principal: null
- CanModifyCode
- app: null
where:
- ?sa is role-compatible as an App Engine runtime SA (same project)
- ?sa.privilege_level >= ?principal.privilege_level
- the ?sa bound by CanPassIdentity is the SAME ?sa attached to the deployed version; the deploy path can
set version.serviceAccount = ?sa
- ?principal's iam.serviceAccounts.actAs grant is scoped to THIS ?sa (per-SA actAs), not merely to the
appspot SA
emit:
source_type: Identity
target_type: Identity
source: <principal>
target: <chosen service account>
permissions:
- iam.serviceAccounts.actAs
- appengine.versions.create
conditions:
- role_compatibility
- iam_permission
state_logic: 'CONDITIONAL(iam_permission) until per-SA actAs on ?sa is confirmed AND the deploy path
can set version.serviceAccount=?sa; ACTIVE only once both hold.
'
derived_from:
- <CanPassIdentity edge_id>
- <CanModifyCode edge_id>
false_positive_note: 'iam.serviceAccounts.actAs is per-SA. A principal able to actAs only the appspot
SA cannot attach an arbitrary stronger ?sa to a version. Confirm the actAs grant covers exactly the
?sa bound by CanPassIdentity and that the deploy actually sets version.serviceAccount=?sa before asserting
CanExecuteAs.
'
narrative: '{principal.name} can deploy an App Engine version bound to {sa.name} (per-SA actAs + appengine.versions.create)
and execute code as that SA, provided actAs is scoped to {sa.name}.'