azure-devops-kv-variable-group-can-read-secret
A Key Vault-linked variable group exposes Azure Key Vault secrets to pipeline runs; the pipeline's service-connection identity must hold Key Vault Secrets User RBAC.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'pipeline': None}
HasPolicy {'variable_group': None}
{'variable_group': None} ContainsSecret {'kv_secret': None}
where
node_type(?pipeline) ==
BuildWorker
node_type(?variable_group) == Secret
?variable_group.linkType == AzureKeyVault
node_type(?kv_secret) == Secret # Key Vault secret node
emit
| source type | BuildWorker |
|---|---|
| target type | Secret |
| source | ?pipeline |
| target | ?kv_secret |
| permissions | Key Vault Secrets User RBAC on the Key Vault (for the service connection's identity) Use (variable group) in DevOps Library namespace |
| conditions | resource_policy iam_permission |
| state logic | ACTIVE when the pipeline's service-connection identity has Key Vault Secrets User (or legacy Get on the KV access policy) on the vault and the variable group is referenced by the pipeline. CONDITIONAL(resource_policy) when the RBAC or access policy grant is absent or uncertain — the pipeline will fail to load the group at queue time. |
Narrative
{pipeline.name}'s Key Vault-linked variable group {variable_group.name} fetches secrets from Azure Key Vault at queue time; the pipeline service-connection identity reads {kv_secret.name} and injects it into the job environment.
Raw rule rules/derived/azure/devops.yaml
id: azure-devops-kv-variable-group-can-read-secret
emits: CanReadSecret
description: A Key Vault-linked variable group exposes Azure Key Vault secrets to pipeline runs; the pipeline's
service-connection identity must hold Key Vault Secrets User RBAC.
applies_to:
- azure
match:
- - pipeline: null
- HasPolicy
- variable_group: null
- - variable_group: null
- ContainsSecret
- kv_secret: null
where:
- node_type(?pipeline) == BuildWorker
- node_type(?variable_group) == Secret
- ?variable_group.linkType == AzureKeyVault
- 'node_type(?kv_secret) == Secret # Key Vault secret node'
emit:
source_type: BuildWorker
target_type: Secret
source: ?pipeline
target: ?kv_secret
permissions:
- Key Vault Secrets User RBAC on the Key Vault (for the service connection's identity)
- Use (variable group) in DevOps Library namespace
conditions:
- resource_policy
- iam_permission
state_logic: "ACTIVE when the pipeline's service-connection identity has Key Vault Secrets User (or\
\ legacy Get on the KV access policy) on the vault and the variable group is referenced by the pipeline.\
\ CONDITIONAL(resource_policy) when the RBAC or access policy grant is absent or uncertain \u2014\
\ the pipeline will fail to load the group at queue time."
confidence: 0.85
derived_from:
- azure-devops-variable-group-can-read-secret
false_positive_note: "The Key Vault secret read happens at pipeline queue time (before the run starts),\
\ not at job step execution time. If the SC identity lacks RBAC, the pipeline fails to start with\
\ an error \u2014 not a silent miss. Verify the service-connection SP has Key Vault Secrets User at\
\ the vault or secret scope. A Key Vault access policy model (not RBAC) requires an explicit 'Get'\
\ policy grant for the SP."
narrative: '{pipeline.name}''s Key Vault-linked variable group {variable_group.name} fetches secrets
from Azure Key Vault at queue time; the pipeline service-connection identity reads {kv_secret.name}
and injects it into the job environment.'