azure-rest-api-specs
azure-rest-api-specs copied to clipboard
Returns none when code is authenticated with the service principal
Describe the bug
We are trying to run code using the azure python SDK and are getting different results when we are authenticated with a service principal instead of a user. When the below code is run with regular username pass authentication, the last line of the code, sub[‘domain’], will return the list of domains in the tenant. When the same code is run when authenticated as a service principal, sub[‘domain’] returns ‘None’ even though there are domains values that exist for the tenant. This makes me think there is some role or api permission that a service principal might not be granted by default.
To Reproduce
Steps to reproduce the behavior: The code snippet was enclosed below. The below code works with username, password authentication, whereas it is returning none when authenticating with service principal.
Expected behavior
domains[sub['tenant_id']][0] should return the list of domains in the tenant
Screenshots
import functools import logging from typing import Any, Dict, List from azure import identity # type: ignore from azure.mgmt import resource, storage, web from azure.storage import blob from azure.identity import ClientSecretCredential from azure.mgmt.compute import ComputeManagementClient
creds = identity.AzureCliCredential() client = resource.SubscriptionClient(credential=creds)
subs = { s.subscription_id: s.as_dict() for s in client.subscriptions.list()}
update subscription info with tenant domains domains = {t.tenant_id: t.domains for t in client.tenants.list()}
for sub in subs.values(): sub['domain'] = domains[sub['tenant_id']][0]
Additional context
Q1) Is the service principal being used is in the same tenant, with the same permissions, as the user account that was used to successfully list domains? I believe it is yes, please confirm this. A) Yes
Q2) Is the service principal authentication being attempted with the AzureCliCredential, as shown in your example code? A) Yes
Hi @pmatte
According to my investigation, the domains field data you want, the swagger definition is a read-only parameter. https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/resources/azure-mgmt-resource/azure/mgmt/resource/subscriptions/v2021_01_01/models/_models_py3.py#L847
The python SDK is generated by swagger. It receives the data returned by the service and displays it to the user after processing. Therefore, the SDK will not delete or modify a certain parameter data.
swagger definition: https://github.com/Azure/azure-rest-api-specs/blob/main/specification/resources/resource-manager/Microsoft.Resources/stable/2021-01-01/subscriptions.json#L592-L600
https://github.com/Azure/azure-rest-api-specs/blob/main/specification/resources/resource-manager/Microsoft.Resources/stable/2021-01-01/subscriptions.json#L165
I think this issue a service problem
@msyyc any update on this? customer made a follow-up..
Hi @pmatte I am not that familiar with different authentication and here is my inference: when you create a service principle, you need create it under specific tenant and specific suscription while user name and password not. It proves that service principal has smaller action scope so that's why client with service principal can't list all the domains while user name and password can.
Thank you for the explanation, so is it not possible to list the domains using service principle?
is there a work around / other alternative exist to achieve this using service principal?
Do you think it is good to involve someone who can help in different authentication methods and/or for providing work around? customer was waiting on this from long time.
Hello @msyyc any update on this? your help on this is highly appreciated.
Hi @pmatte according to the swagger definition, tenants_list
"Gets the tenants for your account", so I think calling the api needs access across different tenant. But service principal only has access to one tenant, so it doesn't work well. Now the question becomes: which kind of authentication has such high access like username and password authentication? I will raise e-mail to add more experts.
Thank you @msyyc for sending email to the group. I see the below update from the team.
====
User-based credentials (https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity#authenticate-users) seem to work fine (as do AzureCliCredential and PowerShellCredential).
Whatever processing is done at the https://management.azure.com/tenants?api-version=2021-01-01
endpoint seems to restrict the results to just the fields “id”, “tenantId”, and “tenantCategory” when an access token from a service principal is used (fields like “domains”, “countryCode”, and “displayName” are absent in the response). And I haven't had any luck getting it to work by tinkering with various roles and permissions.
Perhaps someone on the Azure AD service team or someone more familiar with Azure AD might have more input.
====
may you loop the Azure AD team for more help? I appreciate your help on this
I just got bit by this. When using a managed identity with the latest API version only the id, tenantId and tenantCategory are returned by https://management.azure.com/tenants?api-version=2022-12-01
For my use case I wanted to get tenant name