azure-auto-runbook-write

Overwrite or create a runbook (PowerShell/Python) in an Automation Account; content executes as the account MI on next job.

derived azure emits CanModifyCode

match (effective permission)

{ "any_of": [ { "action": "Microsoft.Automation/automationAccounts/runbooks/write", "scope_type": "resource|resourceGroup|subscription" }, { "action": "Microsoft.Automation/automationAccounts/runbooks/draft/write", "scope_type": "resource|resourceGroup|subscription" } ] }

where

principal effectively holds the runbook write action at the automationAccount scope

emit

source typeIdentity
target typeGenericCompute
source<principal>
target<runbook (BuildWorker) in the automationAccount>
permissionsMicrosoft.Automation/automationAccounts/runbooks/write Microsoft.Automation/automationAccounts/runbooks/draft/write
conditionsservice_state trigger_exists
state logicACTIVE when principal also holds automationAccounts/jobs/write (confirmed run path) AND the account is not suspended. CONDITIONAL(trigger_exists) when runbook-write is confirmed but jobs/write is absent — code is planted but requires an existing schedule, webhook, or a different principal to start a job. CONDITIONAL(service_state) if the account is suspended. Publishing a draft requires automationAccounts/runbooks/publish/action in addition to draft/write (full runbooks/write includes publish implicitly). BLOCKED if a deny assignment covers runbooks/write at the scope.

Narrative

{principal.name} can overwrite or create runbook code in Automation Account {target.name} (automationAccounts/runbooks/write); the content is arbitrary PowerShell/Python that executes as the account's managed identity on the next job. cicd-chains cicd-modify-buildspec-executes-as collapses this with ExecutesAs to CanExecuteAs(managed identity) when a run path exists.

Raw rule rules/derived/azure/automation.yaml

id: azure-auto-runbook-write
emits: CanModifyCode
description: Overwrite or create a runbook (PowerShell/Python) in an Automation Account; content executes
  as the account MI on next job.
match_effective_permission:
  any_of:
  - action: Microsoft.Automation/automationAccounts/runbooks/write
    scope_type: resource|resourceGroup|subscription
  - action: Microsoft.Automation/automationAccounts/runbooks/draft/write
    scope_type: resource|resourceGroup|subscription
where:
- principal effectively holds the runbook write action at the automationAccount scope
emit:
  source_type: Identity
  target_type: GenericCompute
  source: <principal>
  target: <runbook (BuildWorker) in the automationAccount>
  permissions:
  - Microsoft.Automation/automationAccounts/runbooks/write
  - Microsoft.Automation/automationAccounts/runbooks/draft/write
  conditions:
  - service_state
  - trigger_exists
  state_logic: "ACTIVE when principal also holds automationAccounts/jobs/write (confirmed run path) AND\
    \ the account is not suspended. CONDITIONAL(trigger_exists) when runbook-write is confirmed but jobs/write\
    \ is absent \u2014 code is planted but requires an existing schedule, webhook, or a different principal\
    \ to start a job. CONDITIONAL(service_state) if the account is suspended. Publishing a draft requires\
    \ automationAccounts/runbooks/publish/action in addition to draft/write (full runbooks/write includes\
    \ publish implicitly). BLOCKED if a deny assignment covers runbooks/write at the scope."
  confidence: 0.97
  derived_from:
  - 'effective permission: Microsoft.Automation/automationAccounts/runbooks/write OR runbooks/draft/write'
  - 'cicd-chains.yaml: cicd-modify-buildspec-executes-as'
  false_positive_note: runbooks/write alone does NOT start a job; publishing (runbooks/publish/action)
    and job creation (jobs/write) are separate operations. Draft/write requires publish/action as an additional
    step before the draft becomes the active runbook version. Without jobs/write or an existing trigger/schedule
    that fires the modified runbook, this is CONDITIONAL(trigger_exists), not ACTIVE. Automation Operator
    holds jobs/write but NOT runbooks/write; Automation Job Operator holds jobs/write but NOT runbooks/write.
    The full code-execution chain requires both runbooks/write AND jobs/write (or an existing automated
    trigger); confirm both before marking ACTIVE.
  narrative: '{principal.name} can overwrite or create runbook code in Automation Account {target.name}
    (automationAccounts/runbooks/write); the content is arbitrary PowerShell/Python that executes as the
    account''s managed identity on the next job. cicd-chains cicd-modify-buildspec-executes-as collapses
    this with ExecutesAs to CanExecuteAs(managed identity) when a run path exists.'
move · open · esc close