Microsoft Azure logo Quarkus Azure Services Extensions

Quarkus Azure App Configuration 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 App Configuration is a fast, scalable parameter storage for app configuration. This extension allows to inject a io.smallrye.config.SmallRyeConfig object inside your Quarkus application so you can access the app configuration stored in Azure.

Installation

If you want to use this extension, you need to add the io.quarkiverse.azureservices:quarkus-azure-app-configuration 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-app-configuration</artifactId>
    <version>1.1.0</version>
</dependency>

How to Use It

Once you have added the extension to your project, follow the next steps, so you can inject io.smallrye.config.SmallRyeConfig object in your application to store and read blobs.

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-app-configuration \
    --location eastus

Create an Azure App Configuration store with the following command:

az appconfig create \
    --name appcs-quarkus-azure-app-configuration \
    --resource-group rg-quarkus-azure-app-configuration \
    --location eastus

Then create some key-value properties with the following commands:

az appconfig kv set --name appcs-quarkus-azure-app-configuration --yes --key myKeyOne --value "Value 1"
az appconfig kv set --name appcs-quarkus-azure-app-configuration --yes --key myKeyTwo --value "Value 2"

You can list the key-value properties with the following command:

az appconfig kv list --name appcs-quarkus-azure-app-configuration

If you log into the Azure portal, you can see the resource group and the key-value you created.

Azure Portal showing the app configuration

Configure the Azure App Configuration Client

As you can see below in the Configuration Reference section, the property quarkus.azure.app.configuration.endpoint is required if the extension is enabled.

For that, execute the following Azure CLI command:

export QUARKUS_AZURE_APP_CONFIGURATION_ENDPOINT=$(az appconfig show \
  --resource-group rg-quarkus-azure-app-configuration \
  --name appcs-quarkus-azure-app-configuration \
  --query endpoint -o tsv)

Notice that you get the endpoint and set it to environment variable QUARKUS_AZURE_APP_CONFIGURATION_ENDPOINT, instead of setting it to property quarkus.azure.app.configuration.endpoint in the application.properties file. Although technically both approaches work, using environment variable is recommended and more secure as there’s no risk of committing the connection information to source control.

To be able to connect to the Azure App Configuration that you’ve just created, you have two options to authenticate to Azure App Configuration, either with Microsoft Entra ID or access keys. The following sections describe how to authenticate with both options. For optimal security, it is recommended to use Microsoft Entra ID for authentication.

Authenticating to Azure App Configuration with Microsoft Entra ID

You can authenticate to Azure App Configuration with Microsoft Entra ID. Run the following commands to assign the App Configuration Data Reader role to the signed-in user as a Microsoft Entra identity.

# Retrieve the app configuration resource ID
APP_CONFIGURATION_RESOURCE_ID=$(az appconfig show \
    --resource-group rg-quarkus-azure-app-configuration \
    --name appcs-quarkus-azure-app-configuration \
    --query 'id' \
    --output tsv)
# Assign the "App Configuration Data Reader" role to the current signed-in identity
az role assignment create \
    --assignee $(az ad signed-in-user show --query 'id' --output tsv) \
    --role "App Configuration Data Reader" \
    --scope $APP_CONFIGURATION_RESOURCE_ID
Authenticating to Azure App Configuration with access keys

You can also authenticate to Azure App Configuration with access keys. Run the following commands to export the Azure App Configuration access keys as environment variables.

credential=$(az appconfig credential list \
    --name appcs-quarkus-azure-app-configuration \
    --resource-group rg-quarkus-azure-app-configuration \
    | jq 'map(select(.readOnly == true)) | .[0]')
export QUARKUS_AZURE_APP_CONFIGURATION_ID=$(echo "${credential}" | jq -r '.id')
export QUARKUS_AZURE_APP_CONFIGURATION_SECRET=$(echo "${credential}" | jq -r '.value')

