Partner – Microsoft – NPI (cat= Spring)
announcement - icon

Azure Spring Apps is a fully managed service from Microsoft (built in collaboration with VMware), focused on building and deploying Spring Boot applications on Azure Cloud without worrying about Kubernetes.

And, the Enterprise plan comes with some interesting features, such as commercial Spring runtime support, a 99.95% SLA and some deep discounts (up to 47%) when you are ready for production.

>> Learn more and deploy your first Spring Boot app to Azure.

You can also ask questions and leave feedback on the Azure Spring Apps GitHub page.

1. Overview

HashiCorp’s Vault is a tool to store and secure secrets. Vault, in general, solves the software development security problem of how to manage secrets. To learn more about it, check out our article here.

Spring Vault provides Spring abstractions to the HashiCorp’s Vault.

In this tutorial, we’ll go over an example of how to store and retrieve secrets from the Vault.

2. Maven Dependencies

To start with, let’s take a look at the dependencies we need to start working with Spring Vault:


The latest version of spring-vault-core can be found on Maven Central.

3. Configuring Vault

Let’s now go through the steps needed to configure Vault.

3.1. Creating a VaultTemplate

To secure our secrets, we’ll need an instance of the VaultTemplate class for which we need VaultEndpoint and TokenAuthentication instances:

VaultTemplate vaultTemplate = new VaultTemplate(new VaultEndpoint(), 
  new TokenAuthentication("00000000-0000-0000-0000-000000000000"));

3.2. Creating a VaultEndpoint

There’re a few ways to instantiate VaultEndpoint. Let’s take a look at some of them.

The first one is to simply instantiate it using a default constructor, which will create a default endpoint pointing to http://localhost:8200:

VaultEndpoint endpoint = new VaultEndpoint();

Another way is to create a VaultEndpoint by specifying Vault’s host and port:

VaultEndpoint endpoint = VaultEndpoint.create("host", port);

And finally, we can also create it from the Vault URL:

VaultEndpoint endpoint = VaultEndpoint.from(new URI("vault uri"));

There are a few things to notice here – Vault will be configured with a root token of 00000000-0000-0000-0000-000000000000 to run this application.

In our example, we’ve used  TokenAuthentication, but there are other authentication methods supported as well.

4. Configuring Vault Beans Using Spring

With Spring, we can configure the Vault in a couple of ways. One is by extending the AbstractVaultConfiguration, and the other one is by using EnvironmentVaultConfiguration, which makes use of Spring’s environment properties.

We’ll now go over both ways.

4.1. Using AbstractVaultConfiguration

Let’s create a class that extends AbstractVaultConfiguration, to configure Spring Vault:

public class VaultConfig extends AbstractVaultConfiguration {

