Azure python sdk authentication with cert hangs - python

I am trying to authenticate with the python SDK to pull Azure VNet data.
As a first step to verify that I can authenticate I am trying to use the subscription client to list subscriptions. I am creating a certificate credential to use for authentication.
When I make the call to list the subscriptions from the subscription client the call hangs seemingly indefinitely with no error returned. I am trying to authenticate to azure_gov. Here is the code:
import logging
import os
import boto3
from msrestazure.azure_cloud import AZURE_US_GOV_CLOUD as CLOUD
from azure.identity import CertificateCredential
from azure.mgmt.subscription import SubscriptionClient
# Setup logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
logging.basicConfig(level=logging.INFO)
# Constants
CERT_PATH = '/tmp/cert.pem'
AZURE_CERT_PATH = '/tmp/cert.pem'
AZURE_TENANT_ID = os.environ['AZURE_TENANT_ID']
AZURE_CLIENT_ID = os.environ['AZURE_CLIENT_ID']
AZURE_SDK_S3_BUCKET = os.environ['AZURE_SDK_S3_BUCKET']
s3 = boto3.client('s3')
s3.download_file(AZURE_SDK_S3_BUCKET, 'certs/cert.pem', CERT_PATH)
# Setup Azure credentials
credential = CertificateCredential(
tenant_id=AZURE_TENANT_ID,
client_id=AZURE_CLIENT_ID,
certificate_path=AZURE_CERT_PATH,
authority=CLOUD.endpoints.active_directory)
logger.info(f'tenant_id = {AZURE_TENANT_ID}, client_id = {AZURE_CLIENT_ID}')
logger.info(f'CLOUD: {CLOUD}')
sub_client = SubscriptionClient(
credential=credential,
base_url=CLOUD.endpoints.resource_manager)
#Code times out here
subscription = next(sub_client.subscriptions.list())
logger.info(f'Fetched subscription {subscription.subscription_id}')
I have verified multiple times that the cert, tenant_id, and client_id all match what I see in active directory.
I've found the following posts from Microsoft: first post and second post, which both use the azure.mgmt.resource SubscriptionClient which gives no attribute 'signed_session' in the CertificateCredential when trying to use a CertificateCredential to setup the client.
I have found the following adapter for using the CertificateCredential class with this client and tried using it but it also gives me the same timeout issue on the next(sub_client.subscriptions.list) call.
EDIT:
I am still seeing issues with this, when things completely time out after the max number of retries I get the following error:
Attempted credentials:
EnvironmentCredential: Authentication failed: <urllib3.connection.HTTPSConnection object at 0x7fad94f116d8>: Failed to establish a new connection: [Errno 110] Connection timed out
I don't think it is an environment issue as I can log into the Azure CLI from the same instance.

Related

Retrieving ID/email from an Azure credential

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)

Why do I get `secretmanager.versions.access` denied in GCP?

I am trying to access a secret stored in secrets manager.
I created a service account with owner role. I created a key from it. I run:
import os
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = './keyfile.json'
from google.cloud import secretmanager
secret_client = secretmanager.SecretManagerServiceClient()
secret_name = f'projects/{project_id}/secrets/{secret_id}/versions/{version_id}'
response = secret_client.access_secret_version(request={"name": secret_name})
but I get:
google.api_core.exceptions.PermissionDenied: 403 Permission 'secretmanager.versions.access'
denied for resource 'projects/myprojnumber/secrets/mysecret/versions/1' (or it may not exist).
I checked the secret_name was the same as the secret's value in secret manager.
I have tried adding Secret Manager Secret Accessor and Secret Manager Viewer roles.
Edit: running this from cloud shell.
I think the issue is that the code is taking the Default Credentials of the Cloud Shell instead of using your SA key.
You can specify the credentials when creating the client
from google.cloud import secretmanager
from google.oauth2 import service_account
credentials = service_account.Credentials.from_service_account_file("./keyfile.json")
secret_client = secretmanager.SecretManagerServiceClient(credentials=credentials)
secret_name = f'projects/{project_id}/secrets/{secret_id}/versions/{version_id}'
response = secret_client.access_secret_version(request={"name": secret_name})
Another option using some of the methods found in the library docs:
from google.cloud import secretmanager
secret_client = secretmanager.SecretManagerServiceClient.from_service_account_file("./keyfile.json")
secret_name = f'projects/{project_id}/secrets/{secret_id}/versions/{version_id}'
response = secret_client.access_secret_version(request={"name": secret_name})
Just as an advice, being newbie does not mean you cannot Google a little more to search for something like how to use a SA as credential for the client of the library you're using.
For example you could easily find this doc which shows a sample.
Anyway, good luck with GCP!