Notice that you get the id and secret and set them to environment variables QUARKUS_AZURE_APP_CONFIGURATION_ID and QUARKUS_AZURE_APP_CONFIGURATION_SECRET, instead of setting them to properties quarkus.azure.app.configuration.id and quarkus.azure.app.configuration.secret in the application.properties file, with the similar reasons as mentioned above.

Inject the SmallRyeConfig

Now that your Azure environment is ready and that you have configured the extension, you can inject the SmallRyeConfig object in your application, so you can interact with Azure App Configuration.

@Path("/config")
@Produces(MediaType.APPLICATION_JSON)
public class ConfigResource {

  @Inject
  SmallRyeConfig config;

  @GET
  @Path("/{name}")
  public Response configValue(@PathParam("name") final String name) {
      return Response.ok(config.getConfigValue(name)).build();
  }
}

To test this sample you can run the following cURL commands after the application is started:

  • curl -X GET localhost:8080/config/myKeyOne

  • curl -X GET localhost:8080/config/myKeyTwo

Extension Configuration Reference

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

Configuration property

Type

Default

The flag to enable the app configuration. If set to false, the app configuration will be disabled

Environment variable: QUARKUS_AZURE_APP_CONFIGURATION_ENABLED

boolean

true

The endpoint of the app configuration. Required if quarkus.azure.app.configuration.enabled is set to true

Environment variable: QUARKUS_AZURE_APP_CONFIGURATION_ENDPOINT

string

The id of the app configuration. Required if quarkus.azure.app.configuration.enabled is set to true and access keys are used for authentication

Environment variable: QUARKUS_AZURE_APP_CONFIGURATION_ID

string

The secret of the app configuration. Required if quarkus.azure.app.configuration.enabled is set to true and access keys are used for authentication

Environment variable: QUARKUS_AZURE_APP_CONFIGURATION_SECRET

string

The label filter of the app configuration. Use comma as separator for multiple label names

Environment variable: QUARKUS_AZURE_APP_CONFIGURATION_LABELS

string

Quarkus Azure Cosmos DB 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 Cosmos DB is a fully managed NoSQL, relational, and vector database. This extension allows you to do the full set of data manipulations supported by Azure Cosmos DB by injecting a com.azure.cosmos.CosmosClient or com.azure.cosmos.CosmosAsyncClient object inside your Quarkus application.

This is a step by step guide on how to use the Quarkus Azure Cosmos DB extension. If you’re looking for a complete code sample, you can find it in the Azure Cosmos DB sample.

Installation

Add a dependncy on io.quarkiverse.azureservices:quarkus-azure-cosmos.

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

<dependency>
    <groupId>io.quarkiverse.azureservices</groupId>
    <artifactId>quarkus-azure-cosmos</artifactId>
    <version>1.1.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.cosmos.CosmosClient or com.azure.cosmos.CosmosAsyncClient object in your application to read/write items from/to the specified database and container.

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-cosmos \
    --location westus

Create an Azure Cosmos DB account with the following command:

az cosmosdb create \
    -n kvquarkusazurecosmos080824 \
    -g rg-quarkus-azure-cosmos \
    --default-consistency-level Session \
    --locations regionName='West US' failoverPriority=0 isZoneRedundant=False

If you log into the Azure portal, you can see the resource group and the Azure Cosmos DB account you created.

Azure Portal showing the Azure Cosmos DB account

Run the following commands to create a database demodb and a container democontainer using Azure CLI.

az cosmosdb sql database create \
    -a kvquarkusazurecosmos080824 \
    -g rg-quarkus-azure-cosmos \
    -n demodb
az cosmosdb sql container create \
    -a kvquarkusazurecosmos080824 \
    -g rg-quarkus-azure-cosmos \
    -d demodb \
    -n democontainer \
    -p "/id"

Configure the Azure Cosmos DB Client

As you can see below in the Extension Configuration Reference section, the property quarkus.azure.cosmos.endpoint is required if the extension is enabled. To get the endpoint of the Azure Cosmos DB account, execute the following Azure CLI command:

