Encrypt Spring application data with Vault
Some applications process sensitive or personally identifiable information (PII). You should encrypt this information in-transit and at-rest to protect the data. Vault helps centralize management of cryptographic services for data protection.
In this tutorial, you'll use the Vault transit secrets engine to encrypt data processed by a Spring application before writing it into a database. Encrypting the data before writing ensures that only those with access to the key in Vault can decrypt it. Any service or user without access to the key and decryption endpoint in Vault cannot decrypt the data.
Prerequisites
Set up application dependencies
Retrieve the configuration by cloning or downloading the hashicorp-education/learn-vault-spring-cloud repository from GitHub.
Clone the repository.
Or download the repository.
The repository contains supporting content for this Spring application tutorial.
Change directories to the
vault-transit/
directory.Review
pom.xml
to review the application's dependencies. The Spring application in this demo uses the Spring Cloud Vault library. It provides lightweight client-side support for connecting to Vault in a distributed environment. The application also needs JDBC and PostgreSQL to access the database.pom.xml1 2 3 4 5 6 7 8 9 10111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
Configure application access to Vault and database
Spring Cloud Vault requires the Vault address and authentication method passed as application properties. This tutorial uses the Vault token authentication method. The application also passes the transit secrets engine path and database connection as configuration properties.
Review
application.properties
in/src/main/resources
. The application setsspring.cloud.vault.uri
andspring.cloud.vault.token
to the address and root token of the Vault server in dev mode. You can change the Vault authentication to any supported authentication methods based on your organization's Vault setup.application.properties1 2 3 4 5 6 7 8 9 1011121314151617
Additional properties in
application.properties
set up application access to the database and initializes the database table.application.properties1 2 3 4 5 6 7 8 9 1011121314151617
Review the
schema.sql
file in/src/main/resources
. Spring supports database initialization, which sets up the initial table in the database. The database initializes the first time you run the application.src/main/resources/schema.sql1 2 3 4 5 6 7 8 9 10
Add custom configuration properties for transit secrets engine
The application needs the path to the transit secrets engine and key in Vault. Rather than hard-code the path into the application, set up custom configuration properties for the transit secrets engine path and key.
Review the
VaultTransitProperties.java
file in/src/main/java/com/hashicorp/vaulttransit
. This class enables a configuration property with the prefixtransit
and fields for path and key.VaultTransitProperties.java1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627
The
main
function inVaultTransitApplication.java
includes a Spring annotation to add the custom configuration properties.VaultTransitProperties.java12345678
Return to
application.properties
. It includes the custom propertiestransit.path
andtransit.key
to use the transit secrets engine in Vault.application.properties1 2 3 4 5 6 7 8 9 1011121314151617
Implement encrypt and decrypt methods
Spring Cloud Vault uses the Spring Vault library to make requests to Vault. Spring Vault includes an interface with operations for the transit secrets engine. The interface simplifies calls to encrypt and decrypt payloads.
Tip
If you use a JPA implementation, you can use an AttributeConverter interface to encrypt and decrypt the payload before inserting and retrieving it from the database.
Review
VaultTransit.java
in/src/main/java/com/hashicorp/vaulttransit
. This class injects sets up theVaultOperations
interface and passes the transit secrets engine's path and key. It implements methods to encrypt and decrypt a plaintext credit card number used by the application.VaultTransit.java1 2 3 4 5 6 7 8 9 101112131415161718192021222324
Review
VaultTransitApplication.java
. This file contains a controller definition for the application. Each time someone creates a payment with the application's API, the plaintext credit card number gets encrypted by Vault.VaultTransitApplication.java1 2 3 4 5 6 7 8 9 1011121314151617181920212223242526272829303132333435363738394041424344
Continue reviewing
VaultTransitApplication.java
. Each time someone gets a list of payments from the database, the controller decrypts the credit card information with Vault transit secrets engine.Tip
For applications that do not need to decrypt and use the plaintext data, create a Vault policy that only allows access to the "/encrypt" endpoint. This approach further protects sensitive information from unauthorized access.VaultTransitApplication.java1 2 3 4 5 6 7 8 9 10111213141516171819202122232425262728293031323334
Run the application
Build and run the application on your local machine to test how Vault encrypts the data before inserting it into the database and decrypts the data for a list of payments.
Return to the
vault-transit
directory.Use Docker Compose to create a Vault server in dev mode, PostgreSQL database for the application, and Vault configuration container to set up the transit secrets engine.
After you start the Vault server, verify that it has the transit secrets engine enabled with an encryption key at
transit/keys/payments
.In your terminal, build and run the application using the Apache Maven Wrapper included in the repository.
Open another terminal session. Send the application an API request to create a payment with a name and credit card number in plaintext. The application returns a response with a credit card number encrypted by Vault transit secrets engine.
Query the database for the
payments
database for the encrypted credit card number.Verify that application successfully decrypts the payload using Vault. Request the application for a list of payments in the database using its API. The request returns the credit card information in plaintext.
Clean up
Stop the application and remove the Vault server and database.
Stop the application running with Maven.
Remove the Vault server and database with Docker Compose.
Next steps
In this tutorial, you learned how to encrypt and decrypt application payloads with Vault transit secrets engine and Spring Cloud Vault. Encrypting the payloads before storing them in a database protects sensitive information in-transit and at-rest, ensuring only authorized identities can decrypt and use the payload. In the case of a data breach, you can rotate the encryption key in Vault and rewrap the data in the table with a new key.
For more information, review the following resources:
- Spring Cloud Vault
- Spring Vault, the core library for Spring Cloud Vault
- Transit secrets engine for Vault