Learn how to Authorize your Key Vault Secrets to Serverless Azure Function

Learn how to Authorize your Key Vault Secrets to Serverless Azure FunctionAre 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.

If you want to learn how to access Key Vault from ASP.NET CORE web application you can read my previous article “Your secrets are safe with Key Vault in ASP.NET CORE

…Before diving in 

Special For You! Are you getting started as an Azure .NET developer and are not aware from where to start and when to use which service? Have you already checked out my Azure Book for .NET Developers ? It’s a full basic learning book getting started with Microsoft Azure Step by Step in 7 days for .NET Developers and many bonuses included source code and access to other Azure Topics.
  Click here to check it out!.

We have already set up a Key Vault on Azure Portal and now 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 ASP.NET CORE web application?
The Answer is NO,  Don’t you lose your hopes as 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 HttpTrigger 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 to for this Demo.
  5. Provide Key Vault access identity to the Function app using power shell command and manual from the portal.

Let’s get started and create our Azure function using Visual studio:

Select HTTP Trigger Template and select Azure Functions V1 because in version V2 I had some issues with Http trigger function when i tested on my local machine while writing this.

Template generated Code for Http trigger

using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;

namespace AzFuncKeyVaultIntegration
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, TraceWriter log)
        {
            log.Info("C# HTTP trigger function processed a request.");
            string name = req.Query["name"];
            string requestBody = new StreamReader(req.Body).ReadToEnd();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;
            return name != null
                ? (ActionResult)new OkObjectResult($"Hello, {name}")
                : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
        }
    }
}

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:

Install 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 along with below code snippet as shown below:

using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using System;
using System.Threading.Tasks;

namespace Services
{
    public class KeyVaultService
    {
        public  async Task GetSecretValue(string keyName)
        {
            string secret = "";
            AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
            var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
            //slow without ConfigureAwait(false)
            //keyvault should be keyvault DNS Name
            var secretBundle = await keyVaultClient.GetSecretAsync(Environment.GetEnvironmentVariable("keyvault") + keyName).ConfigureAwait(false);
            secret = secretBundle.Value;
            Console.WriteLine(secret);
            return secret;
        }

    }
}

Now reference Service library in our Azure function project.

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 help of Key Vault references for Application Settings on Azure.

In 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:

 

Access the App settings keys value and call the Service function (GetSecretValue) in Function code:

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Services;

namespace AzFuncKeyVaultIntegrationM
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
        {
            log.Info("C# HTTP trigger function processed a request.");
            KeyVaultService _service = new KeyVaultService();
            //secret name applicationSecret2
            string secretValue = await _service.GetSecretValue("applicationSecret2");
            log.Info("Secret value retrived via Secret Uri" + secretValue);
            // parse query parameter
            string name = req.GetQueryNameValuePairs()
                .FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
                .Value;
            if (name == null)
            {
                // Get request body
                dynamic data = await req.Content.ReadAsAsync();
                name = data?.name;
            }
            return name == null
                ? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
                : req.CreateResponse(HttpStatusCode.OK, $"Hello {name} using keyvault Syntax from app settings {Environment.GetEnvironmentVariable("secret2")}");
        }
    }
}

Let’s run our application in our development environment. Now check whether our Function app is able to retrieve the secrets or not?

In order to consume this Http trigger Azure function, i will be using Postman Rest HTTP client. We will consume http://localhost:7071/api/Function1” endpoint.

 

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 like 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 access policy to Function App, once we deploy our Function app.

Let us first deploy our Azure function on Azure Portal using Visual Studio:

As I don’t have any Azure App Service on Azure I will create a new Azure App Service Step by Step:

Click on Publish.

Than Click on Create. Visual studio will publish our application now. Once this is completed Azure function will be published, we can check the status in an Output window.

Let’s now login to the Azure portal to see if our Function app has been created or not?

 

Assign your function app access to the Key Vault step by step:

 

Once you are done click on OK, 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.

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.

 

Now Click on applicationSecret1 and you will be navigated to version blade view as shown below:

Click on Current Version row and now copy the Secret identifier value from the new page as shown below:

Now go back to function app and create a new application variable/ application setting named “secret2” and put the value in 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 local.settings.json file.

Format of Key Vault Value for secret:

@Microsoft.KeyVault(SecretUri=secret identifier value)

Once all steps are completed save the application settings and lets try to consume the deployed Azure function from Postman now.

Click on Function1 and then click on get function URL and copy the URL:

Hit the URL from POSTMAN and you will the see the value retrieved from the Key Vault.

So you can see how easily step by step we learned “how to Authorize your Key Vault Secrets to Serverless Azure Function”

If you want to learn Azure from start, my honest suggestion will be to watch this Learn Azure Step by Step video.

I hope you enjoyed the article 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.

References:

Getting Key Vault Secrets in Azure Functions

Simplifying security for serverless and web apps with Azure Functions and App Service

Use Key Vault references for App Service and Azure Functions

 

 

 

 

2 thoughts on “Learn how to Authorize your Key Vault Secrets to Serverless Azure Function

Leave a Reply to Laxmikanth Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.