It only takes five simple steps to secure your secrets in Azure Functions

As seen in my last blog, we occasionally need to address secrets in Azure Function code. It’s too easy to just copy and paste for example connection strings or passwords in the source code but then you risk exposing your secrets to anyone who can access the code.

It takes only five steps to secure these secrets using an access policy. Let’s fix a common example using the Azure Key vault.

An ‘unsafe’ Azure function

Let’s start with an unsafe Azure function. I just took the code of the previous blog.

First, I created an empty Azure Function App:

kv02

Then, I added a simple HTTP triggered function and populated it with some code which connects to an IoTHub using a connection string:

kv03

I marked the part which is ‘insecure’. Here a human-readable secret, a connection string, is shown. How can we insert this connection string at runtime without exposing it directly?

We could hide the secret (again as plain text) in the Azure function Appsettings but there is an even more secure way of hiding them: Azure Key vault.

Step 1: Create an Azure Key vault with the secret key

We need an Azure Key vault for that, which is just another Azure resource. So create it in the same resource group:

kv01

Once created, add the secret connection string as a secret in the Secrets pane:

kv04

You can both generate secrets manually or load (certificate) files. We generate our secret by hand and insert the connection string on an IoTHub:

kv05

Yes, we now have put our secret in our vault.

But secrets are not generally accessible so it’s useless at this point. Only those (services) with the right permissions can access the secrets to read, write, list, etc. For that, Identities have to be granted access to the Key vault.

For now, the Azure Function has no rights to access the vault so it has no permissions. To get permissions, the Azure Function first needs an ‘Identity’, which it does not have yet either.

Step 2: Activate RBAC on Azure Function

Go back to the Azure function. Access the Platform features and look for Identity:

kv06

Here you are able to activate a (System assigned) Identity with the same name as the Azure Function:

“A system assigned managed identity enables Azure resources to authenticate to cloud services (e.g. Azure Key Vault) without storing credentials in code. Once enabled, all necessary permissions can be granted via Azure role-based-access-control. The lifecycle of this type of managed identity is tied to the lifecycle of this resource. Additionally, each resource (e.g. Virtual Machine) can only have one system assigned managed identity.”

Flip the switch and save:

kv07

Check the warning text for the Identity name.

We have now an Identity.

Note: This should not harm or block the execution of Azure Functions. Eg. the Http triggered function is still accessible outside the Azure portal using the API key.

Step 3: Granting access to the Key vault

Again, switch over to the Key vault. This time, go to the Access policies pane:

kv08

As you can see, one Access policy is already added. This is for the person/Identity who created the Key vault.

We add a policy for our new Azure function identity with ‘Read’ access to the secrets. Click the ‘Add new’ button and in the ‘Add access policy’ pane, select the Azure Function principal:

kv09

After ‘Select’, the principal is added.

Proceed with the other settings. Add ‘Get’ permissions for the secrets. The Azure function only needs to read our secret so ‘Get’ is enough for our function:

kv10

In the end, the access policy will look like this:

kv11

Confirm our policy settings.

The Key vault now has a second access policy. The Azure function has got access to the vault and permissions to read the secrets.

Step 4: Adding an Azure function Application setting

The Azure function consumes the now accessible secret as an Azure Function Application setting. This is how it’s exposed to the function source code.

But first, we need the specific identifier of our secret so the Azure function can request its value.

Just visit the page with the latest version of our secret and copy the Secret Identifier:

kv12

This Secret Identifier looks something like:

https://vaultdemo-kv.vault.azure.net/secrets/iothubownersecret/c6907a3e3f914f86a784ea8a5545be13

Note: The hash is the version ‘number’ of our secret.

Now open the Azure function Configuration pane:

kv13

Here, add an Application setting named ‘secretvalue’:

kv14a

The value is the Secret Identifier inserted in some kind of command ‘@Microsoft.KeyVault(SecretUri=[your Secret Identifier])’:

@Microsoft.KeyVault(SecretUri=https://vaultdemo-kv.vault.azure.net/secrets/iothubownersecret/c6907a3e3f914f86a784ea8a5545be13)

Update this setting. Do not forget to save the setting changes:

kv16

Note: Only at this point, the Key vault value is read by the Azure Function.

This is all it takes to configure the Azure Function App.

Step 5: Replace the hard-coded secret

Now all functions can access the secret as an Environment variable. Here is an updated version of our source code:

...
var connectionString = Environment.GetEnvironmentVariable("secretvalue");
log.LogInformation($"Pssst, the secret is {connectionString}");
...

It’s not recommended to actually represent the secret in the logging! But for demonstration purposes, we see the actual secret represented:

kv15

Finally, the secret is now hidden and exposed in a secure way!

What if a secret is updated?

The vault can hold multiple versions of the same secret. Here I updated the same secret with a new value. A second version identifier is created:

kv17

Yes, this update gets a new (hashed?) id. So if the secret changes, the Azure function application setting is not updated automatically! You need to update your Azure function Appsettings too…

Conclusion

In only five steps we transformed an insecure Azure function containing a secret into one that uses the Azure Key vault.

It takes less than a couple of minutes so please try it once. Ans see how easy it is to bump up the security of your Azure functions.

Advertenties