export QUARKUS_AZURE_COSMOS_ENDPOINT=$(az cosmosdb show \
    -n kvquarkusazurecosmos080824 \
    -g rg-quarkus-azure-cosmos \
    --query documentEndpoint -o tsv)
echo "QUARKUS_AZURE_COSMOS_ENDPOINT is: ${QUARKUS_AZURE_COSMOS_ENDPOINT}"

Because Quarkus implements the MicroProfile Config specification, the value of the environment variable QUARKUS_AZURE_COSMOS_ENDPOINT is read as if the property quarkus.azure.cosmos.endpoint were set in the application.properties file.

Although technically both approaches work, using environment variable is recommended as it won’t hardcode the configuration in the source code, making it easier to switch between environments and to avoid committing sensitive information to source control.

You have two options to authenticate to Azure Cosmos DB, either with Microsoft Entra ID or key-based authentication. The following sections describe how to authenticate with both options. For optimal security, it is recommended to use Microsoft Entra ID for authentication.

Authenticating to Azure Cosmos DB with Microsoft Entra ID

You can authenticate to Azure Cosmos DB with Microsoft Entra ID. Run the following commands to assign the Cosmos DB Built-in Data Contributor role to the signed-in user as a Microsoft Entra identity.

az ad signed-in-user show --query id -o tsv \
    | az cosmosdb sql role assignment create \
    --account-name kvquarkusazurecosmos080824 \
    --resource-group rg-quarkus-azure-cosmos \
    --scope "/" \
    --principal-id @- \
    --role-definition-id 00000000-0000-0000-0000-000000000002

Notice that you cannot use any Azure Cosmos DB data plane SDK to authenticate management operations with a Microsoft Entra identity, that’s why you created database and container manually before.

Authenticating to Azure Cosmos DB with key-based authentication

You can also authenticate to Azure Cosmos DB with key-based authentication. Run the following commands to export the key of the Azure Cosmos DB account as an environment variable.

export QUARKUS_AZURE_COSMOS_KEY=$(az cosmosdb keys list \
    -n kvquarkusazurecosmos080824 \
    -g rg-quarkus-azure-cosmos \
    --query primaryMasterKey -o tsv)

The value of environment variable QUARKUS_AZURE_COSMOS_KEY will be read by Quarkus as the value of config property quarkus.azure.cosmos.key of azure-cosmos extension in order to set up the connection to the Azure Cosmos DB.

Notice that you do not need to create a database and container manually if you use key-based authentication, because it has full access to the Azure Cosmos DB account. The database and container were created before because the sample code assumes that they exist.

Inject the Azure Cosmos DB Client

Now that your Azure environment is ready and you have configured the extension, you can @Inject the com.azure.cosmos.CosmosClient object in your imperative application or @Inject the com.azure.cosmos.CosmosAsyncClient object in your reactive application, so you can interact with Azure Cosmos DB. For complete API see the Azure SDK for Java Reference Documentation.

Use the CosmosClient in an imperative application

The createItem method first creates the item with request payload in the specified database and container of the Azure Cosmos DB account. The getItem method reads the item with the id from the specified database and container of the Azure Cosmos DB account.

@Path("/quarkus-azure-cosmos")
@ApplicationScoped
public class CosmosResource {

    @Inject
    CosmosClient cosmosClient;

    @Path("/{database}/{container}")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createItem(
            @PathParam("database") String database,
            @PathParam("container") String container,
            Item body,
            @Context UriInfo uriInfo) {

        cosmosClient.getDatabase(database).getContainer(container).upsertItem(body);
        return Response.created(uriInfo.getAbsolutePathBuilder().path(body.getId()).build()).build();
    }

    @Path("/{database}/{container}/{itemId}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getItem(
            @PathParam("database") String database,
            @PathParam("container") String container,
            @PathParam("itemId") String itemId) {
        CosmosItemResponse<Item> item = cosmosClient.getDatabase(database).getContainer(container).readItem(itemId, new PartitionKey(itemId),
                Item.class);

        return Response.ok().entity(item.getItem()).build();
    }
}

To test this sample you can run the following cURL commands after the application is started:

