In the articles mysql-quartz-email-scheduler  and postgres-quartz-email-scheduler we have provided the database username and password in application.properties. 


There, we let the spring boot auto configure the datasource for us. 


However, we missed one thing. We are writing the database and password in plain text in properties file and this is prone to attacks and leaking sensitive information. We must  store the sensitive information such as database username and passwords securely in a secret manager and when application starts, it should fetch the username and password and establish a connection with the database server. 


In this way, our code doesn’t contain and expose any sensitive information. Here the sensitive information is  database username and password.  



In this article, we will use Hashicorp vault to store the secrets and fetch them from spring boot application.


Let’s get started. 




Vault Installation


Refer the below link for the vault installation based on your OS.


https://learn.hashicorp.com/tutorials/vault/getting-started-install?in=vault/getting-started




Starting the vault server


We will start the vault server in dev mode for testing our code. 


Vault is a client server application where vault server interacts with the data storage and backends. We will store the secrets in vault with the vault CLI over a TLS Connection.


To start the Vault dev server, run:


$ vault server -dev






You should see the output similar to above.  Notice that Unseal Key and Root Token values are displayed


Note: The dev server listens on localhost without TLS and stores the data in-memory  and shows you unseal key and root key. 


Now open a new terminal and execute below commands. 


export VAULT_ADDR='http://127.0.0.1:8200'


Provide root token as shown below. 


export VAULT_TOKEN=“<vault root token>”



To interact with Vault, you must provide a valid token.


If the output looks different, restart the dev server and try again. 




Storing the database secrets in vault


One of the core features of Vault is the ability to read and write arbitrary secrets securely. Secrets written to Vault are encrypted and then written to backend storage. Therefore, the backend storage mechanism never sees the unencrypted value and doesn't have the means necessary to decrypt it without Vault.


Let's write a secret to Key/Value v2 secrets engine when running a dev server. Use the vault kv put <path> <key>=<value> command.





Notice that the version is now 2. The vault kv put command creates a new version of the secrets and replaces any pre-existing data at the path if any.


Sending data as a part of the CLI command often end up in the shell history unencrypted. To avoid this, refer to the Static Secrets: Key/Value Secrets Engine tutorial to learn different approaches.




Verifying our secrets


To fetch secrets, use below command. 


$  vault kv get secret/db



Vault returns the latest version (in this case version 2) of the secrets at secret/db.


To print only the value of a given field, use the -field=<key_name> flag.


vault kv get -field=username secret/db 





Optional JSON output is very useful for scripts. For example, you can use the jq tool to extract the value of the excited secret.


$ vault kv get -format=json secret/db | jq -r .data.data.username




Deleting a Secret


Now that you've learned how to read and write a secret, let's go ahead and delete it. You can do so using the vault kv delete command.


$ vault kv delete secret/db




Spring boot Vault Config


Quartz-dependency


<dependency>

    <groupId>org.springframework.vault</groupId>

    <artifactId>spring-vault-core</artifactId>

    <version>2.2.3.RELEASE</version>

</dependency>



Since, we need to fetch the username and password from vault and then initialise the datasource we need to exclude the DataSourceAutoConfiguration.class and QuartzAutoConfiguration.class 


After exclusion, our application file will look like below



We will choose, local-postures profile here. But you can select any profile you wish and add the two properties in the application-{profile}.properties file like this file<link>


vault.uri=http://localhost:8200


vault.token=s.npj4vbfvXd7MDmYHdimslXMO #your root token here - obtained from dev server



We will use EnvironmentVaultConfiguration.class to configure the vault in our application like below



Here, from my properties file, vault.uri and vault.token will be picked up and instantiated. 



Now, I will create a Credentials POJO like below to cast secrets object fetched from vault to obtain username and password




Now, lets create a CredentialsService class to create a datasource bean by fetching the database credentials from vault like below



Now, we will use the same datasource for our quartz as well. Let’s create a bean for quartz scheduler as well like below



Now, we can run our application. Remember, postgres should be running for this. Refer this post to install postgres. 


You should be able to see your application running like below



You can follow the same for mysql as well.  For mysql docker installation and using with spring boot, refer this example.


You can find the GitHub code base here, Checkout to vault-configs branch.




Resources




Keep Experimenting 🔎 

Keep Learning 🚀


Post a Comment

Previous Post Next Post