Retrieving ID/email from an Azure credential - python

We are working on our dev environment around Azure ML and Python.
As part of this, we are using azure-identity (DefaultAzureCredential) for authorization. This is going to either match a CLI credential or a "VSCode-logged-in" credential.
We would programatically like to know which user (identified by email address or ID) is currently present. How would we do this?
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
token = credential.get_token("https://management.azure.com/", scopes=["user.read"])
current_user_id = ???
Update 1
As suggested by #xyan I can deconstruct the token to retrieve information about user accounts:
import json
import base64
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
token = credential.get_token("https://management.azure.com/", scopes=["user.read"])
base64_meta_data = token.token.split(".")[1].encode("utf-8") + b'=='
json_bytes = base64.decodebytes(base64_meta_data)
json_string = json_bytes.decode("utf-8")
json_dict = json.loads(json_string)
current_user_id = json_dict["upn"]
print(f"{current_user_id=}")
This works for user accounts, but not for service principals. In that case, it fails retrieving the token:
DefaultAzureCredential failed to retrieve a token from the included credentials.
Attempted credentials:
EnvironmentCredential: Authentication failed: ClientApplication.acquire_token_silent_with_error() got multiple values for argument 'scopes'
What would be a proper scope that could retrieve upn/oid for various types of clients?

You can try parse the token to get the client id, tenant id information.
Sample code:
https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/identity/azure-identity/azure/identity/_internal/decorators.py#L38.
(I work in the Azure SDK team in Microsoft)

Related

Microsoft Graph API Python SDK "Insufficient privileges to complete the operation."

i'm trying to get user data from AAD using Microsoft Graph API Python SDK.
App registration that i have in company tenant has the followiing API permissions:
I'm using the following piece of code to get user's details from AAD:
from azure.common.credentials import ServicePrincipalCredentials
from azure.graphrbac import GraphRbacManagementClient
credentials = ServicePrincipalCredentials(
client_id="appClientId",
secret="appClientSecret",
resource="https://graph.windows.net",
tenant = 'companyTenant'
)
tenant_id = 'companyTenantId'
graphrbac_client = GraphRbacManagementClient(
credentials,
tenant_id
)
user = graphrbac_client.users.get("myUserObjectId")
And get "azure.graphrbac.models.graph_error_py3.GraphErrorException: Insufficient privileges to complete the operation."
I'm using Python 3.10.5 and my app service should be able to get data of any user from AAD.
What am i doing wrong here?
Looks like the resource are trying to reach out is incorrect , https://graph.windows.net is used when you want to connect to AAD graph , please check the docs for more info - https://learn.microsoft.com/en-us/previous-versions/azure/ad/graph/howto/azure-ad-graph-api-operations-overview.
Could you please try by using the resource = graph.microsoft.com .
graph.microsoft.com is correct endpoint for graph .
please see the doc - https://learn.microsoft.com/en-us/graph/use-the-api
Hope this helps
Thanks
I tried to reproduce the same in my environment and got below results:
I created one Azure AD application and granted API permissions like below:
When I ran the same code as you, I got same error as below:
from azure.common.credentials import ServicePrincipalCredentials
from azure.graphrbac import GraphRbacManagementClient
credentials = ServicePrincipalCredentials(
client_id="appClientId",
secret="appClientSecret",
resource="https://graph.windows.net",
tenant = 'companyTenantId'
)
tenant_id = 'companyTenantId'
graphrbac_client = GraphRbacManagementClient(
credentials,
tenant_id
)
user = graphrbac_client.users.get("myUserObjectId")
Response:
I agree with Vicky kumar that graph.windows.net is deprecated and you need to change/migrate to https://graph.microsoft.com.
But the libraries that you are using won't support this resource that results error as below:
Your current library azure.graphrbac only supports resource as graph.windows.net that needs AAD graph permissions:
To resolve the error, you can make use of below code by installing urllib3 library beforehand:
import urllib3
uri = "https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token"
payload= {
'Content-Type': 'application/x-www-form-urlencoded',
'Host': 'login.microsoftonline.com',
'client_id': '3de439c4-570d-4534-bxxb-e3axxx5d', #Your AppID
'scope': 'https://graph.microsoft.com/.default',
'client_secret': 'T2Y8Q~wYQxxxxxxxxxxOODUtFxajo', #Your client secret
'grant_type': 'client_credentials'
 }