You can go back to the Azure portal, open Data Explorer of the Azure Cosmos DB account, and see the item that you’ve created.

Azure Portal showing the content of item created with the CosmosClient object
Use the CosmosAsyncClient in a reactive application

Similarly, the createItem method first asynchronously creates the item with request payload in the specified database and container of the Azure Cosmos DB account. The getItem method asynchronously reads the item with the id from the specified database and container of the Azure Cosmos DB account. The sample makes heavy use of Project Reactor. For more information see Reactor Reference Guide.

@Path("/quarkus-azure-cosmos-async")
@ApplicationScoped
public class CosmosAsyncResource {

    @Inject
    CosmosAsyncClient cosmosAsyncClient;

    @Path("/{database}/{container}")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Uni<Response> createItem(
            @PathParam("database") String database,
            @PathParam("container") String container,
            Item body,
            @Context UriInfo uriInfo) {

        Mono<CosmosItemResponse<Item>> response = cosmosAsyncClient.getDatabase(database).getContainer(container).upsertItem(body);
        return Uni.createFrom().completionStage(response.toFuture())
                .map(it -> Response.created(uriInfo.getAbsolutePathBuilder().path(body.getId()).build()).build());
    }

    @Path("/{database}/{container}/{itemId}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Response> getItem(
            @PathParam("database") String database,
            @PathParam("container") String container,
            @PathParam("itemId") String itemId) {
        Mono<CosmosItemResponse<Item>> item = cosmosAsyncClient.getDatabase(database).getContainer(container).readItem(itemId, new PartitionKey(itemId), Item.class);
        return Uni.createFrom().completionStage(item.toFuture())
                .map(it -> Response.ok().entity(it.getItem()).build());

    }
}

To test this sample you can run the following cURL commands after the application is started:

You can go back to the Azure portal, open Data Explorer of the Azure Cosmos DB account, and see the item that you’ve created.

Azure Portal showing the content of item created with the CosmosAsyncClient object

Extension Configuration Reference

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

Configuration property

Type

Default

The flag to enable the cosmos. If set to false, the cosmos will be disabled

Environment variable: QUARKUS_AZURE_COSMOS_ENABLED

boolean

true

The endpoint of Azure Cosmos DB. Required if quarkus.azure.cosmos.enabled is set to true

Environment variable: QUARKUS_AZURE_COSMOS_ENDPOINT

string

The key of Azure Cosmos DB. Optional and can be empty if the Azure Identity is used to authenticate

Environment variable: QUARKUS_AZURE_COSMOS_KEY

string

Quarkus Azure Event Hubs 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 Event Hubs is a big data streaming platform and event ingestion service. It can receive and process millions of events per second. This extension allows you to produce and consume events from Azure Event Hubs by injecting com.azure.messaging.eventhubs.EventHubProducerClient, com.azure.messaging.eventhubs.EventHubConsumerClient, com.azure.messaging.eventhubs.EventHubProducerAsyncClient, and com.azure.messaging.eventhubs.EventHubConsumerAsyncClient objects in your Quarkus application.

This is a step by step guide on how to use the Quarkus Azure Event Hubs extension wity sync clients. . If you’re looking for a complete code sample, you can find it in the Azure Event Hubs sample.

Installation

Add a dependncy on io.quarkiverse.azureservices:quarkus-azure-eventhubs.

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

<dependency>
    <groupId>io.quarkiverse.azureservices</groupId>
    <artifactId>quarkus-azure-eventhubs</artifactId>
    <version>1.1.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.messaging.eventhubs.EventHubProducerClient or com.azure.messaging.eventhubs.EventHubConsumerClient object in your application to produce and consume events from Azure Event Hubs.

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-eventhubs \
    --location westus

Create an Azure Event Hubs namespace with the following command:

az eventhubs namespace create \
    --name ehnamespace20241217 \
    --resource-group rg-quarkus-azure-eventhubs
az eventhubs eventhub create \
    --name eventhub1217 \
    --namespace-name ${EVENTHUBS_NAMESPACE} \
    --resource-group rg-quarkus-azure-eventhubs \
    --partition-count 2

