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

derived gcp emits CanExecuteAs

match

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

{'principal': None} CanModifyCode {'deploy_worker': None} {'deploy_worker': None} ExecutesAs {'deploy_sa': None}

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

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

{'principal': None} CanTrigger {'deploy_worker': None}

emit

source typeIdentity
target typeServiceAccount
source?principal
target?deploy_sa
permissionsclouddeploy.rollouts.create iam.serviceAccounts.actAs
conditionsiam_permission
state logicACTIVE 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.'
move · open · esc close