http = urllib3.PoolManager()
response = http.request('POST', uri, payload)
my_dict = eval(response.data)
token = f"{my_dict['token_type']} {my_dict['access_token']}"
#print(token)
uri5 = 'https://graph.microsoft.com/v1.0/users/myUserID'
payload5 = {'Authorization':token,'Host':'graph.microsoft.com','ConsistencyLevel':'eventual'}
https = urllib3.PoolManager()
response5 = http.request('GET', uri5, headers=payload5)
print(response5.data)
When I ran the above code, I got the user details successfully as below:
Okay, so it came out that the issue was that i was using wrong SDK, the one that i've used was working with the AAD graph but i need Microsoft.Graph (if the permission that i've granted to the app registration would be of the AAD Graph type - then it would work, but since AAD Graph cannot be assigned anymore to the app registration since it is deprecated i've assigned Microsoft.Graph permission).
So the fix was to use another SDK from MS (that is currenty in preview) and it worked for me, here is the code:
from azure.identity import ClientSecretCredential
from msgraph.core import GraphClient
credential = ClientSecretCredential(tenant_id='tenantId',client_secret='appRegClientId',client_id='appRegClientSecret')
client = GraphClient(credential=credential)
result = client.get('/users') # gets all users
# result = client.get('/users/userObjectId') # gets a certain user by it's objectId
# result = client.get('/users/email') # gets a certain user by it's email address
print(result.json())

How do I authenticate to Azure using a Service Principal and the Python SDK?