If you log into the Azure portal, you can see the resource group and the Azure Event Hubs namespace you created.

Next, assign the Azure Event Hubs Data Owner role to the signed-in user, so that the sample application can do data plane operations.

EVENTHUBS_EVENTHUB_RESOURCE_ID=$(az eventhubs eventhub show \
    --resource-group rg-quarkus-azure-eventhubs \
    --namespace-name ehnamespace20241217 \
    --name eventhub1217 \
    --query 'id' \
    --output tsv)
az role assignment create \
    --role "Azure Event Hubs Data Owner" \
    --assignee $(az ad signed-in-user show --query 'id' --output tsv) \
    --scope $EVENTHUBS_EVENTHUB_RESOURCE_ID

Configure the Azure Event Hubs Extension

As you can see below in the Extension Configuration Reference section, the property quarkus.azure.eventhubs.namespace and quarkus.azure.eventhubs.event-hub-name are required. Execute the following Azure CLI command to export the environment variables so that the extension can read the values.

export QUARKUS_AZURE_EVENTHUBS_NAMESPACE=${EVENTHUBS_NAMESPACE}
export QUARKUS_AZURE_EVENTHUBS_EVENTHUB_NAME=${EVENTHUBS_EVENTHUB_NAME}

Because Quarkus implements the MicroProfile Config specification, the value of the environment variables QUARKUS_AZURE_EVENTHUBS_NAMESPACE and QUARKUS_AZURE_EVENTHUBS_EVENTHUB_NAME is read as if the properties quarkus.azure.eventhubs.namespace and quarkus.azure.eventhubs.event-hub-name were set in the application.properties file.

Although technically both approaches work, using environment variable is recommended and more secure as there’s no risk of committing the connection string to source control.

Inject the Azure Event Hubs Client

Now that your Azure environment is ready and you have configured the extension, you can @Inject the com.azure.messaging.eventhubs.EventHubProducerClient object in your imperative application or @Inject the com.azure.messaging.eventhubs.EventHubConsumerClient object in your reactive application, so you can interact with Azure Event Hubs. For complete API see the Azure SDK for Java Reference Documentation.

Use the EventHubProducerClient and EventHubConsumerClient in a Quarkus application
@Path("/quarkus-azure-eventhubs")
@ApplicationScoped
public class EventhubsResource {
    private static final Logger LOGGER = LoggerFactory.getLogger(EventhubsResource.class);

    @Inject
    EventHubProducerClient producer;

    @Inject
    EventHubConsumerClient consumer;

    @Path("/publishEvents")
    @GET
    public void publishEvents() {
        List<EventData> allEvents = Arrays.asList(new EventData("Foo"), new EventData("Bar"));
        producer.send(allEvents, new SendOptions().setPartitionId("0"));
    }

    @Path("/consumeEvents")
    @GET
    public void consumeEvents() {

        LOGGER.info("Receiving message using Event Hub consumer client.");
        String PARTITION_ID = "0";
        // Reads events from partition '0' and returns the first 2 received.
        IterableStream<PartitionEvent> events = consumer.receiveFromPartition(PARTITION_ID, 2,
                EventPosition.earliest());

        for (PartitionEvent partitionEvent : events) {
            // For each event, perform some sort of processing.
            LOGGER.info("Message Body received: " + partitionEvent.getData().getBodyAsString());
            LOGGER.info("Message SequenceNumber is: " + partitionEvent.getData().getSequenceNumber());
        }
    }
}

To test this sample you can run the following cURL commands after the application is started:

You should see similar output in the logs:

Message Body received: Foo
Message SequenceNumber is: 0
Message Body received: Bar
Message SequenceNumber is: 1

Extension Configuration Reference

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

Configuration property

Type

Default

The flag to enable the eventhubs. If set to false, the eventhubs will be disabled

Environment variable: QUARKUS_AZURE_EVENTHUBS_ENABLED

boolean

true

