Quarkus Azure Key Vault Extension

Quarkus Azure Services Extensions are developed and supported by Microsoft as part of their commitment to Open Standard Enterprise Java. For more information, see Jakarta EE on Azure.

Azure Key Vault is a cloud service for securely storing and accessing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, certificates, or cryptographic keys. This extension allows you to:

  • Create and retrieve secrets from Azure Key Vault by injecting the one or both of the following objects in a Quarkus application.

    • com.azure.security.keyvault.secrets.SecretClient

    • com.azure.security.keyvault.secrets.SecretAsyncClient

  • Use secrets from the key vault directly inside your application.properties.

The extension produces SecretClient and SecretAsyncClient using DefaultAzureCredential. Developers who want more control or whose scenario isn’t served by the default settings should build their clients using other credential types.

Installation

Add the io.quarkiverse.azureservices:quarkus-azure-keyvault extension first to your build file.

For instance, with Maven, add the following dependency to your POM file:

<dependency>
    <groupId>io.quarkiverse.azureservices</groupId>
    <artifactId>quarkus-azure-keyvault</artifactId>
    <version>1.2.0</version>
</dependency>

How to Use It

Once you have added the extension to your project, follow the next steps, so you can inject com.azure.security.keyvault.secrets.SecretClient or com.azure.security.keyvault.secrets.SecretAsyncClient in your application to manage secrets.

Setup your Azure Environment

First thing first. For this sample to work, you need to have an Azure account as well as Azure CLI installed. The Azure CLI is available to install in Windows, macOS and GNU/Linux environments. Checkout the installation guide. Then, you need an Azure subscription and log into it by using the az login command. You can run az version to find the version and az upgrade to upgrade to the latest version.

Create an Azure resource group with the az group create command. A resource group is a logical container into which Azure resources are deployed and managed.

az group create \
    --name rg-quarkus-azure-keyvault \
    --location eastus

Create a general-purpose key vault with the following command:

az keyvault create --name kvquarkusazurekv0423 \
    --resource-group rg-quarkus-azure-keyvault \
    --location eastus \
    --enable-rbac-authorization false

Key Vault provides secure storage of generic secrets, such as passwords and database connection strings. All secrets in your key vault are stored encrypted. The Azure Key Vault service encrypts your secrets when you add them, and decrypts them automatically when you read them.

The command creating key vault has assigned all secret permissions(backup, delete, get, list, purge, recover, restore, set) to your signed in identity:

Create a secret secret1 with value mysecret.

az keyvault secret set \
    --vault-name kvquarkusazurekv0423 \
    --name secret1 \
    --value mysecret

If you sign into the Azure portal, you can see the key vault you created. Select ObjectsSecrets, you will find the Secrets page.

Azure Portal showing Key Vault Secrets

Configure the Azure Key Vault Secret Client

As you can see below in the Configuration Reference section, the configuration option quarkus.azure.keyvault.secret.endpoint is mandatory. To get the endpoint, execute the following Azure CLI command:

export QUARKUS_AZURE_KEYVAULT_SECRET_ENDPOINT=$(az keyvault show --name kvquarkusazurekv0423 \
    --resource-group rg-quarkus-azure-keyvault \
    --query properties.vaultUri \
    --output tsv)

Notice that you get the endpoint and set it to environment variable QUARKUS_AZURE_KEYVAULT_SECRET_ENDPOINT, instead of setting it to property quarkus.azure.keyvault.secret.endpoint in the application.properties file.

Due to Quarkus implementing the MicroProfile Config specification, both approaches work. Using the environment variable is recommended, more flexible and more secure as there’s no risk of committing the endpoint to source control.

Read Secrets as Properties

You can load and reference secrets from Azure Key Vault in your application.properties file by using the following syntax. A hierarchical approach is supported, similar to that found in Google Cloud Secret Manager.

The syntax supports loading secrets from multiple key vault. Default key vault is configed with quarkus.azure.keyvault.secret.endpoint.

