gcp-deploy-rollout-promote-executes-as
Promote a Cloud Deploy release (rollouts.create) + actAs(deploy SA) → deploy Cloud Build worker executes as the deploy SA, which has runtime control over the target (GKE/Cloud Run).
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
CanModifyCode {'deploy_worker': None}
{'deploy_worker': None} ExecutesAs {'deploy_sa': None}
where
BuildWorker
?deploy_worker is a Cloud Deploy deploy-phase job run
?principal holds clouddeploy.rollouts.create AND CanPassIdentity(?principal, ?deploy_sa)
optional
Present → upgrade the emitted state; absent → downgrade (not a hard requirement).
CanTrigger {'deploy_worker': None}
emit
| source type | Identity |
|---|---|
| target type | ServiceAccount |
| source | ?principal |
| target | ?deploy_sa |
| permissions | clouddeploy.rollouts.create iam.serviceAccounts.actAs |
| conditions | iam_permission |
| state logic | ACTIVE when CanModifyCode (rollout creation controls what Skaffold executes) and ExecutesAs (deploy SA) are both ACTIVE and no approval gate is present. CONDITIONAL(approval_required) when target.requireApproval == true AND ?principal does not hold clouddeploy.rollouts.approve on the same target. ACTIVE when ?principal holds BOTH rollouts.create AND rollouts.approve on the same target (approval gate provides no separation). CONDITIONAL(time_window) when a deploy policy restricts rollouts.create for the target and ?principal lacks deployPolicies.override. BLOCKED when deny policy blocks rollouts.create or iam.serviceAccounts.actAs. |
Narrative
{principal.name} can promote a Cloud Deploy release to target {target.name} (clouddeploy.rollouts.create + iam.serviceAccounts.actAs on {deploy_sa.name}). The deploy Cloud Build worker executes as {deploy_sa.name} running skaffold apply and any pre/post-deploy hooks. {deploy_sa.name}'s GCP roles (e.g., container.developer on the GKE target or run.developer on Cloud Run) determine the post-escalation blast radius. Cite cicd-chains cicd-modify-buildspec-executes-as.
Raw rule rules/derived/gcp/clouddeploy.yaml
id: gcp-deploy-rollout-promote-executes-as
emits: CanExecuteAs
description: "Promote a Cloud Deploy release (rollouts.create) + actAs(deploy SA) \u2192 deploy Cloud\
\ Build worker executes as the deploy SA, which has runtime control over the target (GKE/Cloud Run)."
applies_to:
- gcp
match:
- - principal: null
- CanModifyCode
- deploy_worker: null
- - deploy_worker: null
- ExecutesAs
- deploy_sa: null
where:
- node_type(?deploy_worker) == BuildWorker
- ?deploy_worker is a Cloud Deploy deploy-phase job run
- ?principal holds clouddeploy.rollouts.create AND CanPassIdentity(?principal, ?deploy_sa)
optional:
- - principal: null
- CanTrigger
- deploy_worker: null
emit:
source_type: Identity
target_type: ServiceAccount
source: ?principal
target: ?deploy_sa
permissions:
- clouddeploy.rollouts.create
- iam.serviceAccounts.actAs
conditions:
- iam_permission
state_logic: ACTIVE when CanModifyCode (rollout creation controls what Skaffold executes) and ExecutesAs
(deploy SA) are both ACTIVE and no approval gate is present. CONDITIONAL(approval_required) when target.requireApproval
== true AND ?principal does not hold clouddeploy.rollouts.approve on the same target. ACTIVE when
?principal holds BOTH rollouts.create AND rollouts.approve on the same target (approval gate provides
no separation). CONDITIONAL(time_window) when a deploy policy restricts rollouts.create for the target
and ?principal lacks deployPolicies.override. BLOCKED when deny policy blocks rollouts.create or iam.serviceAccounts.actAs.
confidence: 0.93
derived_from:
- ?principal CanModifyCode ?deploy_worker (gcp-deploy-rollout-create-modifies-code)
- ?deploy_worker ExecutesAs ?deploy_sa (gcp-deploy-executes-as)
- cicd-chains cicd-modify-buildspec-executes-as
false_positive_note: "actAs on the DEPLOY SA (not render SA) is the gate. Confirm the target's executionConfigs.serviceAccount\
\ resolves to ?deploy_sa. The deploy SA's blast radius depends on its bound GCP roles: with container.developer\
\ on the GKE cluster it can create/modify pods; with run.developer it can update Cloud Run services.\
\ If the deploy SA is the default compute SA (roles/editor), treat as high-value. Approval gate: CONDITIONAL\
\ unless the same principal can approve (roles segregation failed). Deploy policy time-window: CONDITIONAL(time_window)\
\ \u2014 still reachable outside the window or with policyOverrider."
narrative: '{principal.name} can promote a Cloud Deploy release to target {target.name} (clouddeploy.rollouts.create
+ iam.serviceAccounts.actAs on {deploy_sa.name}). The deploy Cloud Build worker executes as {deploy_sa.name}
running skaffold apply and any pre/post-deploy hooks. {deploy_sa.name}''s GCP roles (e.g., container.developer
on the GKE target or run.developer on Cloud Run) determine the post-escalation blast radius. Cite
cicd-chains cicd-modify-buildspec-executes-as.'