The namespace of the event hub. Required if quarkus.azure.eventhubs.enabled is set to true

Environment variable: QUARKUS_AZURE_EVENTHUBS_NAMESPACE

string

The domain name of the event hub. Required if quarkus.azure.eventhubs.enabled is set to true

Environment variable: QUARKUS_AZURE_EVENTHUBS_DOMAIN_NAME

string

servicebus.windows.net

The name of the event hub. Required if quarkus.azure.eventhubs.enabled is set to true

Environment variable: QUARKUS_AZURE_EVENTHUBS_EVENTHUB_NAME

string

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.1.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 @-

Extension Configuration Reference

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

Configuration property

Type

Default

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

Quarkus Azure Blob Storage 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 Blob Storage is a massively scalable and secure object storage for cloud-native workloads, archives, data lakes, high-performance computing, and machine learning. This extension allows you to store and retrieve blobs from Azure Blob Storage by injecting a com.azure.storage.blob.BlobServiceClient or com.azure.storage.blob.BlobServiceAsyncClient object inside your Quarkus application.

This is a step by step guide on how to use the Quarkus Azure Blob Storage extension. If you’re looking for a complete code sample, you can find it in the Azure Blob Storage sample.

Installation

If you want to use this extension, you need to add the io.quarkiverse.azureservices:quarkus-azure-storage-blob 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-storage-blob</artifactId>
    <version>1.1.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.storage.blob.BlobServiceClient or com.azure.storage.blob.BlobServiceAsyncClient object in your application to store and read blobs.

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-storage-blob \
    --location eastus

Create a general-purpose storage account with the following command:

az storage account create \
    --name stquarkusazurestorageblo \
    --resource-group rg-quarkus-azure-storage-blob \
    --location eastus \
    --sku Standard_ZRS \
    --encryption-services blob

If you log into the Azure portal, you can see the resource group and the storage account you created.

Azure Portal showing the Azure storage account

Blobs are always uploaded into a container. You can organize groups of blobs in containers similar to the way you organize your files on your computer in folders. This guide will use the Azure Storage Blob client to create the container if it doesn’t exist. Alternatively, follow instructions in Create a container if you want to create a container before uploading blobs.

Configure the Azure Storage Blob Client

As you can see below in the Configuration Reference section, either the property quarkus.azure.storage.blob.endpoint or the property quarkus.azure.storage.blob.connection-string is required if the extension is enabled.

You have two options to authenticate to Azure Storage Blob, either with Microsoft Entra ID or connection string. The following sections describe how to authenticate with both options. For optimal security, it is recommended to use Microsoft Entra ID for authentication.

Authenticating to Azure Storage Blob with Microsoft Entra ID

You can authenticate to Azure Storage Blob with Microsoft Entra ID. Run the following commands to assign the Storage Blob Data Contributor role to the signed-in user as a Microsoft Entra identity.

# Retrieve the storage account resource ID
STORAGE_ACCOUNT_RESOURCE_ID=$(az storage account show \
    --resource-group rg-quarkus-azure-storage-blob \
    --name stquarkusazurestorageblo \
    --query 'id' \
    --output tsv)
# Assign the "Storage Blob Data Contributor" role to the current signed-in identity
az role assignment create \
    --assignee $(az ad signed-in-user show --query 'id' --output tsv) \
    --role "Storage Blob Data Contributor" \
    --scope $STORAGE_ACCOUNT_RESOURCE_ID

Then, export Azure Storage Blob endpoint as an environment variable.

export QUARKUS_AZURE_STORAGE_BLOB_ENDPOINT=$(az storage account show \
    --resource-group rg-quarkus-azure-storage-blob \
    --name stquarkusazurestorageblo \
    --query 'primaryEndpoints.blob' \
    --output tsv)
echo "QUARKUS_AZURE_STORAGE_BLOB_ENDPOINT is: ${QUARKUS_AZURE_STORAGE_BLOB_ENDPOINT}"

