Incompatibility between `az ad` and `--subscription`
- Dominant language
- Python
- Stars
- 4.6k
- Forks
- 3.5k
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 60
Description
## `az ad` and `--subscription`
`--subscription`(`_subscription`) is explicitly ignored for `az ad` commands as `az ad` commands are tenant-level. They have nothing to do with subscription.
https://github.com/Azure/azure-cli/blob/e8efb791ea2f0ba5e4f172b26f75725fd8aa8079/src/azure-cli/azure/cli/command_modules/role/_params.py#L26
However, since subscription ID is the primary key of Azure CLI's account, this gives `--subscription` another functionality - **temporarily switching login context**.
`send_raw_request` only switches subscription when the subscription ID is in an ARM URL:
https://github.com/Azure/azure-cli/blob/a5198b578b17de934e15b1c92e369e45323e9658/src/azure-cli-core/azure/cli/core/util.py#L977
As Graph API's URL is like `https://graph.microsoft.com/`, `send_raw_request` uses the current login context:
https://github.com/Azure/azure-cli/blob/a5198b578b17de934e15b1c92e369e45323e9658/src/azure-cli-core/azure/cli/core/util.py#L979
So `--subscription` doesn't take effect in:
```
az rest -u "https://graph.microsoft.com/v1.0/me" --subscription xxx
```
## Problem in doc
The in-tool help says `az ad` commands don't support `--subscription`
```
> az ad app show -h
...
Global Arguments
--debug : Increase logging verbosity to show all debug logs.
--help -h : Show this help message and exit.
--only-show-errors : Only show errors, suppressing warnings.
--output -o : Output format. Allowed values: json, jsonc, none, table, tsv, yaml, yamlc.
Default: json.
--query : JMESPath query string. See http://jmespath.org/ for more information and
examples.
--verbose : Increase logging verbosity. Use --debug for full debug logs.
```
but the online doc says they do, which is wrong (https://github.com/Azure/azure-cli/issues/21806, https://github.com/Azure/azure-cli/issues/23412): https://learn.microsoft.com/en-us/cli/azure/ad/app?view=azure-cli-latest#az-ad-app-show
## Problem in `az keyvault create`
Consider `sub1` is the current subscription+login context while `sub2` is another one, and `az keyvault create` is run with `--subscription sub2`
| subscription | sub1 (current) | sub2 |
| ------------ | -------------- | ------- |
| tenant | tenant1 | tenant2 |
| user | user1 | user2 |
### Creating keyvault
As `subscription` can be read from `cmd.cli_ctx.data.get['subscription_id']`:
https://github.com/Azure/azure-cli/blob/85d68d38793fa49afc40257123f3b9f17e891a3d/src/azure-cli/azure/cli/command_modules/keyvault/custom.py#L671
The keyvault is created with the identity of the `--subscription`-specified account - **(sub2, tenant2, user2)**.
### `_get_current_user_object_id`
When granting permissions for the keyvault, `az keyvault create` first calls `_get_current_user_object_id`
https://github.com/Azure/azure-cli/blob/85d68d38793fa49afc40257123f3b9f17e891a3d/src/azure-cli/azure/cli/command_modules/keyvault/custom.py#L736
`_get_current_user_object_id` internally calls the `/me` API on Microsoft Graph with the current account's identity, so **it grants permission to the identity of the current account** - **(N/A, tenant1, user1)**. This causes a mismatch.
### `_get_object_id`
If `_get_current_user_object_id` fails, it calls `_get_object_id`:
https://github.com/Azure/azure-cli/blob/85d68d38793fa49afc40257123f3b9f17e891a3d/src/azure-cli/azure/cli/command_modules/keyvault/custom.py#L738
which **resolves the identity of the `--subscription`-specified account, but in the current tenant** - **(N/A, tenant1, user2)**.
## Solution
The best solution is to implement a 3-layer structure (https://github.com/Azure/azure-cli/issues/15005).
## More information
- https://github.com/Azure/azure-cli/issues/24753#issuecomment-1768641064
- https://github.com/Azure/azure-cli/issues/22776
- https://github.com/Azure/azure-cli/issues/17607
- https://github.com/Azure/azure-cli/pull/15532
Contributor guide
Assessment
This issue has not been assessed yet.