Skip to content

Basis-Theory/azure-keyvault-emulator

Repository files navigation

Azure KeyVault Emulator

Version Verify

The Basis Theory Azure KeyVault Emulator to mock interactions with Azure KeyVault using the official Azure KeyVault client

Supported Operations

Keys

RSA

  • Create Key
  • Get Key
  • Get Key by Version
  • Encrypt
  • Decrypt
  • Supported Algorithms
    • RSA1_5
    • RSA-OAEP

Secrets

  • Set
  • Get Secret
  • Get Secret by Version

Requirements

HTTPS

Azure KeyClient and SecretClient require HTTPS communication with a KeyVault instance. When accessing the emulator on localhost, configure a trusted TLS certificate with dotnet dev-certs.

For accessing the emulator with a hostname other than localhost, a self-signed certificate needs to be generated and trusted by the client. See Adding to docker-compose for further instructions.

AuthN/AuthZ

Azure KeyClient and SecretClient use a ChallengeBasedAuthenticationPolicy to determine the authentication scheme used by the server. In order for the KeyVault Emulator to work with the Azure SDK, the emulator requires JWT authentication in the Authorization header with Bearer prefix. KeyVault Emulator only validates the JWT is well-formed.

curl -X 'GET' \
  'https://localhost:5551/secrets/foo' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE4OTAyMzkwMjIsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjUwMDEvIn0.bHLeGTRqjJrmIJbErE-1Azs724E5ibzvrIc-UQL6pws'

Adding to docker-compose

For the Azure KeyVault Emulator to be accessible from other containers in the same compose file, a new OpenSSL certificate has to be generated:

  1. Replace <emulator-hostname> and run the following script to generate a new public/private keypair:

    openssl req \
    -x509 \
    -newkey rsa:4096 \
    -sha256 \
    -days 3560 \
    -nodes \
    -keyout <emulator-hostname>.key \
    -out <emulator-hostname>.crt \
    -subj '/CN=<emulator-hostname>' \
    -extensions san \
    -config <( \
      echo '[req]'; \
      echo 'distinguished_name=req'; \
      echo '[san]'; \
      echo 'subjectAltName=DNS.1:localhost,DNS.2:<emulator-hostname>,DNS.3:localhost.vault.azure.net,DNS.4:<emulator-hostname>.vault.azure.net')
    
  2. Export a .pks formatted key using the public/private keypair generated in the previous step:

    openssl pkcs12 -export -out <emulator-hostname>.pfx \
    -inkey <emulator-hostname>.key \
    -in <emulator-hostname>.crt
    
  3. Trust the certificate in the login keychain

    sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <emulator-hostname>.crt
    
  4. Add a service to docker-compose.yml for Azure KeyVault Emulator:

    version: '3.9'
    
    services:
      ...
      azure-keyvault-emulator:
        image: basis-theory/azure-keyvault-emulator:latest
        hostname: <emulator-hostname>.vault.azure.net
        ports:
          - 5001:5001
          - 5000:5000
        volumes:
          - <path-to-certs>:/https
        environment:
          - ASPNETCORE_URLS=https://+:5001;http://+:5000
          - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/<emulator-hostname>.pfx
          - KeyVault__Name=<emulator-hostname>
    
  5. Modify the client application's entrypoint to add the self-signed certificate to the truststore. Example using docker-compose.yml to override the entrypoint:

    version: '3.9'
    
    services:
      my-awesome-keyvault-client:
        container_name: my-awesome-client
        build:
          context: .
        depends_on:
          - azure-keyvault-emulator
        entrypoint: sh -c "cp /https/<emulator-hostname>.crt /usr/local/share/ca-certificates/<emulator-hostname>.crt && update-ca-certificates && exec <original-entrypoint>"
        volumes:
          - <path-to-certs>:/https
        environment:
          - KeyVault__BaseUrl=https://<emulator-hostname>.vault.azure.net:5001/
    
  6. (Optional) Azure KeyVault SDKs verify the challenge resource URL as of v4.4.0 (read more here). To satisfy the new challenge resource verification requirements, do one of the following:

    1. Use an emulator hostname that ends with .vault.azure.net (e.g. localhost.vault.azure.net). A new entry may need to be added to /etc/hosts to properly resolve DNS (i.e. 127.0.0.1 localhost.vault.azure.net).
    2. Set DisableChallengeResourceVerification to true in your client options to disable verification.
var client = new SecretClient(
    new Uri("https://localhost.vault.azure.net:5551/"), 
    new LocalTokenCredential(), 
    new SecretClientOptions
    {
        DisableChallengeResourceVerification = true
    });

Development

The provided scripts will check for all dependencies, start docker, build the solution, and run all tests.

Dependencies

Build the KeyVault emulator and run Tests

Run the following command from the root of the project:

make verify