4

I've read following tutorial:Vault Configuration

Ok we installed the Vault server and put 2 pairs of secret properties:

$ vault kv put secret/gs-vault-config example.username=demouser example.password=demopassword
$ vault kv put secret/gs-vault-config/cloud example.username=clouduser example.password=cloudpassword

Spring boot application has following properties(bootstrap.properties):

spring.application.name=gs-vault-config
spring.cloud.vault.token=00000000-0000-0000-0000-000000000000
spring.cloud.vault.scheme=http
spring.cloud.vault.kv.enabled=true

So based on spring.cloud.vault.token application able to read secure properties(name and password) but spring.cloud.vault.token is stored in the insecure place - bootstrap.properties which is stored in the code repository. Could you please explain why it is safe?

P.S.

As we found out it is insecure. How to make it secure ? I understand that there are might be several solutions to make it secure but single simplified example would be enough for me.

gstackoverflow
  • 36,709
  • 117
  • 359
  • 710
  • 4
    Why is your token stored in an insecure place? – f1sh Mar 17 '20 at 14:12
  • @f1sh As far I understood Vault is a safe place but github repository is not a safe place. To use(to connect from application) safe Vault I need to know token and this token is stored in the github – gstackoverflow Mar 17 '20 at 14:27

3 Answers3

4

Could you please explain why it is safe?

The answer is that it is NOT safe ... if you do it that way. For example, the Spring Vault reference manual says:

"Consider carefully your security requirements. Static token authentication is fine if you want quickly get started with Vault, but a static token is not protected any further. Any disclosure to unintended parties allows Vault use with the associated token roles."

You should either protect your static tokens, or only grant them access to "secrets" in the vault which you are happy to be widely known.

Alternatively, have your application use an authenticated method to generate short-term dynamic tokens.


As I understand initial problem it is bad to store passwords in an application.properties file on Github.

And storing a static Vault token in an application.properties file on Github is equally as bad.

What is the difference ?

There is almost no difference1. This is simply the wrong way to use Vault.


1 - There is a small advantage in that you could invalidate the token if you discover it leaked by accident. But this doesn't mean that it is sensible to publish it deliberately.


So how do you do things securely?

First, you MUST secure the machines where the secrets are going to be used. Even if you are not going to store the actual secrets on disk, you will need to store a different secret (securely) on each of your machines so that they can authenticate themselves to the place where the real secrets are kept.

Here is an example using Chef.

  1. Set up a secure Chef server that holds the configs for your machines; i.e. recipes for all of the things that need to be installed, node descriptions to say what recipes to apply, etc.

  2. When you bootstrap a machine as a node, a keypair is generated for the machine and registered with the Chef server. The keypair is also held on the machine, and has to be held securely.

  3. Then you use the Chef client to run the recipes that install and configure your server.

Note that this relies on having a properly secured system to run the Chef server. It also relies on each of the nodes being sufficiently secure to protect their own keys.

There are other ways to do this, but nothing will work if you cannot secure your host sufficiently.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • So Vault + static token has no additional sense in comparison with spring cloud confing + spring cloud bus ? Thus it is just works as a ditributed centralized property source. Is it corret ? How to store secrets safety ? – gstackoverflow Mar 17 '20 at 14:48
  • There is no way to avoid having some secret (a private key, a password, a static token, physical device, a finger print or retina scan, etc) that has to be kept secure. The advantage of Vault (and similar) is that you can store the secrets better / more securely, and you have better control over who / what can access them. – Stephen C Mar 17 '20 at 14:52
  • Could you explain why using Vault makes secrets storing more securely ? As I understand initial problem it is bad to store passwords in the application.properties of guthub. Ok - instead of having properties in the guthub we store Vault token in guthub and move properties to the Vault. If hacker knows token he easily can read all properties from the Vault. What is the difference ? – gstackoverflow Mar 17 '20 at 15:06
  • Could you please clarify your phrase **You should either protect your static tokens, or only grant them access to "secrets" in the vault which you are happy to be widely known.** – gstackoverflow Mar 17 '20 at 16:20
  • Anyway I don't understand where do I have to store Vault token ? Are there any best practices to achieve it ? Do I have to put secret to each environment manually ? – gstackoverflow Mar 17 '20 at 16:24
  • 1) I see nothing unclear in what I said there. 2) In a safe place. Or don't use static tokens. 3) https://www.satisfice.com/blog/archives/5164 4) People use deployment tools like Puppet, Chef, etc for this kind of thing. You could bootstrap each host with its own token and then it can pull its own secrets from the vault. But the host needs to be secure enough to keep its own token secret. If you can't achieve that, this is all pointless. – Stephen C Mar 17 '20 at 23:42
  • My point 3 is particularly apropos in this case because you seem to be looking for a so-called "best practice" that will allow you make your system secure without you thinking about it. They don't exist in the sense that the words "best practice" mean. You can't avoid thinking about security. And you can't ignore certain ground truths ... such as the need to secure your systems before you put secrets of any kind on them. – Stephen C Mar 17 '20 at 23:50
  • Could you please provide example of safe configuration ? I believe example will help me to understand this topic better. – gstackoverflow Mar 19 '20 at 11:27
  • I don't try to avoid thinking about security. I just want to understand some basics about HOW to achieve that seurity. – gstackoverflow Mar 19 '20 at 13:37
  • Well the basic fundamental thing is that you have to secure the token or password or whatever that you use to unlock the vault. There is no such thing as an intrinisicly safe configuration. – Stephen C Mar 19 '20 at 13:40
