Azure / azure-cli

Azure Command-Line Interface
MIT License
3.97k stars 2.95k forks source link

Incompatibility between `az ad` and `--subscription` #29837

Open jiasli opened 1 week ago

jiasli commented 1 week ago

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/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

yonzhan commented 1 week ago

Thank you for opening this issue, we will look into it.