The MSI feature essentially extends the idea of computer trust. At the Azure level, one can associate an Azure Active Directory (AAD) identity with a particular Azure resource (lets say a web app). This identity can then be used to make authentication decisions against various Azure resources. Currently, the following targets are supported:
- Azure Resource Manager
- Azure Key Vault
- Azure Data Lake
- Azure SQL
- Azure Event Hubs
- Azure Service Bus
When MSI is enabled on a resource, such as a VM, a special endpoint is setup on the local machine. This endpoint can be hit by any code running on the machine itself, and by providing the right parameters, you can get a token that is valid for the resource requested. By default, this endpoint is the following:
http://localhost:50432/oauth2/token
Here is an example of how to call this via powershell:
$response = Invoke-WebRequest -Uri http://localhost:50342/oauth2/token -Method GET -Body @{resource="https://vault.azure.net"} -Headers @{Metadata="true"}
The response is JSON, and the important part of the response is the access_token property.
In some cases, for example Azure Web Apps, enabling MSI populates a couple of environment variables that can be used to determine the exact location of your endpoint. In specific, it is the MSI_ENDPOINT environment variable. For more information, see the documentation here.
In C#, all of the above logic has been abstracted away in the Microsoft.Azure.Services.AppAuthentication library (currently in preview). You can simply add this nuget package to your application to request tokens. Please note that this works well for Azure Web Apps, but that you may have issues with Azure VMs as the environment variables required are not populated by default.
One really cool thing about the AppAuthentication library is that it provides features for local development. When used with visual studio, the library makes use of the developer credentials currently associated to gain access to Azure resources. This is pretty cool!
One last thing on usage is ensuring you are using the right resource type when requesting tokens. The token issued is valid for a paticular resource type, and so you may need to make the call to the endpoint multiple times to get all the tokens required for your application.
Azure Resource Manager = https://management.azure.com/
Azure Key Vault = https://vault.azure.net/
Azure Data Lake = https://datalake.azure.net/
Azure SQL = https://database.windows.net/
Azure Event Hubs = https://eventhubs.azure.net/
Azure Service Bus = https://servicebus.azure.net/
Please note that the trailing slashes are required as part of the request.
When using MSI, you should probably note the following:
- Azure MSI is machine trust, and you now need to concern yourself with all security concerns related to this approach
- If you are using VMs, you will want to combine this with other solutions/techniques that ensure only authorized software can run on your VM
- You will probably want to audit/alert on usage of the MSI identity, including, if you can, the IP which originates the request
- Remember that you need to grant the least privilege to the MSI identity that is being used
I am loving Azure MSI, and the idea that I can now create applications without having to manage identity (or without my devs having to manage it). Hopefully you enjoyed this post!