How do you manage secrets and configuration settings in Azure Functions?

Question

How do you manage secrets and configuration settings in Azure Functions?

Brief Answer

Managing secrets and configuration in Azure Functions hinges on a core principle: App Settings for non-sensitive configuration, and Azure Key Vault for sensitive secrets.

  • App Settings (Configuration): Use these for non-sensitive values like API endpoints, feature flags, or non-credentialed connection strings. They are easily managed in the Azure portal, CLI, or Infrastructure-as-Code (IaC). However, they are not encrypted at rest like Key Vault secrets and should never store sensitive data.
  • Azure Key Vault (Secrets): This is the secure, centralized solution for sensitive data such as passwords, API keys, and certificates. Key Vault offers robust security (e.g., Hardware Security Modules), comprehensive auditing, versioning, and granular access control through policies.
  • Managed Identities: For secure access to Key Vault from your Function App, always use Managed Identities. This eliminates the need to manually manage credentials, significantly reducing your attack surface and simplifying authentication to Azure services.
  • Local Development: Use local.settings.json to mimic App Settings and Key Vault secrets locally. Crucially, ensure this file is always excluded from source control (e.g., via .gitignore) to prevent accidental secret exposure.
  • Avoid Environment Variables for Production Secrets: While usable locally, environment variables lack the robust security, auditing, and management features that Azure Key Vault provides for production environments.

In essence, distinguish between configuration and secrets, use the right tool for each, and leverage Azure’s built-in security features like Managed Identities for a robust and secure solution.

Super Brief Answer

In Azure Functions, manage non-sensitive configuration using App Settings and all sensitive secrets (passwords, API keys, certificates) exclusively with Azure Key Vault.

  • Access Key Vault securely using Managed Identities for your Function App.
  • For local development, use local.settings.json, ensuring it’s always in .gitignore.
  • Never store production secrets in App Settings or environment variables; Key Vault is mandatory for security, auditing, and management.

Detailed Answer

In Azure Functions, you manage configuration settings and secrets through distinct, secure mechanisms. For non-sensitive application configuration, App Settings are the primary method. Crucially, for sensitive data like passwords, API keys, or certificates, Azure Key Vault is the essential, recommended service. While environment variables can be used for local development, they are not suitable for production secrets. The core principle is: App Settings for configuration, Azure Key Vault for secrets.

Understanding Configuration vs. Secrets in Azure Functions

A fundamental aspect of secure application development in Azure Functions is understanding the difference between configuration settings and secrets:

  • Configuration Settings: These are non-sensitive values that dictate your function’s behavior. Examples include connection strings (without sensitive credentials), feature flags, logging levels, or API endpoints. They are not inherently risky if exposed.
  • Secrets: These are highly sensitive pieces of data that, if compromised, could lead to severe security breaches. This includes database passwords, API keys with write access, cryptographic keys, or certificates. Protecting secrets is paramount.

Consider a real-world example: In a serverless e-commerce platform built with Azure Functions, a Stripe API key (granting access to financial transactions) is classified as a ‘secret’ and must be highly protected. Conversely, the URL for a product image CDN, while important for application functionality, is ‘configuration’ and doesn’t pose a security risk if public.

Key Mechanisms for Managing Settings and Secrets

1. App Settings for Configuration (Non-Sensitive Data)

Azure Functions utilizes App Settings for managing non-sensitive configuration values. These settings are easily managed directly in the Azure portal, via the Azure CLI, PowerShell, or through Infrastructure-as-Code tools like Azure Resource Manager (ARM) templates or Terraform. They are ideal for:

  • Connection strings (excluding the password, which should be in Key Vault)
  • Feature flags to control application behavior
  • Logging levels and diagnostic settings
  • Non-sensitive API endpoints or public identifiers

While convenient, it’s critical to remember that App Settings are not encrypted at rest in the same way Key Vault secrets are, and they are generally visible to anyone with sufficient access to the Function App’s configuration. Therefore, they are not suitable for sensitive data.

2. Azure Key Vault for Sensitive Secrets

Azure Key Vault is your dedicated, secure solution for storing and managing sensitive data. It acts as a centralized fortress for:

  • Passwords
  • Sensitive API keys (e.g., those with write or administrative permissions)
  • Certificates
  • Cryptographic keys
  • Any other information that would cause significant damage if compromised.

Key Vault offers robust security features, including Hardware Security Modules (HSMs) for key protection, comprehensive auditing capabilities, and versioning of secrets. Its seamless integration with Azure Functions simplifies secret retrieval within your function code.

Granular Access Control with Access Policies

A key strength of Key Vault is its ability to enforce access policies at a granular level. You can define precisely which applications or users have permissions (e.g., “get,” “list,” “set”) to specific secrets. For instance, an order processing function might only have “get” permission for a Stripe API key, preventing accidental modification or deletion.

