Issue
I am trying to get my Spring Boot application to configure a datasource connection from a Kubernetes Secret. Due to security requirements, I cannot use the envFrom/secretRef combo in my Deployment descriptor. So I'm trying to use Spring's configtree imports to access the secrets.
(Not all of the values are secrets, however, they all come to me from an Operator that I cannot control as a Secret.)
My application's application.yml
has the following:
spring:
config:
import: "optional:configtree:/etc/secrets/"
datasource:
url: jdbc:postgresql://${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_APP_DB}
username: ${POSTGRES_APP_USERNAME}
password: ${POSTGRES_APP_PASSWORD}
I have a volume/volumeMount that look like this in my Deployment descriptor:
volumes:
- name: postgres-operator
secret:
secretName: postgres
items:
- key: POSTGRES_HOST
path: HOST
- key: POSTGRES_PORT
path: PORT
- key: POSTGRES_APP_DB
path: APP_DB
- key: POSTGRES_APP_USERNAME
path: APP_USERNAME
- key: POSTGRES_APP_PASSWORD
path: APP_PASSWORD
...
volumeMounts:
- name: postgres-operator
mountPath: "/etc/secrets/postgres"
readOnly: true
I've verified that the secrets are mounted in my Pod's filesystem as expected and I created a ConfigurationProperties class that takes in the expected properties and shows the values. However, when the Spring Data JPA tries to initialize, I get errors such as:
Hostname "${POSTGRES_HOST}" not found
This makes me think that Spring isn't capable of reinterpreting configtree imported properties for other properties. Is this true? Is there some other way to work around this?
Solution
You set the configtree base path to /etc/secrets/
.
You volume mounted the secret value into the file /etc/secrets/postgres/HOST
. Configtree converts the subdirectory path to a dot-separated prefix on the configuration property name, so the secret value is readable from configuration property name postgres.HOST
.
Answered By - Chin Huang
Answer Checked By - Willingham (JavaFixing Volunteer)