Secure Secrets With Spring Cloud Config and Vault
Tags: java, spring, security
Published: 2022-11-15 13:50:29

> Original post written by [Jimena Garbarino](https://auth0.com/blog/authors/jimena-garbarino/) for Auth0 blog.

### Storing secrets in your code is a bad idea. Learn how to use Spring Cloud Config and HashiCorp Vault to make your app more secure.

### <br>

In 2013, GitHub released a search feature that allows users to scan code in all public repositories. A day after the release, however, they had to partially shut it down. It was speculated that the shutdown was because the feature allowed any user to search for all kinds of secrets stored in GitHub repositories. Later, in 2014, data on 50,000 Uber drivers were stolen. It seems someone got access to the company’s database using login credentials found in a GitHub public repository. Hashicorp Vault, a tool for managing secrets and encrypting data in transit, was first announced in 2015, and Spring Vault, the integration of Spring with Vault, was first released in 2017.

It seems like a long time ago, right? Secrets leakage seems to remain pervasive and constant, happening to all kinds of developers—as explained by [this study from NC State University](https://www.ndss-symposium.org/ndss-paper/how-bad-can-it-git-characterizing-secret-leakage-in-public-github-repositories/). Exposed secrets lead to cyber-attacks, data loss or corruption, sensitive data breaches, and crypto-jacking (cryptocurrency mining using a victim’s cloud computer power). With tools like Hashicorp’s Vault and Spring Cloud Vault, the risk can be reduced.

Nowadays, it is widely recommended never to store secret values in code. Therefore, this tutorial will demonstrate the following alternatives:

* Using environment variables for Spring Boot secrets
* Secrets encryption with Spring Cloud Config
* Secrets management with HashiCorp’s Vault
* Using Spring Cloud Vault

<div class="alert alert-info alert-icon">

  <strong>This tutorial was created with the following frameworks and tools:</strong><br> 
  ‣ <a href="https://jdk.java.net/java-se-ri/17">Java OpenJDK 17</a><br> 
  ‣ <a href="https://cli.okta.com/">Okta CLI 0.10.0</a><br> 
  ‣ <a href="https://docs.docker.com/engine/install/">Docker 20.10.12</a><br> 
  ‣ <a href="https://httpie.io/docs/cli/installation">HTTPie 3.2.1</a><br> 
  ‣ <a href="https://hub.docker.com/_/vault">Vault 1.12.0</a><br> 
</div>


## Use Environment Variables for Secrets; A Precursor to Spring Vault

Spring Boot applications can bind property values from environment variables. To demonstrate, create a `vault-demo-app` with OpenID Connect (OIDC) authentication using the Spring Initializr. Then add `web`, `okta`, and `cloud-config-client` dependencies, some of which will be required later in the tutorial:


```
https start.spring.io/starter.zip \
  bootVersion==2.7.4 \
  dependencies==web,okta,cloud-config-client \
  groupId==com.okta.developer \
  artifactId==vault-demo-app  \
  name=="Spring Boot Application" \
  description=="Demo project of a Spring Boot application with Vault protected secrets" \
  packageName==com.okta.developer.vault > vault-demo-app.zip
```


Unzip the file and open the project. Modify its `src/main/java/.../Application.java` class to add the `/` HTTP endpoint:


```java
package com.okta.developer.vault;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @GetMapping("/")
    String hello(@AuthenticationPrincipal OidcUser user) {
        return String.format("Welcome, %s", user.getFullName());
    }

}
```


Disable the cloud configuration for the first run. Edit `application.properties` and add the following value:


```java
spring.cloud.config.enabled=false
```

### OpenID Connect authentication with Okta

In a command line session, go to the `vault-demo-app` root folder.

Before you begin, you’ll need a free Okta developer account. Install the [Okta CLI](https://cli.okta.com/) and run `okta register` to sign up for a new account. If you already have an account, run `okta login`. Then, run `okta apps create`. Select the default app name, or change it as you see fit. Choose Web and press Enter.

Select Okta Spring Boot Starter. Accept the default Redirect URI values provided for you. That is a Login Redirect of `http://localhost:8080/login/oauth2/code/okta` and a Logout Redirect of `http://localhost:8080`.

<details>
  <summary>What does the Okta CLI do?</summary>

The Okta CLI will create an OIDC Web App in your Okta Org. It will add the redirect URIs you specified and grant access to the Everyone group. You will see output like the following when it’s finished:

```
Okta application configuration has been written to: 
  /path/to/app/src/main/resources/application.properties
```

Open `src/main/resources/application.properties` to see the issuer and credentials for your app.

```
okta.oauth2.issuer=https://dev-133337.okta.com/oauth2/default
okta.oauth2.client-id=0oab8eb55Kb9jdMIr5d6
okta.oauth2.client-secret=NEVER-SHOW-SECRETS
```

> NOTE: You can also use the Okta Admin Console to create your app. See [Create a Spring Boot App](https://developer.okta.com/docs/guides/sign-into-web-app/springboot/create-okta-application/) for more information.

</details>

Instead of storing Okta credentials in `application.properties` as part of the project code, Spring Boot allows you to bind properties from environment variables. You can see this in action by starting your application with the Maven command below:


```java
OKTA_OAUTH2_ISSUER={yourOktaIssuerURI} \
OKTA_OAUTH2_CLIENT_ID={yourOktaClientId} \
OKTA_OAUTH2_CLIENT_SECRET={yourOktaClientSecret} \
./mvnw spring-boot:run
```

> NOTE: Copy the values of `yourOktaIssuerURI`, `yourOktaClientId`, and `yourOktaClientSecret` as you will need them for configuration in the next sections. You can also just keep at hand `yourOktaClientId` and retrieve the configuration with `okta apps config --app {yourOktaClientId}`.

In an incognito window, go to `http://localhost:8080`. Here, you should see the Okta login page:

![Okta login page](https://images.ctfassets.net/23aumh6u8s0i/7CC4TBcAIVVHsMK4xDtrHZ/a1e24467c73eba22cfcf12fca3f81802/spring-vault-01.png)

In the application logs, you’ll see the security filter chain initializes an OAuth 2.0 authentication flow on startup:


```
2022-09-07 08:50:09.460  INFO 20676 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Will secure any request with
[org.springframework.security.web.session.DisableEncodeUrlFilter@6b4a4e40,
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@46a8c2b4,
org.springframework.security.web.context.SecurityContextPersistenceFilter@640d604,
org.springframework.security.web.header.HeaderWriterFilter@7b96de8d,
org.springframework.security.web.csrf.CsrfFilter@2a0b901c,
org.springframework.security.web.authentication.logout.LogoutFilter@38ac8968,
org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@7739aac4,
org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@36c07c75,
org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter@353c6da1,
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@7e61e25c,
org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@4f664bee,
org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter@21b51e59,
org.springframework.security.web.savedrequest.RequestCacheAwareFilter@5438fa43,
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@512abf25,
org.springframework.security.web.authentication.AnonymousAuthenticationFilter@76563ae7,
org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter@3e14d390,
org.springframework.security.web.session.SessionManagementFilter@4dc52559,
org.springframework.security.web.access.ExceptionTranslationFilter@51ac12ac,
org.springframework.security.web.access.intercept.FilterSecurityInterceptor@2407a36c]
```

Using environment variables for passing secrets to containerized applications is now considered bad practice because the environment can be inspected or logged in a number of cases. So, let’s move on to using Spring Cloud Config server for secrets storage.

[Read more...](https://auth0.com/blog/spring-vault/?utm_source=devto&utm_medium=sc&utm_campaign=devto)