How To Authorize Your Key Vault Secrets To Serverless Azure Function

Are you looking to authorize your Key Vault secrets to Serverless Azure Function? If yes, then this article is for you. In the previous article, we learned how to access and configure Key Vault in our ASP.NET Core web application. Wait! What if we want to access the Key Vault from a Serverless Azure Function?
 
Before diving in, we have already set up a Key Vault on the Azure portal and now, we want to access the stored secrets on Key Vault in our Azure Function.
 
However, you are probably wondering: "How do I use it?" Can I access the Key Vault in the same way as I did in the ASP.NET CORE web application?
 
The answer is NO. Don't you lose hope; we are here to demystify the secret.
 

We can access the Key Vault Secret in our Azure Function in two different ways

  1. Application settings from Key Vault
     
    @Microsoft.KeyVault(SecretUri=secret_uri_with_version) Allowing Application settings to access KeyVault via secret URL
     
  2. Managed Identities for App Services
     
    By giving access rights to our Azure Function to access the Key Vault secrets with the help of Secret URI
     
    https://{name}.vault.azure.net/secrets/{secretname})

Case Study

 
Let us look at an example where we want to access some secret keys in our Azure function to achieve our business requirement. Considering that we are trying to solve a business problem with this HTTP Trigger Azure function, let us do a proof of concept that the Azure function should be an HTTP trigger Azure function. Once the user tries to consume the Azure function, it should show those secret values in the response.
 
Here are the 3 requirements that you will discover,
  1. Configure the Azure function to communicate with Key Vault when deployed on the local development environment and Azure.
  2. Locate where to store keys in the local development environment.
  3. Learn how to Deploy Azure function on Azure.
Prerequisite
  1. Active Azure subscription
  2. Azure Resources needed
     
    • Azure Function
    • Azure Active Directory
    • Key Vault

How do we proceed?

 
Breaking down the problem into smaller chunks first that’s how we will be proceeding ahead step by step,
  1. Create your first HTTP Trigger Azure function. If you are not aware of HTTP Trigger functions, my honest suggestion will to go and read this article HTTP Trigger Azure Function(Serverless Computing).
  2. Create a Service Library which will interact with Key Vault.
  3. Access the value from local.settings.json in our development environment.
  4. Create Azure Resources needed for this Demo.
  5. Provide Key Vault access identity to the Function app using the PowerShell command, manually from the portal.
Let's get started and create our Azure function using Visual Studio.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function 
 
Select HTTP Trigger Template and select Azure Functions V1 because, in version V2, I had some issues with the HTTP trigger function when I tested on my local machine while writing this.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
Template generated code for HTTP trigger.
  1. using System.IO;    
  2. using Microsoft.AspNetCore.Mvc;    
  3. using Microsoft.Azure.WebJobs;    
  4. using Microsoft.Azure.WebJobs.Extensions.Http;    
  5. using Microsoft.AspNetCore.Http;    
  6. using Microsoft.Azure.WebJobs.Host;    
  7. using Newtonsoft.Json;    
  8.     
  9. namespace AzFuncKeyVaultIntegration    
  10. {    
  11.     public static class Function1    
  12.     {    
  13.         [FunctionName("Function1")]    
  14.         public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get""post", Route = null)]HttpRequest req, TraceWriter log)    
  15.         {    
  16.             log.Info("C# HTTP trigger function processed a request.");    
  17.             string name = req.Query["name"];    
  18.             string requestBody = new StreamReader(req.Body).ReadToEnd();    
  19.             dynamic data = JsonConvert.DeserializeObject(requestBody);    
  20.             name = name ?? data?.name;    
  21.             return name != null    
  22.                 ? (ActionResult)new OkObjectResult($"Hello, {name}")    
  23.                 : new BadRequestObjectResult("Please pass a name on the query string or in the request body");    
  24.         }    
  25.     }    
  26. }   
Now, let's create a Service Library which will have all responsibility of calling Key Vault APIs and return us the actual value of our secret keys.

Creating a new Class Library from our solution

 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
Install the below packages to interact with Key Vault from our services library from NuGet.
  • Microsoft.Azure.Services.AppAuthentication Version:1.0.3
  • Microsoft.Extensions.Configuration.AzureKeyVault Version: 2.2.0
Once done, create a class named KeyVaultService putting in the below code snippet.
  1. using Microsoft.Azure.KeyVault;    
  2. using Microsoft.Azure.Services.AppAuthentication;    
  3. using System;    
  4. using System.Threading.Tasks;    
  5.     
  6. namespace Services    
  7. {    
  8.     public class KeyVaultService    
  9.     {    
  10.         public  async Task GetSecretValue(string keyName)    
  11.         {    
  12.             string secret = "";    
  13.             AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();    
  14.             var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));    
  15.             //slow without ConfigureAwait(false)    
  16.             //keyvault should be keyvault DNS Name    
  17.             var secretBundle = await keyVaultClient.GetSecretAsync(Environment.GetEnvironmentVariable("keyvault") + keyName).ConfigureAwait(false);    
  18.             secret = secretBundle.Value;    
  19.             Console.WriteLine(secret);    
  20.             return secret;    
  21.         }    
  22.     
  23.     }    
  24. }    
