How Things Work: Azure Managed Identity and Service Principal
By: Sarah Fan
Tags: Managed Identity, Azure, Service Principal, Authentication, Azure Active Directory

How Things Work: Azure Managed Identity and Service Principal

Introduction

Recently I dabbled into Azure. One of the challenges I faced was to figure out how to integrate two services, and inevitably, I ran into the concepts of managed identity and service principal. It took me a while to grasp the concepts, and I’m sharing my learning here to whoever encounters the same challenge.

After reading the article, you will understand:

How authentication using Active Directory works

what are Azure Activity Directory and Service Principal and their differences

How to use Azure libraries to programmatically authenticate with Azure Active Directory

Azure Active Directory

Azure Active Directory (AAD) is Microsoft’s cloud-based fully managed multi-tenant identity and access management service. An organisation can use it as its identity provider (IdP) to enable single sign-on (SSO) experience of applications running within or outside Azure environment. SSO brings in the benefit that when onboarding or revoking a user, his/her credentials and access permissions are centrally managed, which ensures better security and user experience.

A generic authentication workflow with an IdP is illustrated below (Please note different authentication protocols and methods will have slightly different processes from this generic workflow. See ADD supported authentication methods and authentication protocols. You can consider authentication methods and protocols as to how the communication is agreed and conducted between application, actor and IdP.):

The diagram above highlights two things:

there is no direct sensitive information (e.g. access tokens, secrets, connection strings) exchange between an actor and an application, and credentials management (e.g. create, revoke, update, rotate credentials) is centralised in one place.

Managed Identity & Service Principal

So far, we talked about using AAD to authenticate a human user. When extending this capability to Azure resources (i.e. machine, application, service, etc.), we have managed identity and service principal.

In many situations where process execution is automated, there are usually several Azure services chained in a sequence which requires authentication (e.g. allows Azure Data Factory instance to access an Azure Storage Account to process a file) and authorisation (e.g. restricted to read-only access to data from the particular path) to govern secured access. Similar to the human user authentication with AAD, a requester resource will need to

register itself in AAD (a.k.a creating a service principal),

configure the resource to know the required credentials to identify itself, and

ensure the recipient resource knows how to use the temporary token (i.e. can support receiving requests with AAD authentication).

A service principal can be created in the portal and programmatically using PowerShell. It requires permission to read and write to AAD. Once a service principal is created, a client ID would be added in ADD for role assignments (i.e. authorisation).

An Azure service that supports managed identity can have the registration and configuration done automatically behind the scene by Azure via Azure Resource Management (ARM) template. Therefore, managed identity is to enable an access requester to self identify itself and pass its temporary token along with the outbound request to a recipient resource. Managed identity can be enabled through the Identity > System assigned option in the Azure Portal. Unfortunately, there is only a small number of Azure services that support the creation of managed identity (as a requester) and a subset of Azure services that support AAD authentication (as a recipient) (see the list for detail).

Azure SDK for Authentication

The Azure Identity library can be used to authenticate with Azure services that support AAD token authentication. DefaultAzureCredential is a handy function to obtain the temporary token for most applications running in the Azure environment for both development (i.e. use user credential) and post-deployment phase (i.e. use environment variables or managed identity). It will try to authenticate via environment variables containing account information → managed identity → Visual Studio Code Azure Account extension → Azure CLI az login command → user’s system default browser interactively. An example of using DefaultAzureCredential to authenticate with Azure Storage blob (Note that Azure Storage blob supports ADD authentication):

from azure.identity import DefaultAzureCredential

from azure.storage.blob import BlobServiceClient default_credential = DefaultAzureCredential()

client = BlobServiceClient(account_url, credential=default_credential)

ClientSecretCredential from the Azure Identity library can be used to authenticate with Azure service using token credential (i.e. secrets) when using newer SDK libraries based on azure.core. When using older SDK libraries, use ServicePrincipalCredential from the Azure Common library. An example of using ClientSecretCredential to authenticate with Azure Data Factory using azure.identity:

from azure.common.credentials import ServicePrincipalCredentials

from azure.mgmt.datafactory import DataFactoryManagementClient def main():

# Azure subscription ID

subscription_id = '<Specify your Azure Subscription ID>' # Specify your Active Directory client ID, client secret, and tenant ID

credentials = ServicePrincipalCredentials(client_id='<Active Directory application/client ID>', secret='<client secret>', tenant='<Active Directory tenant ID>')



adf_client = DataFactoryManagementClient(credentials, subscription_id)

The same example of using ServicePrincipalCredential from azure.common:

from azure.identity import ClientSecretCredential

from azure.mgmt.datafactory import DataFactoryManagementClient def main():

# Azure subscription ID

subscription_id = '<Specify your Azure Subscription ID>' # Specify your Active Directory client ID, client secret, and tenant ID

credentials = ClientSecretCredential(client_id='<Active Directory application/client ID>', secret='<client secret>', tenant='<Active Directory tenant ID>')



adf_client = DataFactoryManagementClient(credentials, subscription_id)

Note that using this method, a secret is required during the authentication process. This secret can be stored in a secured place such as Azure Key Vault or environment variables.

Take-Aways