Document Azure MI token discovery limits

This commit is contained in:
Carlos Polop
2026-05-05 17:45:43 +02:00
parent 406b2549aa
commit 2a4cc7c428
@@ -889,6 +889,8 @@ However, not every process will necessarily get the same practical result:
Therefore, if a request works from Run Command but fails from SSH, the usual explanation is a difference in OS user, environment, routing, proxy, firewall, or namespace, not a general Azure rule that only agent execution contexts can reach `168.63.129.16`.
In lab testing this distinction was visible: Linux/Windows VM Agent execution through Run Command or Custom Script extensions could reach GoalState on `168.63.129.16`, while a normal SSH session on another Linux VM could still reach IMDS but timed out when querying GoalState. Treat WireServer/GoalState as useful but environment-dependent; do not rely on it as the canonical way to enumerate managed identities.
### Managed Identity Access From Inside the VM
The reliable way to use a VM's managed identities is the **IMDS managed identity endpoint** at `169.254.169.254`, not the WireServer `ExtensionsConfig` XML. Scripts that only search `ExtensionsConfig` for `UserAssignedIdentity` nodes are not reliable because:
@@ -897,7 +899,19 @@ The reliable way to use a VM's managed identities is the **IMDS managed identity
- They miss **system-assigned managed identities**.
- They only find user-assigned identities if the current GoalState/extension data happens to expose the expected XML shape.
Microsoft's documented security model is that **all code running on the VM can request tokens for the managed identities available on that VM**. If several user-assigned identities exist, request a specific one with `client_id`, `object_id`, or `msi_res_id`.
Microsoft's documented security model is that **all code running on the VM can request tokens for the managed identities available on that VM**. This was confirmed from:
- Linux SSH as a regular VM user.
- Linux Run Command through the VM Agent.
- Linux Custom Script extension through the VM Agent.
- Windows Custom Script extension as `NT AUTHORITY\SYSTEM`.
In all of those contexts, IMDS could mint tokens for Management, Microsoft Graph/Entra ID, Key Vault, and Storage when the requested identity was available to the VM.
There are two different problems that are easy to mix up:
- **Getting a token for a known identity:** If the identity is assigned to the VM, IMDS can issue tokens for different audiences such as `https://management.azure.com/`, `https://graph.microsoft.com/`, `https://vault.azure.net`, and `https://storage.azure.com/`. If several user-assigned identities exist, request a specific one with `client_id`, `object_id`, or `msi_res_id`.
- **Discovering every attached identity from inside the VM:** IMDS does not provide a simple "list all identities" endpoint. A practical method is to get a default Management token, read the VM resource through ARM, and inspect the `identity` property. This only works if that managed identity has permissions such as `Microsoft.Compute/virtualMachines/read` on the VM. If ARM returns `403`, the token can still be valid and useful, but it cannot enumerate the VM's full identity list.
The following examples first request a token. Then they try to read the VM resource from Azure Resource Manager and print its `identity` property. The second step only works if the managed identity has permissions such as `Microsoft.Compute/virtualMachines/read` on the VM.