azure-cli · diff

git:20260910.c429a71 to git:20261023.a6d1dc5

124 added, 63 removed. Audit A to A.

---
name: azure-cli
- description: "Use the Azure CLI to manage subscriptions, resource groups, AKS, App Service, Key Vault, and role assignments."
+ description: "Operate Azure CLI (az) with subscription-scoped ARM, managed identities, AKS/App Service/Key Vault workflows, and RBAC patterns agents mis-scope."
category: devops
risk: safe
source: self
source_type: self
date_added: "2026-08-26"
- tags: ["azure", "az", "azure-cli", "aks", "rbac", "arm", "cli"]
+ tags: ["azure", "az", "azure-cli", "arm", "rbac", "managed-identity", "aks", "key-vault", "oidc"]
tools: ["claude", "cursor", "gemini", "codex"]
---
- # Azure CLI (az) AI Skill Guide
+ # Azure CLI (az) AI Skill Guide (Claude)
- ## Overview
+ ## Overview & Engine Architecture
- The Azure CLI (`az`) talks to Azure Resource Manager (ARM). Work is scoped by **subscription** and usually grouped under a **resource group**. Agents should always resolve tenant, subscription, and default location before mutating resources - Azure errors often look like "NotFound" when the real issue is the wrong subscription context.
+ The **Azure CLI** (`az`) calls **Azure Resource Manager (ARM)**. Work is scoped by **tenant → subscription → resource group → resource**. Auth is interactive login, service principal, managed identity, or **federated OIDC** (GitHub Actions). Agents always resolve **tenant, subscription, and location** before mutating—Azure often returns `NotFound` / “subscription doesn’t exist” when the real issue is **wrong context or missing RBAC**, not a missing resource name.
```
- az login / identity
- |
- v
- +-------------------+ +--------------------+
- | Subscription | --> | Resource groups |
- | Tenant / RBAC | | AKS / App Service |
- +-------------------+ | Storage / Key Vault|
- +--------------------+
+ ┌─────────────────────────────────────────────────────────────┐
+ │ Azure CLI → ARM path │
+ │ │
+ │ Identity │
+ │ ├── az login (user / device code) │
+ │ ├── SP / federated credential (OIDC CI) │
+ │ └── Managed identity (compute / Automation) │
+ │ │
+ │ Scope │
+ │ ├── Tenant → Subscription (az account set) │
+ │ ├── Resource group + location defaults │
+ │ └── RBAC assignments (role + scope + principal) │
+ │ │
+ │ Workloads │
+ │ └── AKS · App Service · ACR · Storage · Key Vault · … │
+ └─────────────────────────────────────────────────────────────┘
```
- ## When to use
+ ---
- - Creating resource groups, App Services, AKS clusters, or storage accounts
- - Wiring managed identities and role assignments
- - Fetching AKS kubeconfig or App Service logs
- - Scripting ARM-friendly deployments without full Bicep/Terraform yet
+ ## When to use / when not to
- ## Operational directives
+ **Use when**
- 1. Start every session with `az account show` and `az account list -o table`.
- 2. Prefer explicit `--resource-group` / `--subscription` on write commands.
- 3. Use managed identities over client secrets when the platform supports it.
- 4. Prefer `--output json` for scripting; use JMESPath `--query` instead of fragile greps.
- 5. Never print Key Vault secret values into chat or CI logs unless the user explicitly needs them redacted.
+ - Creating/managing resource groups, App Services, AKS, ACR, storage, and role assignments.
+ - Fetching AKS kubeconfig, App Service logs, or Key Vault metadata (not dumping secrets to chat).
+ - Debugging “wrong subscription” / RBAC timing after permission grants.
- ## Concrete examples
+ **Do not use when**
- ### Account and defaults
+ - Shared multi-env infra should be declarative → `@terraform` / `@pulumi` (Bicep OK for Azure-native).
+ - Day-2 cluster workloads after credentials → `@kubernetes`.
+ - Someone asks to paste client secrets or Key Vault secret **values** into chat/logs → refuse; use managed identity / Key Vault references / `@vault`.
+ ---
+
+ ## Operational Capabilities & Agent Directives
+
+ 1. **Context first**: `az account show` and `az account list -o table` before every write session.
+ 2. **Pass `--subscription` / `--resource-group` explicitly** on mutates; do not trust ambient defaults in scripts.
+ 3. **Prefer managed identity / federated credentials** over client secrets for apps and CI.
+ 4. **RBAC creates**: use `--assignee-object-id` + `--assignee-principal-type` to skip Entra lookups that fail for SPs (`Insufficient privileges`).
+ 5. **Output**: `--output json` + JMESPath `--query` for automation; never scrape human tables.
+ 6. **Never print** Key Vault secret values, SP passwords, or federated credential secrets into chat/CI logs.
+ 7. After new RBAC grants, **refresh account cache** (`az account clear` + `az login`, or new shell)—ARM/RBAC can lag (~minutes).
+
+ ---
+
+ ## Production Example: subscription gate + App Service + MI RBAC
+
```bash
+ # Login + subscription gate (use device code in remote shells)
az login
- az account set --subscription "Prod Engineering"
- az configure --defaults group=rg-prod-api location=eastus
+ # az login --use-device-code
+ az account list -o table
+ az account set --subscription "00000000-0000-0000-0000-000000000000"
az account show --query "{name:name, id:id, tenant:tenantId}" -o json
- ```
- ### Resource group + App Service
+ az configure --defaults group=rg-prod-api location=eastus
- ```bash
az group create -n rg-prod-api -l eastus
az appservice plan create -g rg-prod-api -n plan-api --sku P1v3 --is-linux
az webapp create -g rg-prod-api -p plan-api -n app-api-prod --runtime "NODE:20-lts"
- az webapp config appsettings set -g rg-prod-api -n app-api-prod \
- --settings WEBSITE_NODE_DEFAULT_VERSION=20
- ```
- ### AKS credentials
+ # User-assigned identity + ACR pull (no client secret)
+ az identity create -g rg-prod-api -n id-api
+ PRINCIPAL=$(az identity show -g rg-prod-api -n id-api --query principalId -o tsv)
+ az webapp identity assign -g rg-prod-api -n app-api-prod --identities \
+ "$(az identity show -g rg-prod-api -n id-api --query id -o tsv)"
- ```bash
+ az role assignment create \
+ --assignee-object-id "$PRINCIPAL" \
+ --assignee-principal-type ServicePrincipal \
+ --role "AcrPull" \
+ --scope "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-prod-api/providers/Microsoft.ContainerRegistry/registries/acrprod"
+
+ # AKS kubeconfig → hand off to @kubernetes
az aks get-credentials -g rg-prod-api -n aks-prod --overwrite-existing
az aks show -g rg-prod-api -n aks-prod --query "powerState.code" -o tsv
```
- ### RBAC with managed identity
+ CI (federated identity / OIDC — prefer over SP password):
```bash
- PRINCIPAL=$(az identity show -g rg-prod-api -n id-api --query principalId -o tsv)
- az role assignment create \
- --assignee-object-id "$PRINCIPAL" \
- --assignee-principal-type ServicePrincipal \
- --role "AcrPull" \
- --scope /subscriptions/<sub>/resourceGroups/rg-prod-api/providers/Microsoft.ContainerRegistry/registries/acrprod
+ # After azure/login action with client-id + tenant-id + subscription-id
+ az account show
+ az group list --query "[].name" -o tsv
```
- ## Extension and query tips
+ What-if for large ARM/Bicep (prefer over blind `az deployment group create`):
- | Goal | Pattern |
- | :--- | :--- |
- | Filter list | `az webapp list -g rg --query "[].{name:name, state:state}" -o table` |
- | Wait for ready | `az webapp show ... --query state -o tsv` in a retry loop |
- | Install extension | `az extension add --name <name>` then pin in docs |
- | What-if deploy | Prefer Bicep/ARM what-if for large templates |
+ ```bash
+ az deployment group what-if -g rg-prod-api -f main.bicep
+ ```
- ## Best practices
+ ---
- 1. Name resources with a consistent scheme (`rg-<env>-<app>`, `aks-<env>`).
- 2. Lock production resource groups against accidental delete when policy allows.
- 3. Prefer Key Vault references for App Service secrets over plain app settings.
- 4. Document required CLI version and extensions in the repo README.
+ ## Technical Troubleshooting Matrix
+ | Signature | Likely cause | Fix path |
+ | :--- | :--- | :--- |
+ | `The subscription of '…' doesn't exist in cloud 'AzureCloud'` | No RBAC on sub; stale account cache; wrong tenant | Grant ≥ Reader on sub; `az account clear && az login`; verify tenant |
+ | Resource `NotFound` but Portal shows it | Wrong subscription/RG context | `az account show`; pass `--subscription` / `-g` |
+ | `Insufficient privileges` on `role assignment create` | SP cannot read Entra directory | Use `--assignee-object-id`; or grant Directory Readers carefully |
+ | RBAC “done” but still 401 | ARM cache / propagation delay | Wait up to ~10 min; new shell; retry |
+ | MI / Automation: `SubscriptionId cannot be null` | Identity has **zero** role assignments | Assign Reader/Contributor (least privilege) at needed scope |
+ | Extension command missing | Extension not installed / version skew | `az extension add --name <n>`; pin versions in README/CI |
+ | Interactive login fails in CI | No browser / device flow | Use OIDC federated credential or MI—not user login |
+
+ ---
+
+ ## Best Practices
+
+ 1. Naming: `rg-<env>-<app>`, `aks-<env>`, `id-<app>`; tag with `env`, `owner`, `service`.
+ 2. Lock production RGs (`CanNotDelete`) when policy allows.
+ 3. App settings: Key Vault references over plaintext secrets; pair with `@vault` when org-standard.
+ 4. Document required `az` version + extensions in the repo README.
+ 5. Graduate shared infra from imperative `az` scripts to `@terraform` / `@pulumi` / Bicep.
+
+ ---
+
## Limitations
- - `az` imperative scripts drift; graduate shared infra to Bicep/Terraform/Pulumi.
- - Cross-tenant and Azure AD permission prompts may need interactive login (hard in headless CI).
- - Some preview features require extension versions that break older pipelines.
+ - Imperative `az` scripts drift; IaC owns long-lived topology.
+ - Cross-tenant and Entra consent flows may require a human.
+ - Preview extensions can break pinned pipelines—treat as deliberate upgrades.
+ - Stop and ask if subscription ID, tenant, or delete approval is missing.
- ## Related skills
+ ---
- - `kubernetes` - AKS workload operations after `get-credentials`
- - `vault` - compare with Key Vault secret workflows
- - `docker` - images for ACR / App Service containers
- - `gcloud-cli` - analogous multi-cloud CLI patterns
+ ## Related Skills
+
+ - `@kubernetes` — AKS workload ops after `get-credentials`
+ - `@terraform` / `@pulumi` — declarative Azure infrastructure
+ - `@vault` — org secret workflows vs Key Vault
+ - `@docker` — images for ACR / App Service containers
+ - `@aws-cli` / `@gcloud-cli` — analogous multi-cloud CLI patterns
+ - `@github-actions` — OIDC login to Azure
+
+ ---
+
+ ## Agent Operational Directive
+
+ > **MANDATORY**: Resolve tenant/subscription with `az account show` before mutating. Prefer managed identity and federated OIDC over client secrets. Use `--assignee-object-id` for RBAC from SPs. Never print Key Vault secret values or SP passwords. Refresh login cache after new grants. If subscription or blast radius is unclear, stop and ask.
+
+ ---
+
+ ## Source anchors (research)
+
+ - [Manage Azure subscriptions with the CLI](https://learn.microsoft.com/en-us/cli/azure/manage-azure-subscriptions-azure-cli)
+ - [Troubleshoot Azure RBAC](https://learn.microsoft.com/en-us/azure/role-based-access-control/troubleshooting)
+ - [Subscription doesn’t exist (SP needs RBAC)](https://github.com/Azure/azure-cli/issues/28329)
+ - [Managed identity subscription null](https://learn.microsoft.com/en-us/azure/automation/troubleshoot/managed-identity)