# 1. Load secret from default key vault  - specify the secret name and use the latest version
${kv//<secret-name>}

# 2. Load secret from default key vault - specify the secret name and version
${kv//<secret-name>/versions/<version-id>}

# 3. Load secret from a specified key vault - specify key vault name, secret name, and use latest version
${kv//<keyvault-name>/<secret-name>}

# 4. Load secret from a specified key vault - specify key vault name, secret name, and use latest version
${kv//<keyvault-name>/secrets/<secret-name>}

# 5. Load secret from a specified key vault - specify key vault name, secret name, and version
${kv//<keyvault-name>/secrets/<secret-name>/<version-id>}

# 6. Load secret from a specified key vault - specify key vault name, secret name, and version
${kv//<keyvault-name>/secret/<secret-name>/versions/<version-id>}

You can use this syntax to load secrets directly from application.properties:

@ConfigProperty(name = "kv//secret1")
String secret;

Inject the Azure Key Vault Secret Client

Now that your Azure environment is ready and that you have configured the extension, you can inject the com.azure.security.keyvault.secrets.SecretClient object in your application, so you can interact with Azure Key Vault Secret.

This is a Quarkus CLI application. The application will:

  • Ask for a secret value.

  • Create a secret with name mySecret and set its value.

  • Retrieve and print the secret value.

  • Delete the secret.

You can build and run the application in development mode using command:

quarkus dev
@QuarkusMain
public class KeyVaultSecretApplication implements QuarkusApplication {

    @Inject
    SecretClient secretClient;

    @ConfigProperty(name = "kv//secret1")
    String secret;

    @Override
    public int run(String... args) throws Exception {

        System.out.println("Print secret1: " + secret);

        Console con = System.console();

        String secretName = "mySecret";
        System.out.println("Create secret: " + secretName);

        System.out.println("Please provide the value of your secret > ");

        String secretValue = con.readLine();

        System.out.println("Creating a secret called '" + secretName + "' with value '" + secretValue + "' ... ");

        secretClient.setSecret(new KeyVaultSecret(secretName, secretValue));

        System.out.println("Retrieving your secret...");

        KeyVaultSecret retrievedSecret = secretClient.getSecret(secretName);

        System.out.println("Your secret's value is '" + retrievedSecret.getValue() + "'.");
        System.out.println("Deleting your secret ... ");

        SyncPoller<DeletedSecret, Void> deletionPoller = secretClient.beginDeleteSecret(secretName);
        deletionPoller.waitForCompletion();

        System.out.println("done.");
        return 0;
    }
}

After running the application, if you log into the Azure portal, you can see the key vault and the secret you created. As the secret is deleted, you will find the secret from ObjectsSecretsManage deleted secrets.

Azure Portal showing the deleted secrets

You can also inject com.azure.security.keyvault.secrets.SecretAsyncClient object to your application. For more usage, see com.azure.security.keyvault.secrets.secretasyncclient.

After the testing, for security consideration, you can rotate the policy with command:

az ad signed-in-user show --query id -o tsv \
    | az keyvault delete-policy \
    --name kvquarkusazurekv0423 \
    --object-id @-

Dev Service

The Dev Service of this extension launch an Lowkey Vault emulator in dev and test mode.

The SecretClient and SecretAsyncClient instances produced by this extension will be automatically configured to use the emulator’s connection string when running in dev or test mode through the quarkus.azure.keyvault.secret.endpoint property.

Prerequisites for Managed Identity simulation

The credentials used by the aforementioned clients will be also automatically configured based on the existence of the properties under quarkus.azure.keyvault.secret.local-configuration.basic-authentication. This can be disabled by setting the quarkus.azure.keyvault.devservices.managed-identity.token-port property in the Dev Service configuration. Setting the port number explicitly will switch authentication to use a simulated Azure Managed Identity token endpoint.

In order to make managed identity work, you must explicitly set the following environment variables:

  1. IDENTITY_ENDPOINT=http://localhost:<token_port>/metadata/identity/oauth2/token where the <token_port> placeholder must match the token port of the Dev Service configuration.

  2. IDENTITY_HEADER=header

Pre-populate the Key Vault with secrets

You can instruct the Dev Service to set secrets with pre-defined values after start-up by setting the key-value pairs of the map under the quarkus.azure.keyvault.devservices.pre-set-secrets configuration property.

For example:

quarkus.azure.keyvault.devservices.pre-set-secrets.secret1=value1
quarkus.azure.keyvault.devservices.pre-set-secrets.secret2=value2

Disable the Dev Service

The Dev Service will not start under any of these conditions:

  • The Dev Service is explicitly disabled with quarkus.azure.keyvault.devservices.enabled=false

  • Global Dev Service is disabled with quarkus.devservices.enabled=false

Extension Configuration Reference

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property

Type

Default

If Dev Services for Azure Key Vault has been explicitly enabled or disabled.

Environment variable: QUARKUS_AZURE_KEYVAULT_DEVSERVICES_ENABLED

boolean

true

The container image name of Lowkey Vault. See the artifact registry for available tags of the default image.

This extension has been tested and verified working with version nagyesta/lowkey-vault:4.0.0-ubi9-minimal.

Environment variable: QUARKUS_AZURE_KEYVAULT_DEVSERVICES_IMAGE_NAME

string

nagyesta/lowkey-vault:4.0.0-ubi9-minimal

Specify the token port for the managed identity server.

Environment variable: QUARKUS_AZURE_KEYVAULT_DEVSERVICES_MANAGED_IDENTITY_TOKEN_PORT

int

0

Set to true to automatically merge the Lowkey Vault SSL keystore with the application keystore.

Environment variable: QUARKUS_AZURE_KEYVAULT_DEVSERVICES_MERGE_SSL_KEYSTORE_WITH_APPLICATION_KEYSTORE

boolean

true

A map of secret names and values to pre-set in the Lowkey Vault instance.

Environment variable: QUARKUS_AZURE_KEYVAULT_DEVSERVICES_PRE_SET_SECRETS__PRE_SET_SECRETS_

Map<String,String>

The flag to enable the key vault secret. If set to false, the key vault secret will be disabled

Environment variable: QUARKUS_AZURE_KEYVAULT_SECRET_ENABLED

boolean

true

The endpoint of Azure Key Vault Secret. Required if quarkus.azure.keyvault.secret.enabled is set to true

Environment variable: QUARKUS_AZURE_KEYVAULT_SECRET_ENDPOINT

string

The flag to disable the challenge resource verification. If set to false, the verification remains enabled.

Environment variable: QUARKUS_AZURE_KEYVAULT_SECRET_LOCAL_CONFIGURATION_DISABLE_CHALLENGE_RESOURCE_VERIFICATION

boolean

false

The username part of the basic authentication token.

Environment variable: QUARKUS_AZURE_KEYVAULT_SECRET_LOCAL_CONFIGURATION_BASIC_AUTHENTICATION_USERNAME

string

required

The password part of the basic authentication token.

Environment variable: QUARKUS_AZURE_KEYVAULT_SECRET_LOCAL_CONFIGURATION_BASIC_AUTHENTICATION_PASSWORD

string

required