Skip to content

Spring Vault Property Injection. Get started using Vault secret management.

License

Notifications You must be signed in to change notification settings

markramach/vault-spring-boot-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vault-spring-boot-starter

As we look to build highly scalable applications in the cloud, we commonly struggle with the task of securing our passwords, API keys and other critical secrets. How do we allow our applications to access these secrets in a scalable and secure manner without distributing the secrets themselves? One possible solution is a secure secret storage tool like Vault. Vault provides secure secret storage with a variety of persistent storage options. The Vault product also provides a complete REST API for configuration and access to your secrets. This project will leverage these REST operations to make the injection of Vault secret properties into a Spring Boot application as simple as possible.

Getting Started

The easiest way to get started with this starter project is to fork, clone or download this repository.

git clone https://github.com/markramach/vault-spring-boot-starter.git  

You will also need to install Vault.

Once installed, you can start a development server using the following command.

vault server -dev

At this point you should have running Vault server running locally. Because the -dev argument was specified, the server instance is initialized and unsealed. In a typical production installation this will not be the case. You will need to follow the procedure to initialize and unseal the vault demonstrated in the Basic Concepts documentation.

Spring Boot Configuration

If you're developing a Spring Boot application, you can have properties injected into the application context during the bootstrap phase of application startup. Injecting properties at this point allows you to leverage many of the features that were recently released from the Spring Cloud Config project. This includes the ability to refresh your properties at any point during the application lifecycle using the predefined /refresh endpoint and the @RefreshScope annotation.

This starter project has a VaulBootstrapConfiguration class configured in the META-INF/spring.factories file that indicates certain beans need to be configured on startup. While bean configuration is automatic, it can be disabled using an environment variable or a bootstrap.yml file like the following:

vault:
  enabled: false

The bootstrap configuration creates three components needed to fetch configuration from Vault. VaultConfiguration, VaultAdapter as well as a VaultPropertySourceLocator. This last locator class implements a Spring Boot PropertySourceLocator interface that is automatically detected by the cloud configuration components and makes the property source available to the application context.

Because the bootstrap components are auto-configured, there is no additional code that needs to be written. However, there are a couple of configuration items that you will want to set for yourself. The first is the Vault services endpoint. By default the endpoint is set to http://localhost:8200/v1. You can update this using the bootstrap.yml file.

vault:
  endpoint: http://hostname:port/v1

You will then want to set the paths element to the Vault key-value pairs that you want to make available to the application.

vault:
  endpoint: http://hostname:port/v1
  paths:
    - path/to/secret1
    - path/to/secret2

The final configuration option available is the failFast option. This instructs the application to either fail passively logging the failure, or throw an exception if the property load fails. This option defaults to false, or passive failure.

vault:
  endpoint: http://hostname:port/v1
  paths:
    - path/to/secret1
    - path/to/secret2
  failFast: false

Token Authentication

The most straightforward way to authenticate with Vault is the use of pre-generated token. Depending on the permissions inherited through the token chain, this will grant you access to read Vault properties. For this example, you can generate a token using the Vault dev server by issuing the following command.

vault token-create

This should return a token that can then be used for authentication. For example:

0c6c3fce-09ee-72aa-fd5e-4d6f1152b002

To test the token, you can execute the following command.

vault auth 0c6c3fce-09ee-72aa-fd5e-4d6f1152b002

You should see output similar to the following.

Successfully authenticated! The policies that are associated
with this token are listed below:

root

Now you can configure token based authentication in the bootstrap.yml file using the authentication type configuration property.

vault:
  endpoint: http://hostname:port/v1
  paths:
    - path/to/secret1
    - path/to/secret2
  failFast: false
  authType: TOKEN
  token: 0c6c3fce-09ee-72aa-fd5e-4d6f1152b002

Note that TOKEN is actually the default authentication type and will be used if not specified. However, for clarity it is shown above. Also note that any configuration item can be specified on the command line when starting the Spring Boot application and is recommended if using token base authentication. For example:

