Passwords are like underwear – Keep them hidden using Azure MSI

Introduction

We keep the credentials and other secrets of  the application in the source files. These secrets are visible to developers and being pushed to the source control. In order to avoid this, we can keep the secrets in centralized key management systems – but the credentials of the centralized key management system should be kept in the source files, resulting that at least one credential being placed in the source files.

x.jpeg

Azure Managed Service Identity (MSI) solves this bootstrap problem. It eliminates the need of storing any credentials in the source files.

MSI is supported by different Azure services. This post explains how to set up MSI in the Azure Web App and retrieve a secret stored in Azure Key Vault (a database password).

Setting MSI in Azure Web App

MSI works on Azure AD authentication.  When MSI is enabled in a service (web app) it creates an application principle in the same tenant where the subscription of the Web App is attached to.

Navigate to your Web App, select the Managed Service Identity option and switch the feature ON.

enable MSI in azure web apps

This will create an application principle in the AAD with the same name of the Web App (teslaspace).

2

You can also notice the following section with the specific IDs in the ARM template of Web App.

3

Creating Azure Key Vault and set up Developer Access for Secrets

Now we should create a Azure Key Vault in a subscription attached to the same tenant. We will store our credentials and other sensitive strings in this Key Vault.

Creating a Azure Key Vault is straight forward and it can easily be done via the portal. I have skipped those steps in this post. Read more articles about Azure Key Vault

Once the Key Vault is created, we should add the Web App Service Principle to the Key Vault access policies. Give minimum permissions are possible.

4

This principle is given only Get permissions to the secret. This is enough to retrieve a sensitive string from Azure Key Vault.

We should create a secret in the Azure Key Vault and obtain the secret URI.

5

Navigate to the secret and copy the URI. Secret URIs are in the below format

https://{key vault name}.vault.azure.net/secrets/{secret name}/{version no}

Implementation

We have done below items.

  1. We created Web App and enabled MSI
  2. This created a service principle in the corresponding tenant
  3. We created a Azure Key vault
  4. We granted some permissions to the Web App Service Principle
  5. We created a secret in Key Vault and obtained the URI

Now, the MSI enabled Web App should connect to the Azure Key Vault and obtain the value of the secret. In order to connect to the Key Vault it does not require any credentials to be stored in the source code.

There is a NuGet package which facilitates this process.

Install-Package Microsoft.Azure.Services.AppAuthentication -Version 1.0.0-preview

Also, add a reference to Azure Key Vault

Install-Package Microsoft.Azure.KeyVault -Version 2.3.2

The below code will retrieve the secret for you, ex – a db password


public async Task<string> RetrieveSecretBasedOnMSIAsync()
 {
 AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
 string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/");

 var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
 var secret = await kv.GetSecretAsync("secret uri");

return secret.Value;
 }

If you turn off the MSI from the Web App the above code will throw an exception that it cannot authenticate to the AAD.

Developer Environment

The above works in the production as MSI is enabled in the Web App, but how to set the same configuration in the developer machine and make sure that the authentication happens to AAD via the above code.

This is straight forward, via Azure CLI. You should install Azure CLI 2.0 or above in your development machine.

Also, we need a user principle to authenticate to the AAD. The same principle should be added to the Azure Key Vault with the required permissions (Get permissions for the secrets).

So create a user in AAD. ex – dev1@massroverdev.onmicrosoft.com. Add the user principle to the Key Vault as shown above. You don’t need to assign any subscription access to this user.

That’s all we should do in the Azure. In the developer machine, after installing the Azure CLI 2.0 or above, login to the Azure CLI using below command.

az login --allow-no-subscriptions

This will pop up the device login and complete the login using the credentials of the created user.

Note : You have to provide the — allow-no-subscriptions flag since user does not have any subscription level access. This is the bare minimum developer permission that can be given in MSI.

As long as the developer is logged in to the Azure CLI which has the required permissions in the Azure Key Vault, the above code will work.

Things to note

  • MSI service principle is a AAD V1 approach. V2 or MSAL support is yet to be released. So if you’ve a V2 app registration, enabling MSI will create another V1 application in the tenant. Read more
  • Developer gets to see the secrets during debug. There are workarounds to eliminate this.
    • Use a different KV in production environment
    • User a token based access for the service which have AAD authentication. This is possible in SQL Databases. But it adds additional complexity in handling tokens expiry and etc. Read more

 

 

 

Advertisement