Using Python to Programmatically Authenticate to Azure & Use Resources

Part 3 of a 3 part series on Python integrations with Azure Key Vault

Cherie
9 min readFeb 1, 2023

All good things must come to an end. In my last post of this series, I will tie together all the pieces and hopefully you can make sense of it. Thus far, I’ve tried to logically break down the prerequisites in Parts 1 and 2. Part 3 will walk through how to set up your development environment, reference environment variables, and authenticate to the Azure platform.

If you need the end-to-end tutorial, you can grab it here.

The what…

In order to interact with Azure resources, especially via code, you need to establish and authenticate an identity using credentials. Microsoft discusses different authentication approaches for Python applications. I’m going to be pulling a secret from Azure Key Vault using Azure Identity python libraries but you could very well be connecting to SQL databases, logic apps, or other Azure resources using the same mechanism.

The why…

I chose to work with the Azure Key Vault because it’s a simple place to reference and store valuable information like tokens, certificates, keys, connection strings, and configuration files. Without this you would be managing and hardcoding objects manually or relying on the console which gets mundane.

The prerequisites:

Python Libraries & Functions

Step 1: Setting up your environment

If you are only trying to authenticate using the Interactive Browser, you can hop on down to Step 3.

First things first, follow steps 1–3 in my post on environment variables. This will get you up to speed before we install the two additional libraries above, not used in the previous post, via terminal commands:

pip3 install azure-identity

and

pip3 install azure-keyvault-secrets

Step 2: Updating the .env file values and referencing them in your script

Back in VS Code open the .env file. You will need the following environment variables:

# Setting the subscription variables
AZURE_TENANT_ID = '[YOUR TENANT ID]'
AZURE_SUBSCRIPTION_ID = '[YOUR SUBSCRIPTION ID]'
# Setting the service principal variablesAZURE_CLIENT_ID = '[YOUR SERVICE PRINCIPAL APPLICATION (CLIENT) ID]'
AZURE_CLIENT_SECRET = '[YOUR SERVICE PRINCIPAL SECRET VALUE]'
# Setting the managed identity variablesMI_CLIENT_ID = '[YOUR MANAGED IDENTITY (CLIENT) ID]'
MI_OBJECT_ID = '[YOUR MANAGED IDENTITY OBJECT ID]'
# Setting the key vault variablesKEY_VAULT_URI = 'https://it-eda-dev-platforms-kv.vault.azure.net/'
KEY_VAULT_NAME = 'it-eda-dev-platforms-kv'

After you add the details hit ctrl+K S or File> Save All.

Move to your .py file or .ipynb file, this time I chose to use a Jupyter Notebook (azureIntegrations.ipynb) instead of a regular python file because it is easier to unit test. Import the following libraries that were installed in step 1. I’m importing three credential libraries that are covered below in addition to a secret client library that allows us to interact with Azure key vault secrets.

import os
from dotenv import load_dotenv
from azure.identity import InteractiveBrowserCredential, ClientSecretCredential, DefaultAzureCredential
from azure.keyvault.secrets import SecretClient

The following cells in the Jupyter notebook , or lines in a python file, will change depending on the azure identity credential requirements. I will walk through the interactive browser credential, client secret credential, and managed identity credential in detail.

Step 3: Choosing an Azure identity credential and connecting to key vault

Whew, now we get to tie everything together. How exciting! Hopefully you are still with me. We are going to get a key vault object after authenticating to the Azure identity platform using each method below. The list is either/or and will change based on your needs.

1. Interactive Browser — probably the easiest, but least programmatic, way to authenticate to Azure. When the client is called, your default browser (i.e. Chrome) will pop up and ask you to sign-in to your account. You definitely can’t use this in a CICD workflow, but it is good to use locally, and the scope of the identity will be limited to the access your account has on the platform. You will need to make sure you’ve completed Part 1 of this series to use this authentication method.

After the libraries are installed, two variables need to be created. The first is KVUri and it pulls in the key vault uri that was stored as an environment variable in Step 2, ‘https://it-eda-dev-platforms-kv.vault.azure.net/’. The second is MEDIUM_TOKEN and it’s referencing the key vault secret that was created in Part 1, ‘medium-token’.

# Grabbing environment variables from the .env file
KVUri = os.getenv('KEY_VAULT_URI')
# Creating a variable to store the key vault value in 
MEDIUM_TOKEN = 'medium-token'

Create a variable named credential to call the interactive browser credential class. This variable will also be passed as a parameter in the SecretClient class along with the key vault url, which needs to be stored as a client variable. Note: I needed to add the additionally_allowed_tenants parameter because I work with multiple tenants and it was throwing an error. Take a look at this blog post about working with multiple tenants.

# This section of code authenticates to an Azure Key Vault Using Interactive Browser Credentials
credential = InteractiveBrowserCredential(additionally_allowed_tenants=['*'] )
client = SecretClient(vault_url = KVUri, credential = credential)

Finally, you are going to retrieve your secret from the key vault using the get_secret method with your MEDIUM_TOKEN variable as a parameter and add .value afterwards to get the actual secret value, otherwise you will be getting the secret uri.

