'inject environment variables in tomcat catalina.properties [Kubernetes]
I am using kubernetes for a web application deployement.
containers:
- name: myapp
image: tomcat8-jre8:latest
imagePullPolicy: Always
env:
- name: DATABASE_HOST
valueFrom:
secretKeyRef:
name: my-secret
key: external.database.host
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: my-secret
key: external.database.user
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: my-secret
key: external.database.password
I also use tomcat JNDI with a custom server.xml and catalina.properties
<Resource factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
name="jdbc/mysource"
auth="Container"
type="javax.sql.DataSource"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://******" # secret url
username="${database.user}"
password="${database.password}" />
I tried puting a new property into catalina.properties
### catalina specific configuration
database.user = ${DATABASE_USER}
database.password = ${DATABASE_PASSWORD}
server.xml can well read the property but could not resolve the environment variable ${DATABASE_USER} and ${DATABASE_PASSWORD}
Both server.xml and catalina.properties are mounted as config maps, the sensitive information are being held in environment variables. we don't know their values
the environment variable are set when I log into the pod and are recognizable from my webapp (java based) but could not read it from catalina.properties (and/or server.xml)
Can anyone give me a tip on this ? Is it possible to inject environment variables within tomcat configuration ?
Thanks
Solution 1:[1]
See https://tomcat.apache.org/tomcat-9.0-doc/config/systemprops.html.
TLDR; set the system property org.apache.tomcat.util.digester.PROPERTY_SOURCE to org.apache.tomcat.util.digester.EnvironmentPropertySource and the environment will be used for variable interpolation on top of system properties.
An alternative, setting system properties from environment variables in setenv.sh, unfortunately dumps the properties to the console on startup (declaring them 'command line arguments') and thus leaks any secrets shared this way.
Solution 2:[2]
I had the same problem and the answer from @jamesfry helped me to have it fixed. Though it was hard for me to find how to set "system property" for the container in Kubernetes. So sharing fix with exact code change required in your 'Deployment' based on James's answer:
containers:
- name: myapp
image: tomcat8-jre8:latest
imagePullPolicy: Always
env:
- name: JAVA_OPTS
value: -Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource
- name: DATABASE_HOST
valueFrom:
secretKeyRef:
name: my-secret
key: external.database.host
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: my-secret
key: external.database.user
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: my-secret
key: external.database.password
Note that your JNDI could directly use your env variables in the deployment file, as below:
<Resource factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
name="jdbc/mysource"
auth="Container"
type="javax.sql.DataSource"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://${DATABASE_HOST}" # secret url
username="${DATABASE_USER}"
password="${DATABASE_PASSWORD}" />
And you don't need to touch catalina.properties.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
