Securing Passwords Using HashiCorp Vault and Spring-Cloud
Introduction
An application should not be only secured from outsiders in this world, it should be secured from insiders as well. Recall those days when you hesitate to check-in secrete DB password into version control or email Id password which might be used for sending emails to end-user.
In my earlier post, I have written how to secure database properties using java simplified encryption.
In this post, we are going to learn how to secure properties using HashiCorp Value and spring which is the most secure way you can think of securing properties.
HashiCorp Vault setup on local
1. Installation
I am installing the HashiCorp vault on Ubuntu 20.20. Just in case if you are using different OS please follow this link to install and feel free to skip the installation section.
After installing vault when you run $vault
you should see below output.
Note: Knowledge of Vault internals is not required to use Vault. This installation usually done by system administrator in the orgnization. Though as a developer you can learn if you interested much about internals here. We will only see basic things needed to get going.
2. Starting vault server on localhost
To start the vault server you need to pass config information on the startup. For that copy below config and save it into a file say vaultConfig.hcl
.
Note: Don’t use above configuration in production. Also, during installation
vault.hcl
config file created on the path/etc/vault.d/vault.hcl
(on ubuntu) but it has TL S/SSL configs automatically written in it to access Vault server overhttps
which is out of the scope of this post. Also changepath
in above configuration according to your file system(Window/Mac).
$ sudo vault server -config /etc/vault.d/vault.hcl
Now once the server is started one a new terminal and set an environment variable for the vault address so that the vault client could use it. (On windows set it using environment variable)
# export VAULT_ADDR=http://127.0.0.1:8200
3. Initialize Vault
Once the vault server is started, for the very first time we need to initialize the vault and generate two different types of tokens one for login and one for Seal/Unseal the Vault. We have two ways to generate these tokens.
- Using the command line
- Using UI (By accessing http://127.0.0.1:8200)
3.1 Command line approach
when you write vault operator init it creates two different tokens.
- The master key portion
- Root Token(For authentication)
Key share and Key threshold
When a Vault server is started, it starts in a sealed state and it does not know how to decrypt data. Before any operation can be performed on the Vault, it must be unsealed. Unsealing is the process of constructing the master key necessary to decrypt the data encryption key.
Once a Vault node is unsealed, it remains unsealed until —
- Server is restarted
- any exception occurred
- or manually resealed
Key shares: HashiCorp vault uses the master key to unseal vault and that master key can be split into any number of separate tokens. Key shares parameter ask you to enter a number and the master key will split into that many numbers of the token.
Key threshold: Number of key shares required to construct the master key to unseal the vault.
We can pass these params during initialization though we didn’t as it uses default key shares 5 and threshold as 3. Below is how we can pass during initialization.
# vault operator init -key-shares=5 -key-threshold=2
it generates 5 shared keys(-key-shares=5
) out of which at least any of the two key combinations(-key-threshold=2
) will be used to unseal the vault.
3.2 UI approach
We can also initialize vault through UI if it is enabled while starting up the vault server. (Check ui=true
in vaultConfig.hcl
)
You can access http://localhost:8200
below is the page you would see for the first time for the token generation.
In UI, it asks for you to enter key shares and key threshold parameters. As these are mandatory (but not in the command line) once you enter key shares and key threshold it will generate all the needed token and will ask you to download it.
Unseal vault
Vault will decrypt the key and serve the request only when it is unsealed. So before using it we need to unseal it.
- Command-line approach
# vault operator unseal <token 1>
# vault operator unseal <token 2>
# vault operator unseal <token 3>
2. UI approach
Access http://localhost:8200 in your browser
- You have to sign in to the vault server first by using to initial root token which was generated earlier.
2. Then Unseal your vault by using key shares -
Now it is time to add a secret in the vault which we will access later in the spring application.
To do that we need to perform the below steps.
- Login to vault
# vault login <Initial Root Token>
2. Enabling key-value secrets
We will have to do this the very first time because by default vault’s secret engine won’t be enabled.
# vault secrets enable -path=secret/ kv
- where the -
path
is where we are going to put all our key-value pair secrets. kv
is internal to the vault by which we are telling the vault server that this path will store key-value pairs.
3. Add your secrets to the vault
Well, this is what we wanted to do, to put our secured key in the vault and access it directly from the spring application.
#vault kv put secret/spring-cloud-vault appSecurityKey=mysecretkey
#vault kv put secret/spring-cloud-vault/dev appSecurityKey=mysecretkey1
#vault kv put secret/spring-cloud-vault/prod appSecurityKey=mysecretkey2
where spring-cloud-vault
is my spring boot application name and dev/prod
is active profile
So the general syntax for multiple key-value pairs —
#vault kv put secret/<application-name>/<profile> key1=value1 key2=value2
Spring Cloud Integration with Vault Server
Now it is time to configure out spring boot application to fetch the secured key from the vault. For that, we need to add client jar dependency to connect to the vault
Maven Dependency
Adding spring cloud maven dependency into the project.
Creating bootstrap.yml to connect with vault server
Why bootstrap.yml not application.yml?
A Spring Cloud application operates by creating a “bootstrap” context, which is a parent context for the main application. Out of the box it is responsible for loading configuration properties from the external sources, and also decrypting properties in the local external configuration files. — From the documentation.
And hence we need to create bootstrap.yml
to fetch external properties from vault server —
Spring Cloud Vault accesses different resources. By default, the secret backend is enabled which accesses secret config settings via JSON endpoints.
The HTTP service has resources in the form:
/secret/{application-name}/{profile}
/secret/{application-name}
/secret/{default-context}/{profile}
/secret/{default-context}
Now you can give it a try for adding more keys into vault serve with a different profile and access it in your spring cloud application by changing profile bypassing program argument like spring.profiles.active=dev/prod/test1
and see if value changes
Conclusion
We saw, how easy it is when it comes to access secrets from the vault server. The overall effort actually goes in the vault server setup which is actually a system administrator job done in your organization. You would only need your vault server IP and a token to authenticate with the vault server, and you would ask the admin to add key-value pairs in the vault server and access it directly in your spring application. There are various ways vault authentication can happen. Please see here for more details.
Git hub code present here