DevOps

Sharing a Secret with a Tomcat Service in ECS

AWS is pretty good, with a lot of documentation. However, often you need to spot the detail you need among a bunch of documentation that’s not wrong, but isn’t quite going to cover your use case.

Providing the low-level detail doesn’t always provide enough information to assemble a complete coherent solution.

I’ve recently been constructing some Cloudformation deployments. We want our tomcat instance, running inside a fargate container in ECS, to be able to point to the database for the deployed environment, with secret credentials.

This opens a world of pain in terms of how to safely get credentials from the right secret in secrets manager, into the config in the server.xml.

How Tomcat Can Read Environment Variables

Bear in mind that my Tomcat runs in docker… I can add this to the Dockerfile:

1
ENV JAVA_OPTS=-Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource

This turns on interpolation of environment variables in tomcat config XML file reading. So if my server.xml does something like this:

1
2
3
4
5
6
7
<Resource name="jdbc/mydatabase" auth="Container" type="javax.sql.DataSource"
          factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
          driverClassName="com.mysql.cj.jdbc.Driver"
          ...
          username="${MYSQL_USER}" password="${MYSQL_PASSWORD}"
          url="jdbc:mysql://${MYSQL_HOST}/mydb?useSSL=false"
          ... />

This means that the MYSQL_ environment variables from the container are injected into the JDBC settings.

It involved a lot of searching to find the above.

Then We Read the Secret

The secret I’m using contains the username, password and host. It’s made automatically by Cloudformation, and has its own rotation schedule. All I need to do is pluck username, password and host from it, provided I know which secret to use.

Let’s put an environment map in our Cloudformation with the secret in:

1
2
3
4
5
Mappings:
  dev:
    Database:
      # the secret dictates usernames/passwords/endpoints
      Secret: arn:aws:secretsmanager:eu-west-1:12345678:secret:database-secret-abRK8x

We have a StageName variable which dictates which environment we’re in. So now, in our fargate container definition, we just need to pluck the values from the secrets into the environment variables:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
MyEcsTask:
    Type: AWS::ECS::TaskDefinition
    Properties:
      RequiresCompatibilities:
        - FARGATE
      ContainerDefinitions:
        - Name: !Sub ${AWS::StackName}-tomcat
          Image: my-tomcat-container:latest
          PortMappings:
            - ContainerPort: 8080
              HostPort: 8080
          Secrets:
            - Name: MYSQL_USER
              ValueFrom: !Sub
                - '${secret}:username::'
                - secret: !FindInMap [!Ref StageName, Database, Secret]
            - Name: MYSQL_PASSWORD
              ValueFrom: !Sub
                - '${secret}:password::'
                - secret: !FindInMap [!Ref StageName, Database, Secret]
            - Name: MYSQL_HOST
              ValueFrom: !Sub
                - '${secret}:host::'
                - secret: !FindInMap [!Ref StageName, Database, Secret]

There’s a lot going on in the Secrets section there. The ValueFrom is using a !Sub expression to work out the secret to use, based on the current StageName using the environment map to find the right secret.

What’s also happening, though, is that the username, password and host keys from the secret are being read individually. This involves a syntax of <secret-name>:<desired-json-key>:: – those trailing ::s are very important (or it doesn’t work!).

Conclusion

The above information is available in the docs if you know where to look.

This recipe will hopefully be of some use to someone.

Published on Java Code Geeks with permission by Ashley Frieze, partner at our JCG program. See the original article here: Sharing a Secret with a Tomcat Service in ECS

Opinions expressed by Java Code Geeks contributors are their own.

Ashley Frieze

Software developer, stand-up comedian, musician, writer, jolly big cheer-monkey, skeptical thinker, Doctor Who fan, lover of fine sounds
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button