Show List

Java Spring Boot Application to Write and Read Secrets from Vault

In this demo we are going to create a Spring Boot application to write secret to local running Vault instance and then read the secret.

Go to Spring initializr website "https://start.spring.io/" and create a Java Project with dependencies: spring-boot-starter-web and spring-cloud-starter-vault-config. Download the project zip and extract to a folder.

We have selected gradle as the build tool for the project. Here is the build.gradle file:
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.7'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'vault.secrets'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
mavenCentral()
}

ext {
set('springCloudVersion', "2021.0.5")
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-vault-config'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}

tasks.named('test') {
useJUnitPlatform()
}
Here is the project structure
Update the DemoApplication.java file as below. Spring provides libraries to integrate with Hashicorp vault. We are using command line runner interface to perform the Vault operations when the application starts.
  • The application connects to local Vault server at port 8200 running in dev mode.
  • For this demo, you can use the root token or the token for a role id.
  • The secrets are going to be stored at and read from path secret/mysecretslocation/creds
package vault.secrets.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.Map;
import java.util.HashMap;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.support.Versioned;
import org.springframework.vault.core.VaultTemplate;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
context.close();
}

@Override
public void run(String... strings) throws Exception {
VaultEndpoint vaultEndpoint = new VaultEndpoint();

//Local running instance of Vault
vaultEndpoint.setHost("127.0.0.1");
vaultEndpoint.setPort(8200);
vaultEndpoint.setScheme("http");

// Authenticate with the token. This token should be valid.
VaultTemplate vaultTemplate = new VaultTemplate(
vaultEndpoint,
new TokenAuthentication("hvs.Z8swD4DRYQDtuHGlkkxFkTRG"));

// Writing the secret to Vault
Map<String, String> data = new HashMap<>();
data.put("password", "top_secret_password");

vaultTemplate
.opsForVersionedKeyValue("secret")
.put("mysecretslocation/creds", data);

System.out.println("Secret written successfully.");

// Reading the secret from Vault
Versioned<Map<String, Object>> secret = vaultTemplate
.opsForVersionedKeyValue("secret")
.get("mysecretslocation/creds");

String password = "";
if (secret != null && secret.hasData()) {
password = (String) secret.getData().get("password");
}

if (!password.equals("top_secret_password")) {
throw new Exception("Unexpected password");
}

System.out.println("Secret read successfully");
}
}
When the Spring Boot application is run, the results can be viewed on the console confirming that the secret was written and read successfully.
8:04:31 AM: Executing task ':DemoApplication.main()'...

> Task :compileJava
> Task :processResources UP-TO-DATE
> Task :classes

> Task :DemoApplication.main()

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.7)

2022-12-27 08:04:35.727  INFO 14328 --- [           main] vault.secrets.demo.DemoApplication       : Starting DemoApplication using Java 11.0.15 on sm15 with PID 14328 (C:\Users\mail2\Downloads\demo\build\classes\java\main started by mail2 in C:\Users\mail2\Downloads\demo)
2022-12-27 08:04:35.730  INFO 14328 --- [           main] vault.secrets.demo.DemoApplication       : No active profile set, falling back to 1 default profile: "default"
2022-12-27 08:04:36.579  INFO 14328 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=83794b8e-03e1-3bf4-aa53-130e4a37486a
2022-12-27 08:04:37.300  INFO 14328 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-12-27 08:04:37.301  INFO 14328 --- [           main] o.a.catalina.core.AprLifecycleListener   : An older version [1.2.28] of the Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of [1.2.30]
2022-12-27 08:04:37.302  INFO 14328 --- [           main] o.a.catalina.core.AprLifecycleListener   : Loaded Apache Tomcat Native library [1.2.28] using APR version [1.7.0].
2022-12-27 08:04:37.302  INFO 14328 --- [           main] o.a.catalina.core.AprLifecycleListener   : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true].
2022-12-27 08:04:37.302  INFO 14328 --- [           main] o.a.catalina.core.AprLifecycleListener   : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
2022-12-27 08:04:37.305  INFO 14328 --- [           main] o.a.catalina.core.AprLifecycleListener   : OpenSSL successfully initialized [OpenSSL 1.1.1k  25 Mar 2021]
2022-12-27 08:04:37.315  INFO 14328 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-12-27 08:04:37.316  INFO 14328 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.70]
2022-12-27 08:04:37.502  INFO 14328 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-12-27 08:04:37.502  INFO 14328 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1690 ms
2022-12-27 08:04:39.469  INFO 14328 --- [           main] o.s.cloud.commons.util.InetUtils         : Cannot determine local hostname
2022-12-27 08:04:39.817  INFO 14328 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-12-27 08:04:41.294  INFO 14328 --- [           main] o.s.cloud.commons.util.InetUtils         : Cannot determine local hostname
2022-12-27 08:04:41.310  INFO 14328 --- [           main] vault.secrets.demo.DemoApplication       : Started DemoApplication in 7.631 seconds (JVM running for 8.126)
Secret written successfully.
Secret read successfully
We can also verify the secret from the Vault UI:
Source Code:

https://github.com/it-code-lab/vault_secrets_demo

    Leave a Comment


  • captcha text