Skip to content

An emulator for Azure Key Vault. Compatible with the Azure Client SDK, runnable with Docker or .NET Aspire.

License

Notifications You must be signed in to change notification settings

james-gould/azure-keyvault-emulator

Azure Key Vault Emulator

Warning

The Azure Key Vault Emulator should not be used in production environments. It is not a replacement for Azure Key Vault, it just makes developing applications using Azure Key Vault much easier.

Features

  • Full Azure SDK Client support; use SecretClient, KeyClient or CertificateClient as normal.
  • Destroy all secrets between sessions, or keep a persisted database.
  • Works standalone with Docker, easy integration with .NET Aspire.
  • TestContainers Module.
  • Fully supported in all CI/CD pipelines and DevOps platforms.

You can find sample applications here or you can read the full launch blog post here!

Prerequisites

  • You'll need Docker installed, or Podman installed and configured to support Docker commands.

Running the Emulator with Docker

The setup process can be fully automated by using the installation script:

bash <(curl -fsSL https://raw.githubusercontent.com/james-gould/azure-keyvault-emulator/refs/heads/master/docs/setup.sh)

Important

If you're using Windows, use wsl -u root to execute the setup script.

Alternatively you can download a copy of setup.sh and run it locally, or read the long form, manual set up docs.

The script is interactive and will create the necessary SSL certificates, install them to your User trust store and provide the commands to run the container. Once configured, you can start the Emulator with:

docker run -d -p {host-port}:4997 -v {/host/path/to/certs}:/certs -e Persist=true jamesgoulddev/azure-keyvault-emulator:latest

A break down of the command:

Command Description Optional?
-d Runs the container in detatched mode. âś…
-p {host-port}:4997 Specifies the port to run on. The host port is configurable, but must map to container port 4997. âś…
-v {/host/path/to/certs}:/certs Binds the directory containing the SSL PFX and CRT files, required for the Azure SDK. ❌
-e Persist=true Instructs the emulator to create an SQLite database, written to your mounted volume/directory alongside the certificate files. âś…
jamesgoulddev/azure-keyvault-emulator:latest The container image name and tag. Always use latest. ❌

You can read more about configuration here.

Running the Emulator with .NET Aspire

1. Install the AzureKeyVaultEmulator.Aspire.Hosting package into your AppHost project:

dotnet add package AzureKeyVaultEmulator.Aspire.Hosting

2. Override an existing Aspire resource or directly include the AzureKeyVaultEmulator:

var keyVaultServiceName = "keyvault"; // Remember this string, you'll need it to get the vaultUri!

// With existing resource, requires Azure configuration in your AppHost
var keyVault = builder
    .AddAzureKeyVault(keyVaultServiceName)
    .RunAsEmulator(); // Add this line

// Or directly add the emulator as a resource, no configuration required
var keyVault = builder.AddAzureKeyVaultEmulator(keyVaultServiceName);

var webApi = builder
    .AddProject<Projects.MyApi>("api")
    .WithReference(keyVault); // reference as normal

You can also toggle on persisted data, which creates an emulator.db loaded at runtime and updated in real-time.

var keyVaultServiceName = "keyvault";

var keyVault = builder
    .AddAzureKeyVault(keyVaultServiceName)
    .RunAsEmulator(new KeyVaultEmulatorOptions { Persist = true }); // Add this option

Read more about configuration here.

Using The Emulator in your applications.

1. Permit requests to the Emulator using the Azure SDK:

This can be done easily by installing the AzureKeyVaultEmulator.Client package:

dotnet add package AzureKeyVaultEmulator.Client

And then inject your clients:

// Injected by Aspire using the name "keyvault".
var vaultUri = builder.Configuration.GetConnectionString("keyvault") ?? string.Empty;

// Basic Secrets only implementation
builder.Services.AddAzureKeyVaultEmulator(vaultUri);

// Or configure which clients you need to use
builder.Services.AddAzureKeyVaultEmulator(vaultUri, secrets: true, keys: true, certificates: false);

Or if you don't want to introduce a new dependency you can achieve the same behaviour with ClientOptions.

Setting up a SecretClient for example:

// Injected by Aspire using the name "keyvault".
var vaultUri = builder.Configuration.GetConnectionString("keyvault") ?? string.Empty;

// Allows "localhost" to be used instead of "<vault-name>.vault.azure.net" as the vaultUri
var options = new SecretClientOptions { DisableChallengeResourceVerification = true };

// Inject a SecretClient into your DI container which doesn't validate the VaultUri
builder.Services.AddTransient(s => new SecretClient(new Uri(vaultUri), new DefaultAzureCredential(), options));

You can use this code from the client library replacing EmulatedCredential with DefaultAzureCredential.

2. Use your AzureClients as normal dependency injected services:

private SecretClient _secretClient;

public SecretsController(SecretClient secretClient)
{
    _secretClient = secretClient;
}

public async Task<string> GetSecretValue(string name)
{
    var secret = await _secretClient.GetSecretAsync(name);

    return secret.Value;
}
Optional, if you're using the AzureKeyVaultEmulator.Client package

Configure your Program.cs to optionally inject the emulated or real Azure Key Vault clients depending on your current execution environment:

var vaultUri = builder.Configuration.GetConnectionString("keyvault") ?? string.Empty;

if(builder.Environment.IsDevelopment())
    builder.Services.AddAzureKeyVaultEmulator(vaultUri, secrets: true, certificates: true, keys: true);
else
    builder.Services.AddAzureClients(client =>
    {
        var asUri = new Uri(vaultUri);

        client.AddSecretClient(asUri);
        client.AddKeyClient(asUri);
        client.AddCertificateClient(asUri);
    });

TestContainers Module

There is a readily available TestContainers module too, which fully supports all CI/CD pipelines.

The same testing setup can be used in your local environment and CI/CD pipelines, no need to set flags or configuration.

Basic Usage

using AzureKeyVaultEmulator.TestContainers;

// Create container with certificate directory and persistence
await using var container = new AzureKeyVaultEmulatorContainer();

// Start the container
await container.StartAsync();

// Get a AzureSDK KeyClient configured for the container
var keyClient = container.GetKeyClient();

// Get a AzureSDK SecretClient configured for the container
var secretClient = container.GetSecretClient();

// Get a AzureSDK CertificateClient configured for the container
var certificateClient = container.GetCertificateClient();

// Use as normal
var secret = await secretClient.SetSecretAsync("mySecretName", "mySecretValue");

You can see more examples here for various test frameworks and scenarios.

Roadmap

The Azure Key Vault Emulator is now stable and ready for public consumption, however maintenance and enhancement work will continue to ensure the longevity of the project. Below you can find previous and upcoming additions to the project, if you'd like to see something added please raise a feature request.

Updates to the Azure Key Vault Emulator API will follow releases announced by Microsoft here.

Pending

  • Management UI, similar to the Azure Portal UI. (#195)

Completed

  • Introduction of the full API for Azure Key Vault:
    • Secrets
    • Keys
    • Certificates
    • Managed HSM
  • Separate NuGet package for introducing an emulated Key Vault into your .NET Aspire projects.
  • Separate NuGet package for easy usage of the emulator in client applications.
  • Optional vault data persistence and importing for dev environment distribution. (#196)
  • Automated environment + Docker setup script, and documentation updated to reflect it.
  • TestContainers module. (#158)

About

An emulator for Azure Key Vault. Compatible with the Azure Client SDK, runnable with Docker or .NET Aspire.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Languages