Azure Managed Service Identity (MSI)

While developing any application to use / access any Azure services we always need credentials to validate access. Like Primary Key, SaS Token etc.  As per protocol we make sure we can’t hard code these credentials in code and can’t commit these credentials in to code repository. This is common problem. Handling credentials is always part of security. For this issue Azure has come up with one solution which is Managed Service Identity (MSI). This is part of Azure Active directory service.

How MSI works ?

MSI has 2 types of Identity’s System Assigned Identity and User Assigned Identity.

System assigned identity is already exists / automatically get created in Azure portal. For User Assigned Identity User can create Identity (Azure Active Directory) of any services from portal. Once Identity is created, this can be assigned to any one or more Azure service instance. User assigned identity is stick to azure service instance. If user deletes this services instance then identity get deleted automatically.

Below flow diagram will provide you more details how it works:

Currently (While writing this document) this service is still preview.  All azure services don’t support MSI. Below is the list of services which supports Managed Service Identity.

Services that supports Managed Service Identity

  • Azure Virtual Machines
  • Azure App Service
  • Azure Functions
  • Azure Data Factory V2

Services that support Azure AD authentication via an MSI supplied Token

  • Azure Resource Manager
  • Azure Key Vault
  • Azure Data Lake
  • Azure SQL
  • Azure Event Hubs
  • Azure Service Bus

Below are the detail steps on how to use MSI to manage azure services. In this below example we will deploy Azure ARM template in cross subscription using MSI token from VM.

  1. Create Azure Resource Group and VM in subscription 1.
  • Enable MSI for newly created VM.
  • Go to subscription list
  • Select Subscription 2 –> Access Control (IAM) –> Add

(You should have ‘Owner’ role then only you will be able to see this ‘Add’ option. If you are only able to see ‘Roles’ and ‘Refresh’ option then contact to Administrator for the same)

  • Add permission -> select Role ‘Contributor’ (Contributor can create and manage resources.)
    • ‘Assign Access To’ option selects ‘Virtual Machine’.
    • ‘Subscription’ dropdown select another subscription ‘Subscription Dev 2’.
    • ‘Resource Group’ – select VM’s resource group or ‘All Resources Groups’.

Once you select value in Resource Group, all existing VM’s will be displayed in below list. Select newly created VM (In above steps). Click on ‘Save’.

  • After Save, you can see VM’s name in that particular list like ‘Owner’ or ‘Contributor’.
  • Now all set as part of MSI Configuration. In Above steps we have given (owner / contributor) subscription level rights to VM (gladev2divm0021). It means any code / scripts executes from this VM will be able to manage all subscription level resources using ‘MSI Token’.

Accessing MSI Token

                Login into Virtual Machine to access MSI token.  

##Using Powershell’s Invoke-WebRequest, make a request to the local MSI endpoint to get an access token   ## for Azure Resource Manager

$response = Invoke-WebRequest –Uri http://169.254.169.254/metadata/identity/oauth2 /token? Api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F’ -Method GET -Headers @ {Metadata=”true”}

##Next, extract the full response, which is stored as a JavaScript Object Notation (JSON) ##formatted string in the $response object.

$content = $response.Content | ConvertFrom-Json

##Next, extract the access token from the response.

$ArmToken = $content.access_token

#Finally, call Azure Resource Manager using the access token. In this example, we’re also using PowerShell’s #Invoke-WebRequest to make the call to Azure Resource Manager, and include the access token in the #Authorization header.

(Invoke-WebRequest -Uri https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>?api-version=2016-06-01 -Method GET -ContentType “application/json” -Headers @{ Authorization =”Bearer $ArmToken”}).content

  • Now you have this MSI token which you can pass to Azure Rest API.