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
| Method | Required Azure role(s) | Typical use-case |
|---|---|---|
| Kubeconfig | Standard Kubernetes RBAC only | Rapid trials when you already possess a kubeconfig. No insight into backing Azure resources. |
| Service Principal (SP) | Azure Kubernetes Service RBAC Reader | Production-grade installations. Same SP can also cover Azure resource discovery. |
| Managed Identity (MI) | Azure Kubernetes Service RBAC Reader | Secret-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 uniqueIf 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:
| Value | Behaviour |
|---|---|
none | Skip indexing — no SLX/SLI/run-books produced |
basic | Retrieve metadata; generate lightweight SLX/SLI |
detailed | Retrieve all objects; generate run-books |
Precedence
| Priority | Location | Reason |
|---|---|---|
| 1 | Namespace annotation config.runwhen.com/lod | Allows application teams to opt-in / opt-out without changing workspace YAML. |
| 2 | Cluster block defaultNamespaceLOD | Lets platform owners set a safe default per cluster. |
| 3 | Workspace defaultLOD | Workspace-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
| Key | Scope | When it is useful |
|---|---|---|
subscriptions | List of subscription objects | Limit discovery to specific subscriptions. |
resourceGroupLevelOfDetails | Per resource group | Apply LoD on an RG basis (e.g. detailed for production RGs). |
includeTags | Any ARM resource | Discover only resources that carry specific tags. |
excludeTags | Any ARM resource | Omit 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 overriddenIf the subscriptions: array is absent, CloudQuery will automatically enumerate all subscriptions that the provided credential can access.
Authentication
| Method | Advantages | Limitations |
|---|---|---|
| Service Principal (SP) | Portable; usable outside Azure; fine-grained role assignment | Secret rotation required |
| Managed Identity (MI) | No secrets; automatic rotation | Only 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 ReaderInline credentials (quick start)
cloudConfig: azure: subscriptionId: "<SUB_ID>" tenantId: "<TENANT_ID>" clientId: "<APP_ID>" clientSecret: "<PASSWORD>"Storing credentials in a secret (recommended)
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-localcloudConfig: azure: spSecretName: azure-spManaged 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)
- Namespace annotation
config.runwhen.com/lod resourceGroupLevelOfDetailsinside a subscription object- Workspace-level
resourceGroupLevelOfDetails - Subscription-level
defaultLOD - 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: detailedExecution flow:
- The SP azure-sp authenticates.
- CloudQuery is instructed to crawl sub-demo only.
- Within that subscription, rg-aks-demo is crawled at detailed LoD; all other RGs default to basic.
- The Kubernetes indexer connects solely to
aks-demoand indexes every namespace at detailed LoD.
CloudQuery Plugin Version Matrix
| CloudQuery source | Tested version |
|---|---|
| Azure | v9.4.0 |
Refer to the CloudQuery documentation for the full list of available tables.