Safeguarding Secrets in Spring Boot with Vault
Tags: springboot, vault, security, devops
Published: 2023-09-14 15:44:16

When developing Spring Boot applications, we often encounter the need to manage sensitive information like database passwords, application keys, and other secrets. Typically, these secrets might reside in `application.properties` or `application.yml`. Pushing such sensitive information to repositories is risky. Thankfully, there's **HashiCorp's Vault**.

## Understanding Vault
Vault is a tool for securely accessing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, or certificates. Vault provides a unified interface to any secret while providing tight access control and recording a detailed audit log.

## Setting Up Vault with Docker Compose
For rapid deployment, especially during development, Docker Compose offers a convenient method to get Vault up and running.

1.Create a file named `docker-compose.yml` and add the following:
```yaml
version: '3'

services:
  vault:
    image: vault:1.13.3
    container_name: vault_dev
    ports:
      - "8200:8200"
    environment:
      VAULT_DEV_ROOT_TOKEN_ID: myroot
      VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"
    cap_add:
      - IPC_LOCK
    command: server -dev
```
2.Run docker-compose up to start the Vault server.

3.Access the Vault UI at http://localhost:8200/ui and log in with the token myroot.

After logging in, you can view this page

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zxqfemfvvi7sbltzn3yj.png)

Enable KV engine

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2crl7iapx04wc15rqyae.png)

Add the secrets in the specific path you want eg Postgresql settings

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cqv4k8u0s8qsdz03ns7o.png)

## Integrating Vault with Spring Boot
Once Vault is up and running, the next step is integrating it with your Spring Boot application.

1.Setting Environments
```bash
export VAULT_URI=http://localhost:8200
export VAULT_TOKEN=myroot
```

2.Spring Boot Initial Setup:
Set up a basic Spring Boot application. If you're new to this, Spring Initializr provides a quick way to bootstrap a new Spring Boot project.

3.Maven Dependency:
To integrate Spring Vault, add the following dependency to your Maven pom.xml:

```yaml
<dependency>
    <groupId>org.springframework.vault</groupId>
    <artifactId>spring-vault-core</artifactId>
    <version>3.0.4</version>
</dependency>
```

4.Integration Code:
First, define your Vault configuration:

```java
public class VaultConfiguration {
    private static final String token;
    private static final String uri;

    static {
        token = System.getenv("VAULT_TOKEN");
        uri = System.getenv("VAULT_URI");
    }

    public static String getToken() {
        return token;
    }

    public static String getUri() {
        return uri;
    }
}
```

Then, use a utility to read secrets from Vault:
```java
public class VaultConfigReaderUtil {
    public static Properties read(String path) {
        String MAIN_VAULT_PATH = "kv/data/myapplication";
        VaultEndpoint endpoint;
        Properties properties = new Properties();

        try {
            endpoint = VaultEndpoint.from(new URI(VaultConfiguration.getUri()));
            VaultTemplate vaultTemplate = new VaultTemplate(endpoint, new TokenAuthentication(VaultConfiguration.getToken()));
            VaultResponse response = vaultTemplate.read("%s/%s".formatted(MAIN_VAULT_PATH, path));
            Map<String, Object> mapData = (Map<String, Object>) response.getRequiredData().get("data");
            properties.putAll(mapData);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

        return properties;
    }
}
```

Lastly, in your main application, use the utility to fetch secrets and feed them to Spring Boot:

```java
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        Properties props = new Properties();
        Properties postgresProp = VaultConfigReaderUtil.read("postgres");
        props.putAll(postgresProp);
        
        SpringApplicationBuilder springApplication = new SpringApplicationBuilder(MyApplication.class);
        springApplication.properties(props).run(args);
    }
}
```



## Conclusion
In the ever-evolving landscape of software development, security remains paramount. Secrets management is a fundamental aspect of ensuring that our applications are robust against breaches and unforeseen vulnerabilities. As we've explored, Vault by HashiCorp offers a comprehensive solution to this challenge, seamlessly integrating with frameworks like Spring Boot.

Utilizing Docker Compose, we've streamlined the deployment of Vault, making it more accessible, especially during the development phase. However, it's essential to understand that while development configurations simplify processes, they aren't suitable for production environments. Always ensure a secure, production-ready configuration for Vault when deploying in live scenarios.

Spring Boot's flexibility and vast ecosystem, paired with Vault's secure secrets management capabilities, provide developers with powerful tools to build secure, scalable, and efficient applications. As we continue to innovate and build, let's prioritize the safety and integrity of our applications, ensuring that our secrets remain just that – secret.