I have a Spring Boot application which runs in Azure Kubernetes. The application uses Liquibase (Liquibase-Core 4.4.3) to create and amend database tables for the application on start up. For security reasons the application has different DB credentials to the Liquibase user and the Liquibase user credentials are added via the application.properties file as per below using environment variables:
spring.liquibase.url=${env_db_connection_url}
spring.liquibase.user=${env_db_lb_username}
spring.liquibase.password=${env_db_lb_password}
We add the credentials using this method with environment variables as the credentials are different depending on the environment (e.g. UAT, production) the app is being deployed to and this allows the pipeline to handle the differences without any changes being necessary to the code.
Our security team want us to stop using environment variables and so we are moving to using csi drivers for any sensitive information. This effectively creates something similar to an external properties file which sits outside the application but within the same container.
However, I am now having trouble resolving the db credentials for Liquibase and I don't know the best method to achieve what I need. I need a solution where we can still tokenize the value within the code but it is able to retrieve the secret values (db password etc) from the external properties file.
As you can imagine hard-coding these values or even just encrypting them wouldn't solve the issue due to the changing values between environments. We are able to retrieve the values within the application however I feel this is done too late in the process as Liquibase will have already attempted to start (and therefore fail) before the application code is run.
Any help or suggestions would be appreciated.
This was the solution we took in the end. Effectively we worked out that the spring properties file could look directly in an external properties file (the csi driver in this case) to get the value.
Added to Spring properties file spring.config.import=optional:configtree:${env_var_for_external_property_file_location:#{null}}/liquibase/
For clarity, below is the secret provider class yaml which stores the liquibase password. The object alias value matching what Liquibase config expects for db password.
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: name
spec:
provider: azure
parameters:
keyvaultName: ****
tenantId: ****
objects: |
array:
- |
objectName: lqb
objectAlias: liquibase/spring.liquibase.password
objectType: secret