Spring Cloud Config — Encryption and Decryption at Rest

Eresh Gorantla
The Startup
Published in
5 min readJan 12, 2021

This story talks about the encrypting secure data like (passwords, API Keys of third party information ..) at REST when spring cloud config is used as centralized configuration for micro services.

Please read the following blog to get started with Spring cloud config server.

The Config Server can use a symmetric (shared) key or an asymmetric one (RSA key pair). In this story we use both the ways.

Pre-requisite

For Spring Cloud to be able to encrypt and decrypt properties you will need to add the full-strength JCE to your JVM (it is not included by default). You can download the “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files” from Oracle and follow the installation instructions. Make sure you download JCE for your Java platform.

The installation process is very simply. Basically you will need to copy the two downloaded jar files to a /lib/security folder in your JDK.

<java-home>/lib/security [Unix]
<java-home>\lib\security [Windows]

Note: Once you copy the JCE libraries you will need to kill the running Java process and start it again. If that does not help, restart your computer.

If you have java version > 8, then the JCE library is supported by default.

Symmetric (shared) key Mechanism

We should add encrypt.key = some key value in bootstrap.properties/yml file. This is must to enable encryption feature in spring-cloud-config

Use one of the strong generated keys

encrypt.key=foM}kcGHmxB7[C9

Once you have added the encryption key to a bootstrap.properties file of your Spring Cloud Config server, run the server. To encrypt a property send HTTP POST request to a /encrypt URL endpoint. Below is an example of CURL command to encrypt a property value “configC Symmetric”:

Configure Encrypted Value in backends

In this case we will take AWSS3 Client. I have uploaded the spring-config.properties by adding below configC value.

The Spring Cloud Config can be used with Git or Native file system as a backend. When adding an encrypted value to a property file which is being served by a Spring Cloud Config server use a {cipher} prefix. For example:

configC={cipher}c176a49340a2b57641b8a41e9d7f94ee4aa980d13626e8a0eaf1fc22203f4a900123f8bda1bc9fdfb138069afe3e9c76

This way you can keep sensitive information like passwords encrypted in a Git repository/jdbc/redis/awss3. When Spring Cloud config server pulls encrypted values from a Git repository or a native file system backend, it will decrypt encrypted values and will serve already decrypted values to your Microservices. You do not need to decrypt properties manually yourself.

Note: If Spring Cloud Config was not able to decrypt the it will add the invalid prefix to a property name and it will use n/a as a property value. For example, let’s assume we used an incorrect encryption key and Spring Cloud Config was not able to decrypt the value of a “encrypted” property. In this case you will see the following in a property source returned to a Microservice

"invalid.configC": "<n/a>"

Let us start config-server and see the config details in server

The configC value got decrypted and shown in the response.

Check the same in S3-Client

We have seen how to encrypt and decrypt at rest with the help of JCA Symmetric (Shared Key) Mechanism. Let us see how to do it in Asymmetric Way.

Asymmetric one (RSA key pair) Encryption Mechanism

To generate keystore file for Asymmetric Encryption we will use keytool utility which comes with JDK. Below is an example of how to use a keytool utility to generate a keystore file. The keystore file will contain keys which will be used in encryption and decryption of information.

keytool -genkeypair -alias myKeyAlias -keyalg RSA \  -dname "CN=Local,OU=Local,O=My laptop,L=Hyderabad,S=Telangana,C=India" \  -keypass keyPassword -keystore server.jks -storepass storePassword

where:

  • myKeyAlias — Replace this value with an alias for your key.
  • keyPassword — Changes the password under which the private/secret key identified by alias is protected, from old_keypass to new_keypass , which must be at least 6 characters.
  • server.jks — A keystore file name. You can come up with a different name,
  • storePassword — Changes the password used to protect the integrity of the keystore contents. The new password is new_storepass, which must be at least 6 characters.

Once you run the above keytool command you might get the following warning message:

Warning:The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format...

If you get this message then follow the instructions mentioned in the message and execute the command it suggests. For example:

keytool -importkeystore -srckeystore apiEncryptionKey.jks -destkeystore apiEncryptionKey.jks -deststoretype pkcs12

Configure RSA Keys in bootstrap.yml

encrypt:
#key: foM}kcGHmxB7[C9
key-store:
location: file:///Users/ereshgorantla/apiEncryptionKey.jks
password: test12345
alias: apiEncryptionKey

I have the key at given location in my local setup.

Encrypt Configuration Property

The process stays same as in earlier case. Spring cloud config dependency enables few Rest endpoints

Configure Encrypted value in backend

Added one more config value in properties file ans uploaded to S3.

configD = {cipher}AQB3bfg8U0GIr8T8qVH39AWncFWjVd4SP+dRAqZIks5IFGEytirgZ9zIf0SFCRwrqU8Jpf+FzmHvEzm3BTE0oYo96kCbrr8W+Bi2jD+rFzpWEIsev/a98e/dJfJr0Xfrfbd2329AaFWggM09iR6DHg+vFSeBvZP+JNW+8N9wF6Rz5VQc0lITlEcvCr9CXVjtpn+yxUwroldtF06CPuZvqE54ai9x9ylBtOqEdJegue0oIoyHy0aCYn9PuKDVOreiY5YrAFEuq8UVf0m2YDCzV1hbtyWZwdIJSxAPdYPQVNZTxXp+zgQ+iQT9AkB2rGvnGaFk7U/lrYie4Of+UuB27rYGViVD86pFlH0BPYvqdQ9apUSZWfEvSjwIrH7zS1gx7g9yo02Vmnh8scfudV81oD9i

Now let us restart the config server as we have modified the ecnryption mechanism. And check the config details again

If you have observed, the configC value has come has invalid. This is because we have encrypted this in symmetric way.

Let us test this in client — S3

If you observer we got the configD decrypted as per our expectation. But configC has the value of the static property we defined in application.properties.

These are the two approaches spring config server provides with JCA as the provider.

Please visit complete code base here

--

--

Eresh Gorantla
The Startup

Experience in Open source stack, microservices, event-driven, analytics. Loves Cricket, cooking, movies and travelling.