azure-rest-api-specs icon indicating copy to clipboard operation
azure-rest-api-specs copied to clipboard

Returns none when code is authenticated with the service principal

Open pmatte opened this issue 2 years ago • 9 comments

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

pmatte avatar Dec 15 '22 16:12 pmatte

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

Wzb123456789 avatar Dec 16 '22 07:12 Wzb123456789

@msyyc any update on this? customer made a follow-up..

pmatte avatar Dec 20 '22 17:12 pmatte

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.

msyyc avatar Dec 22 '22 02:12 msyyc

Thank you for the explanation, so is it not possible to list the domains using service principle?

pmatte avatar Dec 22 '22 18:12 pmatte

is there a work around / other alternative exist to achieve this using service principal?

pmatte avatar Dec 22 '22 18:12 pmatte

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.

pmatte avatar Dec 22 '22 20:12 pmatte

Hello @msyyc any update on this? your help on this is highly appreciated.

pmatte avatar Dec 29 '22 17:12 pmatte

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.

msyyc avatar Dec 30 '22 02:12 msyyc

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

pmatte avatar Jan 03 '23 17:01 pmatte

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

vandre avatar Mar 24 '24 15:03 vandre