Using Azure Key Vault Secrets as Spring Properties in Azure Kubernetes Service
Time for some probably too good for your own good magic. The Azure Key Vault is Azures solution to deliver cryptographic secrets in a cloud environment. You can use this to e.g. store passwords and certificates in a centralized yet secure location in a cloud enviroment.
So how do you get these secrets available to your containerized Spring Boot App? Well you can use the Key Vault Library for example, but if for some reason you don’t want or are unable to modify the implementation you need to come up with a way to pass the secrets to the application during runtime.
We are going to use
FlexVolume for
this. It allows you to access secrets, keys and certificates from
your pod. It will simply mount the desired secrets into a file that is
available inside the container, e.g. /mnt/secret.property
which then
contains the secret value.
Setting it up
First you need to go to The Azure Key Vault page to get all the necessary bootstrapping done. Once you have gone through those hoop, you should be ready to mount secrets into the pod.
Say for example we have a database password we would like to mount into the container. To mount /secrets/database-password to contain this password we first declare the VolumeMount for Kubernetes:
Then we could use this in our container, for example nginx:
This would mount the key vault secret named “key-vault-database-password-key” into /secrets/database-password and it contains the password as its content.
This is fine and dandy, but how do you make the application know that there is a file called /secrets/database-password and its contents is the password? Or worse, what if you can’t even modify this? Say the application assumes that the database password must be in a Spring property called app.database.password?
Creating Spring Properties File From The Secrets
Let’s create a single file with all the secrets and format it as a Spring properties file. Let’s start with a Kubefile again, say we have our app image my-spring-boot-app:
With this, we would have a directory /secrets/ with two files, app.db.password and app.ssl.key. So now we have files names with values, but we need a single file with properties with values. So we want to get this data into a single file that has a key-value pair of this data, such as /app/secrets.properties:
We can modify our Docker container to read all the secrets from disk and append them into a single file and then start the container:
So this is our Spring boot application container Dockerfile:
During startup, the docker container appends all the secrets to the /app/secrets.properties file. Here _/config/application.properties would be hour Spring properties file that contains all the other properties. So we have two files, one with the secrets, and another with everything else.
This could also be a separate layer in the Docker container for the same effect.