cicd-pipeline-orchestrates-stages

Triggering a pipeline reaches each downstream stage runner it orchestrates; propagate CanTrigger to those runners.

derived any cloud emits CanTrigger

match

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

{'principal': None} CanTrigger {'pipeline': None} {'pipeline': None} CanTrigger {'stage_runner': None}

where

node_type(?pipeline) in [BuildWorker, ContainerService, ServerlessFunction, VirtualMachine] node_type(?stage_runner) in [BuildWorker, ContainerTask, ContainerService, ServerlessFunction, VirtualMachine, KubernetesWorkload] ?stage_runner != ?pipeline

emit

source typeIdentity
target typeCompute
source?principal
target?stage_runner
conditionsstage_reachable
state logicinherit from the two CanTrigger contributors: ACTIVE when the principal's trigger of the pipeline is ACTIVE and the pipeline genuinely invokes ?stage_runner unconditionally (not gated by a manual approval / stage condition the attacker cannot satisfy); CONDITIONAL(stage_reachable) when the stage is gated by an approval or a condition that must first be met; BLOCKED if either contributing trigger is BLOCKED. Never stronger than the weaker of the two CanTrigger edges.

Narrative

{principal.name} can trigger the pipeline {pipeline.name}, which orchestrates {stage_runner.name}; the pipeline start therefore reaches {stage_runner.name}, propagating the ability to run it (and thus its execution identity).

Raw rule rules/derived/cicd-chains.yaml

id: cicd-pipeline-orchestrates-stages
emits: CanTrigger
description: Triggering a pipeline reaches each downstream stage runner it orchestrates; propagate CanTrigger
  to those runners.
applies_to:
- '*'
match:
- - principal: null
  - CanTrigger
  - pipeline: null
- - pipeline: null
  - CanTrigger
  - stage_runner: null
where:
- node_type(?pipeline) in [BuildWorker, ContainerService, ServerlessFunction, VirtualMachine]
- node_type(?stage_runner) in [BuildWorker, ContainerTask, ContainerService, ServerlessFunction, VirtualMachine,
  KubernetesWorkload]
- ?stage_runner != ?pipeline
emit:
  source_type: Identity
  target_type: Compute
  source: ?principal
  target: ?stage_runner
  permissions: []
  conditions:
  - stage_reachable
  state_logic: 'inherit from the two CanTrigger contributors: ACTIVE when the principal''s trigger of
    the pipeline is ACTIVE and the pipeline genuinely invokes ?stage_runner unconditionally (not gated
    by a manual approval / stage condition the attacker cannot satisfy); CONDITIONAL(stage_reachable)
    when the stage is gated by an approval or a condition that must first be met; BLOCKED if either contributing
    trigger is BLOCKED. Never stronger than the weaker of the two CanTrigger edges.'
  confidence: min(contributing_confidences)
  derived_from:
  - ?principal CanTrigger ?pipeline
  - ?pipeline CanTrigger ?stage_runner
  false_positive_note: "Only propagate for stages the pipeline actually reaches from the triggered entry\
    \ point. A stage behind a MANUAL APPROVAL gate, a protected-environment wait, or a stage condition\
    \ (branch filter, `when: manual`) the attacker cannot satisfy => CONDITIONAL(stage_reachable), not\
    \ ACTIVE. This is orchestration propagation only; it does NOT itself grant an identity \u2014 it feeds\
    \ rules 1/2 on each ?stage_runner's ExecutesAs. Do not emit CanExecuteAs here."
  narrative: '{principal.name} can trigger the pipeline {pipeline.name}, which orchestrates {stage_runner.name};
    the pipeline start therefore reaches {stage_runner.name}, propagating the ability to run it (and thus
    its execution identity).'
move · open · esc close