Summary
In modern software development, security practices often involve securely managing and regularly updating cryptographic keys used for authentication and encryption. Azure Functions provides a powerful serverless computing platform that can be leveraged to automate tasks like key refreshing. In this article, we'll demonstrate how to create an Azure Function in C# that retrieves public keys from a JWKS (JSON Web Key Set) endpoint and stores them securely in Azure Key Vault.
Prerequisites
Before we start, make sure you have the following prerequisites set up.
- Azure Subscription: You'll need an Azure account to create Azure Key Vault.
- Azure Key Vault: Create an Azure Key Vault instance where the keys will be stored securely.
- Azure Functions: Set up an Azure Functions application in your Azure portal.
Setup Azure Key Vault
Create a secret and put any random value in my case I have put the value asif123.
See the current version of the Secret.
Show the Secret Value
Copy Client ID & Tenant ID from your Registered App from Microsoft Entra ID.
Now go to the Web browser and place Tenant ID and Client ID to get the JWKS from Microsoft Entra ID.
https://login.microsoftonline.com/Your_Tenant_ID/discovery/keys?appid=Your_Application_ID
Setting up the Azure Function
We will create a C# Azure Function app that uses the HttpClient to fetch keys from a JWKS endpoint and then securely stores them in Azure Key Vault.
Create an Azure Function App in Azure Portal by following the steps.
Now Enabling Manage Identity on Azure Function App.
Create Azure Function from Visual Studio.
Copy the URL from browser
Copy the Key Vault URL
Create Azure Function in Visual Studio.
Go to the file and paste the copied URLs in highlighted places.
copy the following code and replace the highlighted values.
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Newtonsoft.Json.Linq;
using System;
using static System.Net.WebRequestMethods;
namespace az_function_app_key_refresher
{
public static class KeyRefreshFunction
{
private static readonly HttpClient httpClient = new HttpClient();
[FunctionName("KeyRefreshFunction")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("Refreshing Public key.");
// Fetch JWT keys from JWKS endpoint
string jwksEndpoint = "https://login.microsoftonline.com/3ed13bce-637a-48c0-9488-1d296357a694/discovery/keys?appid=974b51ab-3fc7-4194-8295-66fc2c020a57";
string jwksJson = await httpClient.GetStringAsync(jwksEndpoint);
var jwks = JObject.Parse(jwksJson);
// Store JWT keys in Azure Key Vault
await StoreKeysInKeyVault(jwks, log);
return new OkObjectResult("Public key refreshed and stored in Azure Key Vault.");
}
private static async Task StoreKeysInKeyVault(JObject jwks, ILogger log)
{
var secretClient = new SecretClient(new Uri("https://azure-function-app-key-refresher.azurewebsites.net"), new DefaultAzureCredential());
string secretName = "mysecret";
foreach (var key in jwks["keys"])
{
string keyId = key["kid"].ToString();
string keyJson = key["x5c"].ToString().Replace('[',' ').Replace('"',' ').Replace('"',' ').Replace(']',' ').Trim();
// Store the key in Azure Key Vault
await secretClient.SetSecretAsync(secretName, keyJson);
log.LogInformation($"Stored key with ID {keyId} in Azure Key Vault.");
break;
}
}
}
}
Run the Azure Function with F5 from Visual Studio in the Local environment and you can test it locally by signing in from Visual Studio to your Azure Portal.
Copy the URL and paste it into the Postman and execute this using Get request.
http://localhost:7193/api/KeyRefreshFunction
When you execute this request from Postman.
you will get the message on the console as highlighted below.
Now go to the Azure portal go to the secret and click on it.
Now you can see that there are two versions of secret and secret points to the current version.
You can see the secret value that has a new value that was extracted from the JWKS URL.
Successfully refreshed the secret at Azure Key Vault from Azure Function that was locally executed using Managed Identity.
Summary
This article outlines the process of automating key refreshing in Azure Functions using C# to securely manage and update cryptographic keys fetched from a JWKS (JSON Web Key Set) endpoint and store them in Azure Key Vault. The article emphasizes modern security practices in software development and the use of serverless computing for automation.
Key Points Covered
- Security Practices: Emphasizes the importance of securely managing and updating cryptographic keys for authentication and encryption in modern software development.
- Azure Services Used: Demonstrates the integration of Azure Functions and Azure Key Vault to automate key refreshing tasks.
- Prerequisites: Lists the prerequisites required to set up the Azure Function and Azure Key Vault, including an Azure subscription and Azure Functions application.
- Setup of Azure Key Vault: Provides step-by-step instructions on setting up Azure Key Vault, creating a secret, and accessing the secret value.
- Azure Function Configuration: Details the creation and configuration of an Azure Function app using Visual Studio, enabling managed identity, and integrating with Azure Key Vault.
- Code Implementation: Presents a C# code snippet for the Azure Function (`KeyRefreshFunction`) that retrieves keys from a JWKS endpoint using `HttpClient` and stores them securely in Azure Key Vault using SecretClient.
- Testing Locally: Guides on running and testing the Azure Function locally from Visual Studio and Postman, showcasing the successful execution of key refreshing using managed identity.
- Outcome: Concludes with the successful refresh of the Azure Key Vault secret, demonstrating effective automation of key management tasks within a secure environment.
Overall, this summary encapsulates the process of implementing automated key refreshing in Azure Functions, highlighting best practices in security and Azure services integration for secure key management in cloud-based applications.