1

Storing spring.cloud.vault.token in the application.properties that is checked into VCS (e.g. Git) might compromise all secrets stored in Vault.

The solution is not to store Vault token in application.properties as a plain text. There are several options.

Remove Vault token from application.properties

Simply remove spring.cloud.vault.token from application.properties and instead provide it via system property -Dspring.cloud.vault.token=00000000-0000-0000-0000-000000000000 (when starting the application) or environment variable SPRING_CLOUD_VAULT_TOKEN. Environment variable is especially convenient if you use containers (Docker or Kubernetes).

Store encrypted Vault token in application.properties

You can keep spring.cloud.vault.token property in application.properties if it is encrypted.

Spring Cloud Config supports decrypting properties with values starting with {cipher}:

spring.cloud.vault.token={cipher}encrypted_vault_token

To use properties encryption and decryption you will need the following dependencies (example for Gradle):

implementation 'org.springframework.cloud:spring-cloud-context:2.2.2.RELEASE'
implementation 'org.bouncycastle:bcprov-jdk15on:1.64'

Symmetric encryption

The simplest way to encrypt the properties is to use symmetric encryption.

Come up with a symmetric key (for example s3cr3t).

To encrypt Vault token you can use Spring Boot CLI with Spring Boot Cloud CLI:

curl "https://repo.spring.io/release/org/springframework/boot/spring-boot-cli/2.2.2.RELEASE/spring-boot-cli-2.2.2.RELEASE-bin.tar.gz" -o spring-boot-cli-bin.tar.gz
tar -xf spring-boot-cli-bin.tar.gz
cd spring-2.2.2.RELEASE
bin/spring install org.springframework.cloud:spring-cloud-cli:2.2.1.RELEASE

bin/spring encrypt 00000000-0000-0000-0000-000000000000 --key s3cr3t
# 507cd1614682535ab8237b448ca73dc74058d3ae9145d63a7381ee67f3046eb1598da6960abdbf2dbf22c47206db5222e45fc74fd6122bc707b61c62f5051e0f

bin/spring decrypt 507cd1614682535ab8237b448ca73dc74058d3ae9145d63a7381ee67f3046eb1598da6960abdbf2dbf22c47206db5222e45fc74fd6122bc707b61c62f5051e0f --key s3cr3t
# 00000000-0000-0000-0000-000000000000

Pass the symmetric key to the application in ENCRYPT_KEY environment variable.

Symmetric encryption key must be never checked into a VCS.

Asymmetric encryption

Consider asymmetric encryption using public and private key pair as a more secure alternative to symmetric encryption.

Instead of a symmetric encryption key you need to generate a keystore (using the keytool utility that comes with the JDK or openssl).

In the bootstrap.properties specify the following properties:

  • encrypt.keyStore.location
  • encrypt.keyStore.password
  • encrypt.keyStore.alias
  • encrypt.keyStore.type

The keystore has to be mounted at the location specified in encrypt.keyStore.location and never checked into a VCS.

Also, password that unlocks the keystore better to pass in ENCRYPT_KEYSTORE_PASSWORD environment variable.

Read about key management in Spring Cloud Config.

Eugene Khyst
  • 9,236
  • 7
  • 38
  • 65
  • 2
    But in all of the approaches, there is a password or key or something that has to be stored securely. You cannot get around that. – Stephen C Mar 21 '20 at 16:37
  • The easiest solution is not to store a master password and keep it in your head only. Or store it in some secure place like AWS Secrets Manager but supply manually. – Eugene Khyst Mar 21 '20 at 16:45
  • That solution is not suitable for production. Doesn't work if you are not available to enter the password whenever the system reboots. Doesn't work if you get hit by a green bus. – Stephen C Mar 21 '20 at 16:46
  • All depends on how the deployment is done. The task is to pass master password as an environment variable. On Kubernetes you can manually create Secret with the master password and bind it to environment variable. This solution works with reboots. Storing master password in AWS Secrets Manager solves the problem if you get hit by bus. – Eugene Khyst Mar 21 '20 at 17:01
0

Answering your questions

Could you please explain why it is safe?

It is not safe! Never put a plain secret in source control.

As we found out it is insecure. How to make it secure?

Some ways to increase security:

  • Use environment variables instead of properties file;
  • Restrict the access at the network level to the Vault server only to workload servers. This guarantees that nobody outside that network can exchange the token;
  • Vault works generating real but temporary credentials each time the token is used. Reduce the scope of the real credentials to read-only whenever be possible;
  • Rotate the token regularly.

Regarding the Spring specifics

The bootstrap properties should contain only non-critical properties. For critical properties, you can pass them to the application using environment variables.

spring.cloud.vault.token = ${SPRING_CLOUD_VAULT_TOKEN}

Summary

The question remains "Who guards the keys?". But the Vault Token serves actually to protect the real sensitive data. In case the vault token is leaked, you can invalidate just the token.

Improve the constraints from where applications can access the vault server and reduce the scope of the real credentials are additional ways to ensure that only the servers that run the application can exchange the tokens by the real credentials and the real credentials have the minimum privilege as possible.

Anderson Marques
  • 808
  • 8
  • 13