inject environment variables in tomcat catalina.properties [Kubernetes]
Asked Answered
S

2

6

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

Softener answered 9/3, 2020 at 16:16 Comment(2)
Are you expecting your configuration files to read the env vars injected in the pods? ConfigMaps get mounted as text files. If you are using it in Application or container (or even echo command) it will work, however if you are using it in text file it is recognized as string.Sunbow
yes I'm expecting that database.user and database.password in catalina.properties are resolved. Because in this same file, similar variables are used with tomcat env variables. Eg : common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"Softener
S
6

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.

Sot answered 23/9, 2020 at 23:37 Comment(3)
Thanks this helps. Question: you mentioned: environment will be used for variable interpolation "instead of" system properties. Will it be like the environment properties will be used "on top of" system properties? the documentation link you provided does not say about system properties will not be used.Whirlwind
@Whirlwind It should be "on top of" and not "instead of". The EnvironmentPropertySource JavaDoc says "NOTE: When configured the PropertySource for resolving expressions from system properties is still active."Implied
The EnvironmentPropertySource class is available from 7.0.108, 8.5.65, 9.0.45 versions, according to this answerGlobule
W
10

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.

Whirlwind answered 29/12, 2020 at 21:53 Comment(0)
S
6

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.

Sot answered 23/9, 2020 at 23:37 Comment(3)
Thanks this helps. Question: you mentioned: environment will be used for variable interpolation "instead of" system properties. Will it be like the environment properties will be used "on top of" system properties? the documentation link you provided does not say about system properties will not be used.Whirlwind
@Whirlwind It should be "on top of" and not "instead of". The EnvironmentPropertySource JavaDoc says "NOTE: When configured the PropertySource for resolving expressions from system properties is still active."Implied
The EnvironmentPropertySource class is available from 7.0.108, 8.5.65, 9.0.45 versions, according to this answerGlobule

© 2022 - 2024 — McMap. All rights reserved.