3. Managed Identities: The Secure Way to Access Key Vault

To further enhance security and simplify credential management, Managed Identities are highly recommended for Azure Functions accessing Key Vault. A Managed Identity acts as an automatically managed service principal for your Function App. It allows your function to authenticate securely with Key Vault (and other Azure services) without you needing to manually manage any secrets, connection strings, or service principal credentials in your code or App Settings. This significantly reduces your attack surface and eliminates the risk of credential leakage.

Local Development Workflow

During local development, your Azure Function needs access to configuration and potentially secrets to run correctly. The local.settings.json file serves as a local equivalent for both App Settings and Key Vault secrets. This file is designed to mimic your production environment settings, allowing for easy testing and debugging.

However, it is absolutely critical that local.settings.json is never committed to source control. Always add this file to your .gitignore (or equivalent version control exclusion file) to prevent sensitive data from accidentally being exposed in your repository.

Why Avoid Environment Variables for Production Secrets?

While environment variables can be used for local secrets, they are generally not ideal for production environments in Azure Functions, especially for sensitive data. Azure Key Vault offers a vastly superior solution by providing:

  • Centralized Secret Management: All secrets are in one secure location.
  • Robust Access Control: Granular permissions via access policies.
  • Auditing: Track who accessed which secret and when.
  • Versioning: Maintain different versions of secrets, allowing for rollback.
  • Secure Storage: Secrets are encrypted at rest and in transit, often backed by HSMs.

These features are essential for a strong security posture in production, which simple environment variables cannot provide.

Practical Code Example: Retrieving a Secret from Azure Key Vault

The following C# code demonstrates how an Azure Function can securely retrieve a secret from Azure Key Vault using Managed Identities and the Azure SDK. This approach leverages DefaultAzureCredential, which automatically handles authentication based on the environment (e.g., Managed Identity in Azure, developer credentials locally).


// Using Azure Key Vault to retrieve a secret
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.MVC;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

public static class SecretRetrievalFunction
{
    [FunctionName("GetSecretFromKeyVault")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        // Retrieve the Key Vault URI from app settings. This URI itself is not a secret.
        string keyVaultUri = Environment.GetEnvironmentVariable("KEY_VAULT_URI");

        if (string.IsNullOrEmpty(keyVaultUri))
        {
            log.LogError("KEY_VAULT_URI application setting is not configured.");
            return new BadRequestObjectResult("Key Vault URI is not configured.");
        }

        try
        {
            // Create a Key Vault client using DefaultAzureCredential.
            // This automatically handles various authentication methods, including Managed Identities
            // when deployed to Azure, or developer credentials locally.
            var client = new SecretClient(new Uri(keyVaultUri), new DefaultAzureCredential());

            // Retrieve the secret from Key Vault. Replace "MySecretName" with your actual secret name.
            KeyVaultSecret secret = await client.GetSecretAsync("MySecretName");

            string secretValue = secret.Value;

            log.LogInformation($"Successfully retrieved secret: {secretValue.Substring(0, Math.Min(secretValue.Length, 5))}..."); // Log partial for security

            return new OkObjectResult($"Secret retrieved successfully. Value starts with: {secretValue.Substring(0, Math.Min(secretValue.Length, 5))}");
        }
        catch (Exception ex)
        {
            log.LogError($"Error retrieving secret from Key Vault: {ex.Message}");
            return new StatusCodeResult(Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError);
        }
    }
}
    

Note: Ensure your Function App’s Managed Identity has “Get” permission on the specific secret in Key Vault for this code to work when deployed to Azure.

Key Takeaways & Best Practices

To summarize the most crucial points for managing secrets and configuration in Azure Functions:

  • Distinguish Clearly: Always differentiate between non-sensitive configuration settings and sensitive secrets.
  • Prioritize Key Vault for Secrets: Azure Key Vault is the definitive solution for storing all sensitive data. Never hardcode secrets directly into your code or store them in plain text in App Settings.
  • Leverage Managed Identities: Use Managed Identities for your Function Apps to securely authenticate with Key Vault, eliminating the need to manage credentials.
  • Secure Local Development: Utilize local.settings.json for local testing, but ensure it is strictly excluded from source control via .gitignore.
  • Avoid Production Environment Variables for Secrets: While convenient locally, environment variables lack the robust security, auditing, and management features of Key Vault for production secrets.
  • Implement Least Privilege: Grant your Function Apps only the necessary permissions (e.g., “get” on specific secrets) in Key Vault access policies.
  • Regularly Review: Periodically review your App Settings, Key Vault access policies, and code for any accidental exposure of sensitive information.