At the end of last week (14 Sept 2017) Microsoft announced a new Azure Active Directory feature – Managed Service Identity. Managed Service Identity helps solve the chicken and egg bootstrap problem of needing credentials to connect to the Azure Key Vault to retrieve credentials. When used in conjunction with Virtual Machines, Web Apps and Azure Functions that meant having to implement methods to obfuscate credentials that were stored within them. I touched on one method that I’ve used a lot in this post here whereby I encrypt the credential and store it in the Application Settings, but it still required a keyfile to allow reversing of the encryption as part of the automation process. Thankfully those days are finally behind us.
I strongly recommend you read the Managed Service Identity announcement to understand more about what MSI is.
This post details using Managed Service Identity in PowerShell Azure Function Apps.
Enabling Managed Service Identity on your Azure Function App
In the Azure Portal navigate to your Azure Function Web App. Select it and then from the main-pane select the Platform Features tab then select Managed service identity.
Turn the toggle the switch to On for Register with Azure Active Directory then select Save.
Back in Platform Features under General Settings select Application Settings.
Under Application Settings you will see a subset of the environment variables/settings for your Function App. In my environment I don’t see the Managed Service Identity variables there. So lets keep digging.
Under Platform Features select Console.
When the Console loads, type Set. Scroll down and you should see MSI_ENDPOINT and MSI_SECRET.
NOTE: These variables weren’t immediately available in my environment. The next morning they were present. So I’m assuming there is a back-end process that populates them once you have enabled Managed Service Identity. And it takes more than a couple of hours
Creating a New Azure Function App that uses Managed Service Identity
We will now create a new PowerShell Function App that will use Managed Service Identity to retrieve credentials from an Azure Key Vault.
From your Azure Function App, next to Functions select the + to create a New Function. I’m using a HttpTrigger PowerShell Function. Give it a name and select Create.
Put the following lines into the top of your function and select Save and Run.
# MSI Variables via Function Application Settings Variables # Endpoint and Password $endpoint = $env:MSI_ENDPOINT $endpoint $secret = $env:MSI_SECRET $secret
You will see in the output the values of these two variables.
Now that we know we have Managed Service Identity all ready to go, we need to allow our Function App to access our Key Vault. If you don’t have a Key Vault already then read this post where I detail how to quickly get started with the Key Vault.
Go to your Key Vault and select Access Polices from the left menu list.
Select Add new, Select Principal and locate your Function App and click Select.
As my vault contains multiple credential types, I enabled the policy for Get for all types. Select Ok. Then select Save.
We now have our Function App enabled to access the Key Vault.
Finally in your Key Vault, select a secret you want to retrieve via your Function App and copy out the Secret Identifier from the Properties.
Function App Script
Here is my Sample PowerShell Function App script that will connect to the Key Vault and retrieve credentials. Line 12 should be the only line you need to update for your Key Vault Secret that you want to retrieve. Ensure you still have the API version at the end (which isn’t in the URI you copy from the Key Vault) /?api-version=2015-06-01
When run the output if you have everything correct will look below.
We now have the basis of a script that we can use in our Azure Functions to allow us to use the Managed Service Identity function to connect to an Azure Key Vault and retrieve credentials. We’ve limited the access to the Key Vault to the Azure Function App to only GET the credential. The only piece of information we had to put in our Function App was the URI for the credential we want to retrieve. Brilliant.