    public ClientAuthentication clientAuthentication() {
        return new TokenAuthentication("00000000-0000-0000-0000-000000000000");

    public VaultEndpoint vaultEndpoint() {
        return VaultEndpoint.create("host", 8020);

This approach is similar to what we’ve seen in the previous section. What’s different is that we’ve used Spring Vault to configure Vault beans by extending the abstract class AbstractVaultConfiguration.

We just have to provide the implementation to configure VaultEndpoint and ClientAuthentication.

4.2. Using EnvironmentVaultConfiguration

We can also configure Spring Vault using the EnviromentVaultConfiguration:

@PropertySource(value = { "" })
@Import(value = EnvironmentVaultConfiguration.class)
public class VaultEnvironmentConfig {

EnvironmentVaultConfiguration makes use of Spring’s PropertySource to configure Vault beans. We just need to supply the properties file with some acceptable entries.

More information on all of the predefined properties can be found in the official documentation.

To configure the Vault, we need at least a couple of properties:


5. Securing Secrets

We’ll create a simple Credentials class that maps to username and password:

public class Credentials {

    private String username;
    private String password;
    // standard constructors, getters, setters

Now, let’s see how we can secure our Credentials object using the VaultTemplate:

Credentials credentials = new Credentials("username", "password");
VaultKeyValueOperations vaultKeyValueOperations = vaultTemplate.opsForKeyValue("credentials/myapp", 
vaultKeyValueOperations.put(credentials.getUsername(), credentials);

We must note that we used an instance of VaultKeyValueOperations as it supports both versioned and unversioned key-value backends.

Next, we’ll see how to access them.

6. Accessing Secrets

We can access the secured secrets using the get() method in VaultKeyValueOperations, which returns the VaultResponseSupport as a response:

VaultResponseSupport response = vaultKeyValueOperations.get(username, Credentials.class);
String username = response.getData().getUsername();
String password = response.getData().getPassword();

Our secret values are now ready.

7. Vault Repositories

Vault repository is a handy feature that comes with Spring Vault 2.0. It applies Spring Data’s repository concept on top of Vault.

Let’s dig deep to see how to use this new feature for unversioned key-value backends.

7.1. @Secret and @Id Annotations

Spring provides these two annotations to mark the objects we want to persist inside Vault.

So first, we need to decorate our domain type Credentials:

@Secret(backend = "credentials", value = "myapp")
public class Credentials {

    private String username;
    // Same code

The value attribute of the @Secret annotation serves to distinguish the domain type. The backend attribute denotes the secret backend mount.

On the other hand, @Id simply demarcates the identifier of our object.

7.2. Vault Repository

Now, let’s define a repository interface that uses our domain object Credentials:

public interface CredentialsRepository extends CrudRepository<Credentials, String> {

As we can see, our repository extends CrudRepository, which provides basic CRUD and query methods.

Next, let’s inject CredentialsRepository into CredentialsService and implement some CRUD methods:

public class CredentialsService {

    private final VaultTemplate vaultTemplate;
    private CredentialsRepository credentialsRepository;
    private final VaultKeyValueOperations vaultKeyValueOperations;

    public CredentialsService(VaultTemplate vaultTemplate, CredentialsRepository credentialsRepository) {
        this.vaultTemplate = vaultTemplate;
        this.credentialsRepository = credentialsRepository;
        this.vaultKeyValueOperations = vaultTemplate.opsForKeyValue("credentials/myapp", 

    public Credentials saveCredentials(Credentials credentials) {

    public Optional<Credentials> findById(String username) {
        return credentialsRepository.findById(username);

Now that we’ve added all the missing pieces of the puzzle, let’s confirm that everything works as excepted using test cases.

First, let’s start with a test case for the save() method:

public void givenCredentials_whenSave_thenReturnCredentials() throws InterruptedException {

    credentialsService = new CredentialsService(vaultTemplate, credentialsRepository);
    // Given
    Credentials credentials = new Credentials("login", "password");

    // When
    Credentials savedCredentials = credentialsService.saveCredentials(credentials);

    // Then
    assertEquals(credentials.getUsername(), savedCredentials.getUsername());
    assertEquals(credentials.getPassword(), savedCredentials.getPassword());

Lastly, let’s confirm the findById() method with a test case:

public void givenId_whenFindById_thenReturnCredentials() {
    // Given
    Credentials expectedCredentials = new Credentials("login", "p@ssw@rd");

    // When
    Optional retrievedCredentials = credentialsService.findById(expectedCredentials.getUsername());

    // Then
    assertEquals(expectedCredentials.get().getUsername(), retrievedCredentials.getUsername());
    assertEquals(expectedCredentials.getPassword(), retrievedCredentials.get().getPassword());

We must note that we use the CredentialsRepository only for the unversioned (“v1“) key-value backend.

8. Conclusion

In this article, we’ve learned about the basics of Spring Vault with an example showing how the Vault works in typical scenarios.

As usual, the source code presented here can be found over on GitHub.

Course – LS (cat=Spring)

Get started with Spring and Spring Boot, through the Learn Spring course:

Course – LSS (cat=Security/Spring Security)

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security:

res – Security (video) (cat=Security/Spring Security)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.