Hashicorp Vault integration with spring boot application

Hashicorp Vault integration with spring boot application

In this article, we'll learn about Hashicorp vault installation, start, access, and integration with the spring boot application.

Hashicorp Vault helps to store and retrieve tokens, passwords, certificates, and encryption keys centrally. It is a central location to store all the credentials and different applications with different platforms can access the same. As credentials are being stored centrally in the vault it helps to reduce time on secret management. Data stored in the vault are encrypted and encryption happens in memory before data is sent to backend storage, so the storage layer never accesses raw data.

In spring we do have a Vault library that helps to store and retrieve secrets from the vault.

I have included a core code snippet as part of this article, for complete code reference refer to - GITHUB

Install vault

  • Download the vault binary from VaultProject based on your operating system. Here as part of this demo, we'll use Windows.
  • Extract downloaded binary to any folder
  • Set the above vault binary path to path variable - example : D:\local\vault_1.10.2_windows_386
  • Execute the below command to verify the installation. It should display output as shown in the image. vault-version.png

Start vault

  • Start vault server in dev(default) environment. As shown in the below image, it will display a URL with an authentication token and it stores all the data in memory only so we should never use the dev environment from the vault to our actual production server. It will start in an interactive terminal so we can stop it by closing that terminal window.
     vault server -dev
    
    vault-dev-start.png

Connect vault

  • Execute commands as shown in the below image to connect the vault in a different terminal window. URL and authentication token are copied from the above step. vault-connection.png
  • Add username and password details to the vault from terminal on secret/springdemo location set-pwd-uname.png
  • Retrieve username and password from vault vault-get-uname-pwd.png

Spring boot integration

  • Create a simple spring boot web application from SpringIO
  • Add below maven dependency to interact with the vault

          <dependency>
              <groupId>org.springframework.vault</groupId>
              <artifactId>spring-vault-core</artifactId>
              <version>2.3.2</version>
          </dependency>
    
  • Add the below properties to the application.properties file. All the attributes were printed when we started the vault server in the dev environment. As we are running on a local environment so we can use HTTP but in production, we should always use HTTPS.

    vault.token=hvs.7g94bzzDpPq2k2MwW39EJMhi
    vault.host=127.0.0.1
    vault.port=8200
    vault.schema=http
    
  • Add the below configuration class to connect the vault. AbstractVaultConfiguration class belongs to the vault core spring library.

    @Configuration
    public class VaultConfiguration extends AbstractVaultConfiguration{
      @Value("${vault.token}")
      private String token;
      @Value("${vault.host}")
      private String host;
      @Value("${vault.schema}")
      private String schema;
      @Value("${vault.port}")
      private Integer port;
      @Override
      public ClientAuthentication clientAuthentication() {
          return new TokenAuthentication(token);
      }
      @Override
      public VaultEndpoint vaultEndpoint() {
          VaultEndpoint vaultEndpoint = new VaultEndpoint();
          vaultEndpoint.setHost(host);
          vaultEndpoint.setPort(port);
          vaultEndpoint.setScheme(schema);
          return vaultEndpoint;
      }
    }
    
  • Add the below controller class to store and retrieve credentials from the vault. It's not recommended to print or expose credentials to any specific end point. Here, we have added the same so we can test end-to-end functionality easily.

    @RestController
    public class SecretController {
      @Autowired
      private VaultTemplate vaultTemplate;
      @RequestMapping(value = "fetch", method= RequestMethod.GET)
      public String fetchFromVault() {
          VaultResponse vaultResponse = vaultTemplate.read("secret/data/springdemo");
          return "Data from vault --> " + vaultResponse.getData() ;
      }
      @RequestMapping(value = "store", method= RequestMethod.GET)
      public String storeIntoVault() {
          Map<String, String> map = new HashMap<>();
          map.put("password","pwd");
          map.put("username","uname");
          VaultKeyValueOperations keyValue = vaultTemplate.opsForKeyValue("secret", VaultKeyValueOperationsSupport.KeyValueBackend.versioned());
          keyValue.put("springdemo", map);
          return "Data stored into vault";
      }
    }