The value of environment variable QUARKUS_AZURE_STORAGE_BLOB_ENDPOINT will be read by Quarkus as the value of config property quarkus.azure.storage.blob.endpoint in order to set up the connection to the Azure Storage Blob.

Authenticating to Azure Storage Blob with connection string

You can also authenticate to Azure Storage Blob with connection string. Run the following commands to export the Azure Storage Blob connection string as an environment variable.

export QUARKUS_AZURE_STORAGE_BLOB_CONNECTION_STRING=$(az storage account show-connection-string \
    --resource-group rg-quarkus-azure-storage-blob \
    --name stquarkusazurestorageblo \
    --output tsv)
echo "QUARKUS_AZURE_STORAGE_BLOB_CONNECTION_STRING is: ${QUARKUS_AZURE_STORAGE_BLOB_CONNECTION_STRING}"

The value of environment variable QUARKUS_AZURE_STORAGE_BLOB_CONNECTION_STRING will be fed into config property quarkus.azure.storage.blob.connection-string in order to set up the connection to the Azure Storage Blob.

Notice that you get the connection string and set it to environment variable QUARKUS_AZURE_STORAGE_BLOB_CONNECTION_STRING, instead of setting it to property quarkus.azure.storage.blob.connection-string in the application.properties file.

Although technically both approaches work, using environment variable is recommended and more secure as there’s no risk of committing the connection string to source control.

Inject the Azure Storage Blob Client

Now that your Azure environment is ready and that you have configured the extension, you can inject the com.azure.storage.blob.BlobServiceClient object in your imperative application or inject the com.azure.storage.blob.BlobServiceAsyncClient object in your reactive application, so you can interact with Azure Blob Storage.

Use the BlobServiceClient in an imperative application

The uploadBlob method first creates the container container-quarkus-azure-storage-blob, sets some text to a text file, and then uploads the text to the container. The downloadBlob method downloads the text file from the container and prints the text to the console.

@Path("/quarkus-azure-storage-blob")
@ApplicationScoped
public class StorageBlobResource {

    @Inject
    BlobServiceClient blobServiceClient;

    @POST
    public Response uploadBlob() {
        BlobContainerClient blobContainerClient = blobServiceClient
                .createBlobContainerIfNotExists("container-quarkus-azure-storage-blob");
        BlobClient blobClient = blobContainerClient.getBlobClient("quarkus-azure-storage-blob.txt");
        blobClient.upload(BinaryData.fromString("Hello quarkus-azure-storage-blob at " + LocalDateTime.now()), true);

        return Response.status(CREATED).build();
    }

    @GET
    public String downloadBlob() {
        BlobContainerClient blobContainerClient = blobServiceClient
                .getBlobContainerClient("container-quarkus-azure-storage-blob");
        BlobClient blobClient = blobContainerClient.getBlobClient("quarkus-azure-storage-blob.txt");

        return blobClient.downloadContent().toString();
    }
}

To test this sample you can run the following cURL commands after the application is started:

  • curl -X POST localhost:8080/quarkus-azure-storage-blob

  • curl localhost:8080/quarkus-azure-storage-blob

You can go back to the Azure portal and see the container container-quarkus-azure-storage-blob and the blob quarkus-azure-storage-blob.txt that you’ve created.

Azure Portal showing the content of the file uploaded with the BlobServiceClient object
Use the BlobServiceAsyncClient in a reactive application

Similarly, the uploadBlob method first asynchronously creates the container container-quarkus-azure-storage-blob-async, sets some text to a text file, and then uploads the text to the container. The downloadBlob method asynchronously downloads the text file from the container and prints the text to the console.

@Path("/quarkus-azure-storage-blob-async")
@ApplicationScoped
public class StorageBlobAsyncResource {

    @Inject
    BlobServiceAsyncClient blobServiceAsyncClient;

