This document provides a comprehensive guide on how to securely integrate your Azure Functions with Azure Key Vault to manage sensitive information such as connection strings, API keys, and certificates.
Azure Functions are a powerful serverless compute service that allows you to run small pieces of code, or "functions," in the cloud. Managing secrets and sensitive data is a critical aspect of developing any application. Azure Key Vault is a cloud service that provides a secure store for secrets, cryptographic keys, and certificates. Combining Azure Functions with Key Vault ensures that your application's sensitive information is never hardcoded in your source code or configuration files.
If you don't already have one, create an Azure Key Vault instance through the Azure portal. Ensure you grant appropriate access policies for your Azure Functions to read secrets.
Navigate to your Key Vault and add the secrets you wish to use. For example, you might add a database connection string or an API key.
The most secure way to grant access is by using a Managed Identity for your Azure Function App.
There are a few ways to access secrets from Key Vault within your Azure Functions:
This is the simplest and most recommended approach. You can reference secrets directly in your Function App's application settings.
In your local.settings.json
(for local development) or in the Function App's configuration settings in the Azure portal, you can define an app setting that points to a Key Vault secret:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"MySecretConnectionString": "@Microsoft.KeyVault.Secret://<YourKeyVaultName>.vault.azure.net/secrets/<YourSecretName>/<YourSecretVersion>"
}
}
Note: When deployed to Azure, the Function App's managed identity will be used to retrieve the secret automatically. For local development, you'll need to configure local authentication or use the Azure CLI.
In your function code, you can then access this setting like any other application setting:
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Net.Http;
public static class GetSecretFunction
{
[FunctionName("GetSecret")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string connectionString = Environment.GetEnvironmentVariable("MySecretConnectionString");
if (connectionString == null)
{
log.LogError("MySecretConnectionString is not set in application settings.");
return new BadRequestObjectResult("Failed to retrieve secret.");
}
log.LogInformation($"Retrieved connection string: {connectionString.Substring(0, 10)}..."); // Log a portion for verification
return new OkObjectResult($"Successfully retrieved secret. First 10 chars: {connectionString.Substring(0, 10)}...");
}
}
You can also directly use the Azure SDK to fetch secrets from Key Vault within your function code. This provides more control but requires more explicit handling.
Example using Azure SDK for .NET:
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class GetSecretFromSdkFunction
{
private readonly ILogger _logger;
public GetSecretFromSdkFunction(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<GetSecretFromSdkFunction>();
}
[Function("GetSecretFromSdk")]
public async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
{
_logger.LogInformation("C# HTTP trigger function processed a request.");
string keyVaultName = Environment.GetEnvironmentVariable("KEY_VAULT_NAME");
string secretName = "MySecretConnectionString"; // Replace with your actual secret name
if (string.IsNullOrEmpty(keyVaultName))
{
_logger.LogError("KEY_VAULT_NAME is not set in application settings.");
var errorResponse = req.CreateResponse(System.Net.HttpStatusCode.InternalServerError);
await errorResponse.WriteStringAsync("Key Vault name not configured.");
return errorResponse;
}
string kvUri = $"https://{keyVaultName}.vault.azure.net";
var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
try
{
KeyVaultSecret secret = await client.GetSecretAsync(secretName);
string secretValue = secret.Value;
_logger.LogInformation($"Retrieved secret '{secretName}' successfully.");
var response = req.CreateResponse(System.Net.HttpStatusCode.OK);
await response.WriteStringAsync($"Secret value (first 10 chars): {secretValue.Substring(0, Math.Min(10, secretValue.Length))}...");
return response;
}
catch (Exception ex)
{
_logger.LogError($"Error retrieving secret '{secretName}' from Key Vault: {ex.Message}");
var errorResponse = req.CreateResponse(System.Net.HttpStatusCode.InternalServerError);
await errorResponse.WriteStringAsync($"Failed to retrieve secret: {ex.Message}");
return errorResponse;
}
}
}
DefaultAzureCredential
will automatically use the Function App's managed identity when running in Azure. For local development, you might need to log in via Azure CLI (az login
) or configure other credential sources.
local.settings.json
and ensure it's excluded from source control. Azure Key Vault references work seamlessly across environments.Integrating Azure Functions with Azure Key Vault is a fundamental security practice. By leveraging Key Vault references or the Azure SDK, you can ensure your applications handle sensitive data securely and efficiently, following best practices for cloud-native development.
For more detailed information, refer to the official Azure Functions and Azure Key Vault documentation.