Now, reference the service library in your Azure Function project.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
So now, let's consider I have created two secrets in Azure Key Vault; for example:
  1. applicationSecret2
  2. secret2
Now I want to access the Key Vault secret applicationSecret2 with the help of managed identities and another secret, secret2, with the help of Key Vault references for Application Settings on Azure.
 
In the ASP.NET core web application, we were using Secret Manager to store our secrets in Development. If you want to read about Secret Manager you can start from here Secret Manager in ASP.NET CORE. In order to access the managed identities value in a local environment, we will be required to add DNS name in local.settings.json and for secret2 value, we can just create a key-value pair with a value as shown below:
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
Access the App settings keys value and call the Service function (GetSecretValue) in Function code,
  1. using System;    
  2. using System.Linq;    
  3. using System.Net;    
  4. using System.Net.Http;    
  5. using System.Threading.Tasks;    
  6. using Microsoft.Azure.WebJobs;    
  7. using Microsoft.Azure.WebJobs.Extensions.Http;    
  8. using Microsoft.Azure.WebJobs.Host;    
  9. using Services;    
  10.     
  11. namespace AzFuncKeyVaultIntegrationM    
  12. {    
  13.     public static class Function1    
  14.     {    
  15.         [FunctionName("Function1")]    
  16.         public static async Task Run([HttpTrigger(AuthorizationLevel.Function, "get""post", Route = null)]HttpRequestMessage req, TraceWriter log)    
  17.         {    
  18.             log.Info("C# HTTP trigger function processed a request.");    
  19.             KeyVaultService _service = new KeyVaultService();    
  20.             //secret name applicationSecret2    
  21.             string secretValue = await _service.GetSecretValue("applicationSecret2");    
  22.             log.Info("Secret value retrived via Secret Uri" + secretValue);    
  23.             // parse query parameter    
  24.             string name = req.GetQueryNameValuePairs()    
  25.                 .FirstOrDefault(q => string.Compare(q.Key, "name"true) == 0)    
  26.                 .Value;    
  27.             if (name == null)    
  28.             {    
  29.                 // Get request body    
  30.                 dynamic data = await req.Content.ReadAsAsync();    
  31.                 name = data?.name;    
  32.             }    
  33.             return name == null    
  34.                 ? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")    
  35.                 : req.CreateResponse(HttpStatusCode.OK, $"Hello {name} using keyvault Syntax from app settings {Environment.GetEnvironmentVariable("secret2")}");    
  36.         }    
  37.     }    
  38. }  
Let's run our application in our development environment. Now check whether our Function app is able to retrieve the secrets or not.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function 
 
In order to consume this HTTP trigger Azure function, I will be using the Postman Rest HTTP client. We will consume the "http://localhost:7071/api/Function1" endpoint.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 

Configure Application Settings from Key Vault on Azure

 
We are successfully able to run our application from our development environment. Now we will deploy our application on Azure and try to access secret secret2 from Key Vault in application settings. This feature works that similarly as we are just using AppSetting key-value pair but internally it retrieves the value from Key Vault. In order to make this work, we have to configure the access policy to Function App, once we deploy our Function app.
 
Let us first deploy our Azure function on Azure Portal using Visual Studio:
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
As I don't have any Azure App Service on Azure I will create a new Azure App Service step by step,
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
Click on Publish.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
Then click on Create. Visual Studio will publish our application now. Once this is completed the Azure function will be published, and we can check the status in an Output window.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function 
 
Let's now login to the Azure portal to see if our Function app has been created or not.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function 
 
Assign your function app access to the Key Vault step by step,
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function 
 
Once you are done click on OK and save the access policy.
 
Once done now enable System Identity in order to authenticate to cloud services (e.g. Azure Key Vault, Active Directory).
  1. Go to function app settings.
  2. Click on platform features.
  3. Click on Identity features in the list.
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function 
Let us now first get the secret_uri_with_version for secret named applicationSecret1 which will be stored in the secret2 key in appSettings.
 
Go to the Key Vault resource that you want to consume and then click on Secret. Now in our function app, I want to use the value of my applicationSecret1 secret which is configured in my (environment variable or AppSettings) on Azure as secret2.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function 
 
Now Click on applicationSecret1 and you will be navigated to version blade view as shown below:
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function 
 
Click on the Current Version row and now copy the Secret identifier value from the new page as shown below:
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
Now go back to the function app and create a new application variable/application setting named "secret2" and put the value in the given format with your secret URL that we just copied, also add other application setting keys and values that are required for the function app like DNS which was present in the local.settings.json file.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 

Format of Key Vault Value for secret

 
@Microsoft.KeyVault(SecretUri=secret identifier value)
 
Once all steps are completed save the application settings and let's try to consume the deployed Azure function from Postman now.
 
Click on Function1 and then click on get function URL and copy the URL:
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function 
 
Hit the URL from POSTMAN and you will see the value retrieved from the Key Vault.
 
Learn How To Authorize Your Key Vault Secrets To Serverless Azure Function
 
So you can see how easily step by step we learned "how to Authorize your Key Vault Secrets to Serverless Azure Function"
 
I hope you enjoyed reading the article as much as I did writing this up.
 
If you did, leave your thoughts in the comments below.
 
Also, I will love it if you share the article on your preferred social media platform.
 
References