Highlight
Managing application account credentials is just another thing to worry for application developers; especially in public cloud. Learn what is Managed Identity for Azure Services and how does it solve this problem.
Intro
Cloud is all about decomposition of application architecture. Usually more components mean more resilient, more scalable and more cost-effective solution. But this also poses new challenges that previously developers and architects didn’t even need to worry about.
Cross-Service Authentication in Azure
Most cross-service integrations in Azure, are done either via secret keys or token exchange. Token exchange is much better approach because it is done using Azure AD. Thanks to this developers have much better control over security, lifecycle and permissions of their applications. Azure AD allows creation of something called service principal, which in layman terms is simply application user.
Any kind of user in Azure, regardless of its type is called identity. It’s important to remember this, because identity is word very often mentioned in the documentation and in Azure Portal. Typical user consists of Client ID (consider this as username) and Client Secret or Certificate (consider this a password). Any service presenting a set of those credentials can retrieve a token from Azure Active Directory which can be used to communicate with other services in Azure.
Terminology
When it comes to entire topic of Identity and security in Azure there are few terms and a lot of aliases. There is no other way than just simply learning them.
So, in short.
- Service Principal - application account (technical user).
- Identity - a service or user in Azure AD. Often used as synonym for service principal.
- Client ID - a globally unique identifier generated for each application and service principal during creation.
- Application ID - synonym for Client ID.
- Managed Service Identity (MSI) - this is old name for what is called right now Managed Identities. Large amount of documentation still is referring to this name.
The simplest design of an application using token authentication looks like this.
To explain the process here
- Service A send the request to Azure AD with Application Credentials to get the token to call Service B
- Azure AD validates the Application Credentials and returns Token on successful authentication
- Service A send the request to Service B with Token in authorization headers
- Service B send the request to Azure AD with Token verify the token
- Azure AD validates the Token and returns validation response
- Service B responds to Service A
This is good. This is how it should work in well-designed authentication in Azure. But there is a catch in here.
How does Service A store Application Credentials?
There is couple of ways Service A can storage credentials. Most common practice to this date is, storing credentials in configuration file, database or environment variables. As anyone can imagine, this isn’t very the best practice because anyone who has access to environment also has access to credentials.
What about KeyVault?
Managed Identity
Here comes managed identity to save the day. Managed Identities is a feature of Azure AD which automatically creates service principal that is tied with the Azure service itself. This identity is automatically also managed by Azure AD and once service is removed the principal will be too. Great part about this isn’t really the management of that identity but that applications hosted on those services can generate tokens using this identity without a need to provide any credentials.
How is this secure?
It is secure because only application hosted on that service which has managed identity enabled will be able to generate tokens.
How Managed Identity works in detail
In classic approach getting token required applications to send request to login.onmicrosoft.com OAuth endpoint. When doing so application has to supply identity credentials and URL of the service that the token will be used for. With managed identity this is much simpler.
Managed Identity principle is always the same, but the usage and implementation is different across different Azure services. Take app service for example.
App Service
When Managed identity is registered on App Service few things happen.
- First of all, a local REST endpoint is registered which is used to retrieve tokens. This endpoint can be only called locally and required secret key from environment variables.
- Endpoint is located as environment variable called MSI_ENDPOINT
http://127.0.0.1:41922/MSI/token/
- And secret for this endpoint is environment variable called MSI_SECRET
BDCF130B80894D398D9716C10C7C419E
- Azure Identity (Service Principal) is created in Azure AD which is tied to this service. This identity is automatically managed by Azure AD.
Requesting Token
When MSI is set up requesting token is very simple. Depending on language you use below samples can be used.
C# Example
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.KeyVault;
// ...
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://vault.azure.net");
// OR
var kv = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)
);
PowerShell Example
$apiVersion = "2017-09-01"
$resourceURI = "https://vault.azure.net"
$tokenAuthURI = $env:MSI_ENDPOINT + "?resource=$resourceURI&api-version=$apiVersion"
$tokenResponse = Invoke-RestMethod `
-Method Get `
-Headers @{"Secret"="$env:MSI_SECRET"; "Content-Type"="application/json"} `
-Uri $tokenAuthURI `
-UseBasicParsing
$accessToken = $tokenResponse.access_token
NodeJS Example
const rp = require('request-promise');
const getToken = function(resource, apiver, cb) {
let options = {
uri: `${process.env["MSI_ENDPOINT"]}/?resource=${resource}&api-version=${apiver}`,
headers: {
'Secret': process.env["MSI_SECRET"]
}
};
rp(options)
.then(cb);
}
REST Call Example
GET /MSI/token?resource=https://vault.azure.net&api-version=2017-09-01 HTTP/1.1
Host: localhost:4141
Secret: BDCF130B80894D398D9716C10C7C419E
Setting up example for App Service
To create MSI in app Service use either of following methods.
Portal
- Go to Web App (App Service)
- Search for Identity in the search window on blade list panel
- Select On option on the blade window
- Click Save to make the change
- Once service principal is created following screen should be shown
Azure CLI
az webapp identity assign --name myApp --resource-group myResourceGroup
With output
{
"identityIds": null,
"principalId": "6009de17-ca37-44d6-b522-5f4de3d2ebdd",
"tenantId": "1f0fb2d0-9423-4dce-ac05-7f195c4ee405",
"type": "SystemAssigned"
}
Azure PowerShell
Set-AzWebApp -AssignIdentity $true -Name $webappname -ResourceGroupName myResourceGroup
With output
...
Identity : Microsoft.Azure.Management.WebSites.Models.ManagedServiceIdentity
...
Azure Resource Manager template
{
"identity": {
"type": "SystemAssigned"
}
}
Managed Identity types
There are currently two types on managed identities
- System Assigned means that lifecycle of managed identity is automatically and managed by Azure AD.
- User Assigned allows user to first create Azure AD application/service principal and assign this as managed identity and use it in the same manner. This has few advantages in terms of reuse of applications and their permissions if many services in Azure should share the account and its permissions.
Adding Access to Managed Identity
When managed identity is provisioned it can be found in Azure Portal for many services. This allows for RBAC assignments of Roles.
- Go to resource
- Open Access control (IAM) blade
- Click on Add Role and select role
- Select App Service from managed identities section
- Select identity and click Save
List of services that allow for assignment of RBAC/roles for Managed Identity
- Resource Manager - manage Azure resources
- Key Vault - keys, secrets, certificates
- Data Lake - data in data lake
- SQL - data in sql
- Event Hubs - queue data
- Service Bus - queue data
- Storage blobs and queues - storage and queue data
- Analysis Services - manage AAS data or server properties
Local development
When it comes to local development with managed identity at first it is very confusing. This is one of very good cases for user assigned managed identity.
How in short how it works is.
Because as of Today there is no MSI emulator users need to use Azure CLI. Azure CLI allows to log in as user but also as Azure Service Principal. This is a good use case for User Assigned Managed Identity. When user created its own principal, he/she can log as that principal locally and request tokens using CLI
KeyVault example
az account get-access-token --resource 'https://vault.azure.net'
Why calling local command line isn’t necessarily the most beautiful approach it surely works. But what is great here is that Microsoft SDKs for identity will recognize local development and lack of Managed Identity endpoint and try to call CLI in the background without any code changes. This is huge benefit of using SDKs.
Supported Services
This list is compilation of services which support or partially support managed identities.
Azure Global
Global Azure region means all regions with exception of Azure Germany, Government and China.
Service (link to Managed Identity docs) | System assigned | User assigned |
---|---|---|
Available | Preview | |
Available | Preview | |
Available | Preview | |
Preview | Preview | |
Available | Preview | |
Preview | Not available | |
Available | Not available | |
Available | Not available | |
Preview | Preview | |
Not available | Not available | |
Available | Preview |
Azure Government
Service | System assigned | User assigned |
---|---|---|
| Preview | Preview |
| Preview | Preview |
| Available | Not available |
| Not available | Not available |
| Available | Not available |
| Preview | Not available |
| Not available | Not available |
| Available | Not available |
| Not available | Not available |
| Not available | Not available |
Azure Germany
Service | System assigned | User assigned |
---|---|---|
| Preview | Preview |
| Preview | Preview |
| Available | Not available |
| Not available | Not available |
| Available | Not available |
| Not available | Not available |
| Not available | Not available |
| Not available | Not available |
| Not available | Not available |
| Not available | Not available |
Azure China
China region available via 21Vianet
Service | System assigned | User assigned |
---|---|---|
| Preview | Preview |
| Preview | Preview |
| Available | Not available |
| Not available | Not available |
| Available | Not available |
| Preview | Not available |
| Not available | Not available |
| Not available | Not available |
| Not available | Not available |
| Not available | Not available |
Conclusion
How it all it takes is just review services and start implementing this fantastic feature.
Read more on Identities on Azure documentation for Managed Identity.