When you run the cell, your browser should pop up and you will need to login to the platform using your credentials. I’ve used a print statement to show that the script does what I say it does.

# Lastly the secret is retrieved from the key vault using get_secret
get_secret = client.get_secret(MEDIUM_TOKEN).value
print(get_secret)

Ta-da! We’ve used the interactive browser credential.

2. Service Principal — is my favorite way to connect to the platform but it requires some additional set up. I am not sure why they named this library ClientSecretCredential instead of ServicePrincipalCredential because it could easily cause some confusion with the SecretClient method… But anyways, you need to ensure that Part 1 and Part 2 of this series have been completed above before trying out this code.

Once you’ve installed the libraries above, create the 5 variables below. The first 4 are environment variables being called from your .env file. The last variable is the name of the secret you wish to grab from your key vault.

# This section of code authenticates to an Azure Key Vault Using Client Secret Credential
# It pulls the medium-token stored in the Azure Key Vault
# This keeps senstive information out of the code.
# Grabbing environment variables from the .env file
KVUri = os.getenv('KEY_VAULT_URI')
client_id = os.getenv('AZURE_CLIENT_ID')
client_secret = os.getenv('AZURE_CLIENT_SECRET')
tenant_id = os.getenv('AZURE_TENANT_ID')
# Creating a variable to store the key vault value in
MEDIUM_TOKEN = 'medium-token'

You’ll then pass the client_id variable as the client_id parameter, the client_secret variable as the client_secret parameter, and the tenant_id as the tenant_id parameter in the ClientSecretCredential method and assign everything to a variable named credentials.

# This section of code authenticates to an Azure Key Vault Using the Client Secret Credentials
credentials = ClientSecretCredential(client_id=client_id, client_secret=client_secret,tenant_id=tenant_id)
client = SecretClient(vault_url = KVUri, credential = credentials)

To finish getting your secret value from the key vault, you use the get_secret method and the MEDIUM_TOKEN variable as it’s parameter. You must add .value after the closing bracket or you’ll be retrieving the secret uri which is not useful here.

When you run the cell, the client retrieves your secret from the key vault via api and returns it’s value. The print statement displays the correct password being requested.

# Lastly the secret is retrieved from the key vault using get_secret
get_secret = client.get_secret(MEDIUM_TOKEN).value
print(get_secret)

You now know how to authenticate to the platform using a service principal. YAY.

3. Managed Identity — probably the most popular credential that is used because it doesn’t require password management or much administration. HOWEVER, you cannot use the ManagedIdentityCredential library locally. In order you use a managed identity credential locally you need to use the DefaultAzureCredential library. Microsoft explains the default credential algorithm in more context here. Make sure that Part 1 and Part 2 of this series are completed before using this authentication method.

When called, the library essentially goes through a list of all possible authentication types, starting with Service Principals and ending with the interactive browser. If the Service Principal is set up it will choose that method first, if it isn’t, it will go down the list of scenarios so on and so forth until one option authenticates.

In your .env file, ensure that you store the ID of the managed identity as a variable (MI_CLIENT_ID) along with your key vault url (KEY_VAULT_URI) so you can call them from your .env file in to your python script. After, switch to your python file and add the lines below. The script below creates three variables, one for the Key Vault url, another for the Managed Identity ID, and the last one is the name of the password you wish to retrieve from the Key Vault.

# Grabbing environment variables from the .env file
KVUri = os.getenv('KEY_VAULT_URI')
MI_CLIENT_ID = os.getenv('MI_CLIENT_ID')
# Creating a variable to store the key vault value in 
MEDIUM_TOKEN = 'medium-token'

Note: I was a tad lazy here and stored the KEY_VAULT_URI environment variable under the name KVUri. You can really choose any name to store your environment variables but for more readable code it’s best to consistent.

After you will create a variable named credential to call the Default Azure Credential class. The DefaultAzureCredential class may require 2 parameters, a managed_identity_client_id parameter which will be your MI_CLIENT_ID variable from the .env file above and the additionally_allowed_tenants parameter which you will need if you use multiple tenants or can help sometimes if other errors are being thrown.

In the next line, the credential variable will also be passed as a parameter value in the SecretClient class along with the key vault url variable (KVUri) which is then assigned as a variable called client (same same as other methods mentioned above).

# This section of code authenticates to an Azure Key Vault Using Default Browser Credentials
credential = DefaultAzureCredential(managed_identity_client_id = MI_CLIENT_ID, additionally_allowed_tenants=['*'])
client = SecretClient(vault_url = KVUri, credential = credential)

You retrieve the key vault secret value using the get_secret method with your MEDIUM_TOKEN variable as a parameter and add .value after the closing bracket. I’ve printed the secret to show that the retrieval is successful.

# Lastly the secret is retrieved from the key vault using get_secret
get_secret = client.get_secret(MEDIUM_TOKEN).value
print(get_secret)

Bada bing bada boom. Congratulations! Now you’re able to authenticate and interact with the Azure platform in multiple ways. You can apply this knowledge to other Azure libraries for programmatically interacting with databases, logic apps, functions, etc.

I hope you have as much fun trying this out, as I did writing this series. Feel free to connect with me on LinkedIn or follow me here for future content!

--

--