I am currently attempting to authenticate to Azure using the azure-mgmt-support MicrosoftSupport client and am receiving the following error:
AdalError: Get Token request returned http error: 400 and server response: {"error":"unauthorized_client","error_description":"AADSTS700016: Application with identifier 'xxx' was not found in the directory 'management.core.windows.net'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant.
I have double checked and am definitely using the correct client_id and tenant_id. What am I missing here? My code below:
from azure.mgmt.support import MicrosoftSupport
from msrestazure.azure_active_directory import ServicePrincipalCredentials
sub_id = 'xxx'
sp_creds = ServicePrincipalCredentials(client_id='xxx', secret='xxx')
SupportClient = MicrosoftSupport(sp_creds, sub_id)
After a short walk and another look at the documentation, and I spotted my error - I was missing the tenant_id from the ServicePrincipalCredentials object. It's not obvious from the SDK specification or error message that this is what was missing as the only required variables are client_id and secret, however when I looked at this example in the documentation I realised it was missing (pasting code below for posterity, in case docs page changes).
import os
from azure.mgmt.resource import SubscriptionClient
from azure.common.credentials import ServicePrincipalCredentials
# Retrieve the IDs and secret to use with ServicePrincipalCredentials
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
tenant_id = os.environ["AZURE_TENANT_ID"]
client_id = os.environ["AZURE_CLIENT_ID"]
client_secret = os.environ["AZURE_CLIENT_SECRET"]
credential = ServicePrincipalCredentials(tenant=tenant_id, client_id=client_id, secret=client_secret)
subscription_client = SubscriptionClient(credential)
subscription = next(subscription_client.subscriptions.list())
print(subscription.subscription_id)

Get Access Token for client profile Azure in Python

I'm looking for a way to get access token from a client profile when working with Azure using Python.
from azure.common.client_factory import get_client_from_cli_profile
from azure.mgmt.compute import ComputeManagementClient
client = get_client_from_cli_profile(ComputeManagementClient)
From the code I get the client profile context but how can I get access token from it?
I could find the method to get the access token from a client profile, to get the access token, you could use the adal, use which method depends on your requirement.
For example, I get the access token of a service principal with the client credentials to access the Azure Management REST API, the given resource is https://management.azure.com/.
import adal
# Tenant ID for your Azure Subscription
TENANT_ID = 'xxxxxxx'
# Your Service Principal App ID
CLIENT = 'xxxxxxx'
# Your Service Principal Password
KEY = 'xxxxxxx'
subscription_id = 'xxxxxxx'
authority_url = 'https://login.microsoftonline.com/'+TENANT_ID
context = adal.AuthenticationContext(authority_url)
token = context.acquire_token_with_client_credentials(
resource='https://management.azure.com/',
client_id=CLIENT,
client_secret=KEY
)
print(token["accessToken"])

Get Azure Security Center alerts via python SDK

I want to list azure security center alerts using the python SDK.
I found this package:
https://pypi.org/project/azure-mgmt-security/
It must be included in the microsoft documentation:
https://learn.microsoft.com/en-gb/python/azure/?view=azure-python
https://github.com/Azure/azure-sdk-for-python
but I can not find any reference or example.
Does anyone know where I can find this information?
Best regards.
I can just give a rough reference.
After install the package azure-mgmt-security, you should use List method in the package, source code is here.
Here is the the doc on how to authentication.
Here is doc on how to get tenantId / client_id / key.
Here is my code:
from azure.mgmt.security import SecurityCenter
from azure.common.credentials import ServicePrincipalCredentials
subscription_id = "xxxx"
# Tenant ID for your Azure subscription
TENANT_ID = '<Your tenant ID>'
# Your service principal App ID
CLIENT = '<Your service principal ID>'
# Your service principal password
KEY = '<Your service principal password>'
credentials = ServicePrincipalCredentials(
client_id = CLIENT,
secret = KEY,
tenant = TENANT_ID
)
client = SecurityCenter(credentials=credentials,subscription_id=subscription_id,asc_location="centralus")
client.alerts.list()
Also, you can use List Alerts api with a http request in python.
As of today, February 2021, Microsoft again changed the way credentials are instantiated. Here is the current one:
from azure.identity import DefaultAzureCredential
# Acquire a credential object for the app identity. When running in the cloud,
# DefaultAzureCredential uses the app's managed identity (MSI) or user-assigned service principal.
# When run locally, DefaultAzureCredential relies on environment variables named
# AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID.
credential = DefaultAzureCredential()
And it also changed the SecurityCenter signature, the credentials parameter was renamed to credential without the "s".
Full documentation here.

Azure ADAL authentication using python

I am trying to authenticate azure using ADAL, I am following azure docs
https://learn.microsoft.com/en-us/python/azure/python-sdk-azure-authenticate?view=azure-python
I am getting error
msrest.exceptions.AuthenticationError: Get Token request returned http error: 401 and server response: {"error":"invalid_client","error_description":"AADSTS70002: Error validating credentials. AADSTS50012: Invalid client secret is provided.\r\nTrace ID: be8e6b37-71dc-4a03-a6d5-8c1ea0c91900\r\nCorrelation ID: 0c1cb916-3250-4176-be9e-d951b8ec7203\r\nTimestamp: 2018-12-21 11:03:22Z","error_codes":[70002,50012],"timestamp":"2018-12-21 11:03:22Z","trace_id":"be8e6b37-71dc-4a03-a6d5-8c1ea0c91900","correlation_id":"0c1cb916-3250-4176-be9e-d951b8ec7203"}
I am sure that i am using correct TENANT_ID CLIENT and KEY.
Here is my code from docs
import adal
from msrestazure.azure_active_directory import AdalAuthentication
from msrestazure.azure_cloud import AZURE_PUBLIC_CLOUD
from azure.mgmt.compute import ComputeManagementClient
# Tenant ID for your Azure Subscription
TENANT_ID = 'bef06fb1-f1d7-4b31-9a96-xxfx5xx5xbx2x7'
# Your Service Principal App ID
CLIENT = '8ce61571-35c4-43ce-94ae-7xx1xex2x5x9'
# Your Service Principal Password
KEY = 'SoafGHAvu2EyTdSvxWQo/1XnlKRoaf89eDuuQiCnptc='
subscription_id = '020dd0e6-f63c-4e76-825c-02faad1d8d18'
LOGIN_ENDPOINT = AZURE_PUBLIC_CLOUD.endpoints.active_directory
RESOURCE = AZURE_PUBLIC_CLOUD.endpoints.active_directory_resource_id
context = adal.AuthenticationContext(LOGIN_ENDPOINT + '/' + TENANT_ID)
credentials = AdalAuthentication(
context.acquire_token_with_client_credentials,
RESOURCE,
CLIENT,
KEY
)
client = ComputeManagementClient(credentials, subscription_id)
vmlist = client.virtual_machines.list_all()
for vm in vmlist:
print(vm.name)
`
I can reproduce your issue on my side, I think you did not give the role to your service principal at the subscription scope.
To fix the issue, you could try to navigate to your subscription -> Access control (IAM) -> Add role assignment -> Add a Owner role(for example) to your service principal.
Then it will work fine.
For more details about Azure RBAC, refer to this link.

Categories

Resources