    @POST
    public Uni<Response> uploadBlob() {
        Mono<BlockBlobItem> blockBlobItem = blobServiceAsyncClient
                .createBlobContainerIfNotExists("container-quarkus-azure-storage-blob-async")
                .map(it -> it.getBlobAsyncClient("quarkus-azure-storage-blob-async.txt"))
                .flatMap(it -> it.upload(BinaryData.fromString("Hello quarkus-azure-storage-blob-async at " + LocalDateTime.now()), true));

        return Uni.createFrom().completionStage(blockBlobItem.toFuture()).map(it -> Response.status(CREATED).build());
    }

    @GET
    public Uni<Response> downloadBlob() {
        BlobAsyncClient blobAsyncClient = blobServiceAsyncClient.getBlobContainerAsyncClient("container-quarkus-azure-storage-blob-async")
                .getBlobAsyncClient("quarkus-azure-storage-blob-async.txt");

        return Uni.createFrom()
                .completionStage(blobAsyncClient.downloadContent().map(it -> Response.ok().entity(it.toString()).build())
                        .toFuture());
    }
}

To test this sample you can run the following cURL commands after the application is started:

  • curl -X POST localhost:8080/quarkus-azure-storage-blob-async

  • curl localhost:8080/quarkus-azure-storage-blob-async

You can also go back to the Azure portal and see the container container-quarkus-azure-storage-blob-async and the blob quarkus-azure-storage-blob-async.txt that you’ve created.

Azure Portal showing the content of the file uploaded with the BlobServiceAsyncClient object

Extension Configuration Reference

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

Configuration property

Type

Default

Whether a health check is published in case the smallrye-health extension is present.

Environment variable: QUARKUS_AZURE_STORAGE_BLOB_HEALTH_ENABLED

boolean

true

If DevServices has been explicitly enabled or disabled. DevServices is generally enabled by default, unless there is an existing configuration present.

When DevServices is enabled Quarkus will attempt to automatically configure and start an azurite instance when running in Dev or Test mode and when Docker is running.

Environment variable: QUARKUS_AZURE_STORAGE_BLOB_DEVSERVICES_ENABLED

boolean

true

The container image name to use, for container based DevServices providers.

Environment variable: QUARKUS_AZURE_STORAGE_BLOB_DEVSERVICES_IMAGE_NAME

string

mcr.microsoft.com/azure-storage/azurite:3.33.0

Optional fixed port the Dev services will listen to.

If not defined, the port will be chosen randomly.

Environment variable: QUARKUS_AZURE_STORAGE_BLOB_DEVSERVICES_PORT

int

Indicates if the azurite instance managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. If a matching container is found, it is used, and so a second one is not started. Otherwise, Dev Services for Azure Storage Blob starts a new container.

The discovery uses the quarkus-dev-service-azure-storage-blob label. The value is configured using the service-name property.

Container sharing is only used in dev mode.

Environment variable: QUARKUS_AZURE_STORAGE_BLOB_DEVSERVICES_SHARED

boolean

true

The value of the quarkus-dev-service-azure-storage-blob label attached to the started container. This property is used when shared is set to true. In this case, before starting a container, Dev Services for Azure Storage Blob looks for a container with the quarkus-dev-service-azure-storage-blob label set to the configured value. If found, it will use this container instead of starting a new one. Otherwise it starts a new container with the quarkus-dev-service-azure-storage-blob label set to the specified value.

This property is used when you need multiple shared azurite instances.

Environment variable: QUARKUS_AZURE_STORAGE_BLOB_DEVSERVICES_SERVICE_NAME

string

default-storage-blob

The flag to enable the storage blob. If set to false, the storage blob will be disabled

Environment variable: QUARKUS_AZURE_STORAGE_BLOB_ENABLED

boolean

true

The endpoint of Azure Storage Blob. Required if quarkus.azure.storage.blob.enabled is set to true and quarkus.azure.storage.blob.connection-string is not set

Environment variable: QUARKUS_AZURE_STORAGE_BLOB_ENDPOINT

string

The connection string of Azure Storage Blob. Required if quarkus.azure.storage.blob.enabled is set to true and quarkus.azure.storage.blob.endpoint is not set

Environment variable: QUARKUS_AZURE_STORAGE_BLOB_CONNECTION_STRING

string