java -jar spring-boot-app.jar --vault.token=0c6c3fce-09ee-72aa-fd5e-4d6f1152b002

After configuration is complete, you should be able to inject the Vault properties using any of the normal injection devices, like @Value("path.to.secret1").

App ID Authentication

An alternate authentication option is App ID. This authentication strategy uses 2 pieces of information, an application ID and a user ID. Typically the user ID is only available to the host running the application. This starter project creates a HMAC value using all the resources from the application classpath to dynamically create that unique identifier. The user ID is then pushed to vault with the corresponding application ID allowing this version of our application access to secrets.

In order to use this authentication type, let first create a token that can be used to push the application ID and user ID to vault.

vault token-create

This should return a token that can then be used for authentication. For example:

0c6c3fce-09ee-72aa-fd5e-4d6f1152b002

To test the token, you can execute the following command.

vault auth 0c6c3fce-09ee-72aa-fd5e-4d6f1152b002

You should see output similar to the following.

Successfully authenticated! The policies that are associated
with this token are listed below:

root

Next we need to enable App ID authentication.

vault auth-enable app-id

We can now push our application ID to Vault.

vault write auth/app-id/map/app-id/sample-application-id value=root display_name=sample-application-id

Now you can configure App ID based authentication in the bootstrap.yml file using the authentication type configuration property. Additionally, there are a few items that will need to be specified to generate the HMAC value for the application. Specifically, you will need to provide access to a valid java keystore and AES key that can be used to generate a secure HMACSHA256 value. To generate a keystore you can use the following command.

keytool -genseckey -alias vault -keyalg AES -keysize 256 -keypass password -storetype jceks -storepass password -keystore hmac.jks

The additional configuration elements are shown below.

vault:
  endpoint: http://hostname:port/v1
  paths:
    - path/to/secret1
    - path/to/secret2
  failFast: false
  authType: APPID
  appId: sample-application-id
  keyStore: file:/path/to/hmac.jks
  keyStorePassword: password
  keyAlias: vault
  keyPassword: password

Again, note that any configuration item can be specified on the command line when starting the Spring Boot application and is recommended when specifying the appId. For example:

java -jar spring-boot-app.jar --vault.appId=sample-application-id

At this point if you attempt to start the application, you should see an error indicating Vault App ID authentication failed. This indicates everything is configured properly. In order to grant the application access, we need to push the generated user ID to Vault indicating that the application ID and user ID are a valid combination. We can have the application push this for us using the following arguments.

 java -jar spring-boot-app.jar --vault.pushUserId=true --vault.token=0c6c3fce-09ee-72aa-fd5e-4d6f1152b002

These arguments establish that you are granting this distinct version of the application access to Vault. The vault.token provided should have permissions to write to Vault. From this point on you should not need to provide these arguments as long as the application source is not changed in any way. If the application source is modified, a different user ID will be generated and application will fail to authenticate.

After configuration is complete, you should be able to inject the Vault properties using any of the normal injection devices, like @Value("path.to.secret1").

I have found that this particular strategy is very powerful when deploying to cloud platforms where you may be spinning up and shutting down virtual machines to meet capacity demands.

Additional Configuration

vault.mount - Once you have some familiarity with Vault you will notice you can create any number of backend mount points. A mount is a path extension that corresponds to a persistent storage solution. You can specify the mount point configuration using the vault.mount configuration value on the command line. Or, you can specify it in the bootstrap.yml file like the following.

vault:
  endpoint: http://hostname:port/v1
  paths:
    - path/to/secret1
    - path/to/secret2
  failFast: false
  authType: APPID
  appId: sample-application-id
  keyStore: file:/path/to/hmac.jks
  keyStorePassword: password
  keyAlias: vault
  keyPassword: password
  mount: secret

Note that the mount value will default to secret when not provided.

About

Spring Vault Property Injection. Get started using Vault secret management.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages