Skip to content

Microsoft Azure

This guide explains how RunWhen Local discovers Azure resources and AKS clusters via CloudQuery, and how you can control discovery scope, level-of-detail (LoD), and authentication. Each configuration option is followed by a brief rationale so you can decide whether it is relevant to your environment.


AKS Cluster Discovery

Discovery methods

MethodRequired Azure role(s)Typical use-case
KubeconfigStandard Kubernetes RBAC onlyRapid trials when you already possess a kubeconfig. No insight into backing Azure resources.
Service Principal (SP)Azure Kubernetes Service RBAC ReaderProduction-grade installations. Same SP can also cover Azure resource discovery.
Managed Identity (MI)Azure Kubernetes Service RBAC ReaderSecret-less deployments on AKS or VMSS.

Why list each cluster? The Azure ARM API does not expose the Kubernetes API server endpoint. Specifying server: guarantees that the Kubernetes indexer can connect without additional look-ups.

cloudConfig:
azure:
aksClusters:
clusters:
- name: aks-cluster-1 # Appears in generated SLX titles
server: https://aks-cluster-1.hcp.eastus.azmk8s.io:443
resource_group: rg-aks-1 # Links namespaces → resource group
subscriptionId: sub-aks-1 # Optional when RG name is unique

If the subscriptions: array is omitted or empty, RunWhen Local passes an empty list to CloudQuery. CloudQuery then enumerates every subscription the credential can access. Include the array only when you must restrict discovery.


Namespace Level-of-Detail (LoD)

LoD determines how much data is retrieved from the Kubernetes or Azure API:

ValueBehaviour
noneSkip indexing — no SLX/SLI/run-books produced
basicRetrieve metadata; generate lightweight SLX/SLI
detailedRetrieve all objects; generate run-books

Precedence

PriorityLocationReason
1Namespace annotation config.runwhen.com/lodAllows application teams to opt-in / opt-out without changing workspace YAML.
2Cluster block defaultNamespaceLODLets platform owners set a safe default per cluster.
3Workspace defaultLODWorkspace-wide fallback.
aksClusters:
clusters:
- name: aks-cluster-1
defaultNamespaceLOD: basic # Applies to all namespaces unless…

Azure Resource Discovery (CloudQuery)

CloudQuery inventories Azure resources so that RunWhen Local can match them to automation tasks (CodeBundles). Scoping the crawl lowers API consumption and speeds up runs.

Scoping options

KeyScopeWhen it is useful
subscriptionsList of subscription objectsLimit discovery to specific subscriptions.
resourceGroupLevelOfDetailsPer resource groupApply LoD on an RG basis (e.g. detailed for production RGs).
includeTagsAny ARM resourceDiscover only resources that carry specific tags.
excludeTagsAny ARM resourceOmit resources that carry specific tags.
cloudConfig:
azure:
subscriptions:
- subscriptionId: sub-prod
defaultLOD: basic
resourceGroupLevelOfDetails:
rg-payments: detailed
- subscriptionId: sub-dev
defaultLOD: none # Ignore unless specifically overridden

If the subscriptions: array is absent, CloudQuery will automatically enumerate all subscriptions that the provided credential can access.


Authentication

MethodAdvantagesLimitations
Service Principal (SP)Portable; usable outside Azure; fine-grained role assignmentSecret rotation required
Managed Identity (MI)No secrets; automatic rotationOnly available on Azure resources

Creating a Service Principal

az account set --subscription <SUB_ID>
az ad sp create-for-rbac \
--name runwhen-local-sp \
--scopes /subscriptions/<SUB_ID> \
--role Reader

Inline credentials (quick start)

cloudConfig:
azure:
subscriptionId: "<SUB_ID>"
tenantId: "<TENANT_ID>"
clientId: "<APP_ID>"
clientSecret: "<PASSWORD>"
kubectl create secret generic azure-sp \
--from-literal=clientId=<APP_ID> \
--from-literal=clientSecret=<PASSWORD> \
--from-literal=subscriptionId=<SUB_ID> \
--from-literal=tenantId=<TENANT_ID> \
-n runwhen-local
cloudConfig:
azure:
spSecretName: azure-sp

Managed Identity

When neither inline credentials nor spSecretName are provided, the indexer falls back to Managed Identity. Ensure that the identity (either the pod’s user-assigned MI or the node pool’s system-assigned MI) has at least the Reader role on every subscription or resource group you wish to discover.


LoD Resolution Order (Quick Reference)

  1. Namespace annotation config.runwhen.com/lod
  2. resourceGroupLevelOfDetails inside a subscription object
  3. Workspace-level resourceGroupLevelOfDetails
  4. Subscription-level defaultLOD
  5. Workspace defaultLOD

End-to-End Example

workspaceName: demo
defaultLOD: none # Workspace fallback
cloudConfig:
azure:
# Authentication via secret
spSecretName: azure-sp
# Cluster list
aksClusters:
clusters:
- name: aks-demo
server: https://aks-demo.hcp.eastus.azmk8s.io:443
resource_group: rg-aks-demo
subscriptionId: sub-demo
defaultNamespaceLOD: detailed
# Subscription-scoped discovery
subscriptions:
- subscriptionId: sub-demo
defaultLOD: basic
resourceGroupLevelOfDetails:
rg-aks-demo: detailed

Execution flow:

  1. The SP azure-sp authenticates.
  2. CloudQuery is instructed to crawl sub-demo only.
  3. Within that subscription, rg-aks-demo is crawled at detailed LoD; all other RGs default to basic.
  4. The Kubernetes indexer connects solely to aks-demo and indexes every namespace at detailed LoD.

CloudQuery Plugin Version Matrix

CloudQuery sourceTested version
Azurev9.4.0

Refer to the CloudQuery documentation for the full list of available tables.