AADSTS700016 ERROR when I try to get access to my outlook calandar with python

I'm trying to get access to my outlook calandar using the following code:
from bs4 import BeautifulSoup
from googleapiclient.discovery import build
from google.auth.transport.requests import Request
from O365 import Account
from O365 import Connection
from O365 import FileSystemTokenBackend
from configparser import ConfigParser
file='config.py'
config = ConfigParser()
config.read(file)
def authenticate_outlook():
# authenticate microsoft graph api credentials
credentials = (config['account']['outlook_client_id'], config['account']['outlook_client_id'])
token_backend = FileSystemTokenBackend(
token_path=config['account']['outlook_token_path'], token_filename=config['account']['outlook_token_filename']
)
account = Account(credentials, token_backend=token_backend)
if not account.is_authenticated:
# not authenticated, throw error
account.authenticate(scopes=config['account']['outlook_scopes'])
connection = Connection(credentials, token_backend=token_backend, scopes=config['account']['outlook_scopes'])
connection.refresh_token()
print("Authenticated Outlook.")
return account
# authenticate outlook credentials
outlook_acct = authenticate_outlook()
And i'm using this config.py file:
[account]
outlook_client_id = "86ae4814-fad2-4cc0-b76e-57bd4b20476c"
outlook_client_secret = "06ecc895-b04d-4578-9c3c-b5a8ccc026ab"
outlook_scopes = ["basic", "calendar"]
outlook_token_path = "./credentials/"
outlook_token_filename = "outlook_token.txt"
previous_days = 40 # retrieve this many past days of events
future_days = 365 # retrieve this many future days of events
Then I get this error:
AADSTS700016: Application with identifier '"86ae4814-fad2-4cc0-b76e-57bd4b20476c"' was not found in the directory 'z7fs3'. 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 checked that i'm using the good app ID and the secret ID, They match with my app on AZURE, I don't ound the issue yet.
Thank you.
The issue indicates that there is a mismatch between the tenant where your app is registered and where you have stated that your app is registered in either the application code or the portal.
You must set the tenant ID in your codE for the application. This is usually found in the web.config or app settings files.
Then, using the same tenant ID that you specified in your code, you must register the application on the portal. Make sure your application ID and client ID are the same on both sides, and that all of the values in your app settings/web.config are the same as what you have in the portal.
Also, using the ID in the Client secret section instead of the Application (client) ID is a common cause of this problem.

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)

Attempting to use service client factory with no configured API client

I am trying to add isp(in skill purchase) to my Alexa Skill. The skill code is written in python and in the Launch request handler i have written the following code:
locale = handler_input.request_envelope.request.locale
monetization_service = handler_input.service_client_factory.get_monetization_service()
product_response = monetization_service.get_in_skill_products(locale)
if isinstance(product_response, InSkillProductsResponse):
in_skill_product_list = product_response.in_skill_products
self._logger.info(in_skill_product_list)
When I am running my lambda though I am getting the following error:
Attempting to use service client factory with no configured API client
Has anybody faced this issue let me know what is it am doing incorrectly?
While initializing the skillbuilder i was using
sb = SkillBuilder()
This SkillBuilder does not have APIClient configured. Instead changing it to
sb = StandardSkillBuilder()
works as it has ApiClient configured.

Categories

Resources