1

I want to connect to a postgresql server from a servlet in tomcat, using jndi.

I have added the server cert to the truststore using keytool -keystore /usr/lib/jvm/java-11-openjdk-amd64/lib/security/cacerts -alias postgresql -import -file ~/postgres.infra-kk.der where the der file is the server cert converted to der. The home directory of tomcat user is /var/lib/tomcat9. /var/lib/tomcat9/.postgresql contains the following files:

  • postgresql.crt the client certificate in pem format
  • postgresql.pk8 the client private key in der-encrypted pk8 format
  • postgresql.key the client private key in pem format

(Those are symbolic links to the real files) I can connect the database with psql with no problem.

However in tomcat I receive the following exception:

org.postgresql.util.PSQLException: FATAL: connection requires a valid client certificate

I did read Providing Certificates to Tomcat for Postgres Connection, https://jdbc.postgresql.org/documentation/head/ssl-client.html and https://jdbc.postgresql.org/documentation/head/connect.html#ssl

My datasource definition in context.xml:

<Context>
    <Resource name="jdbc/users" auth="Container"
          type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
          url="jdbc:postgresql://infra.kodekonveyor.com:5432/users?ssl=true&amp;sslkey=/keys/tomcat/privkey.pk8&amp;sslcert=/keys/tomcat/tomcat.market.pem"
          username="market" maxTotal="20" maxIdle="10"
      maxWaitMillis="-1"/>
</Context>

(The filenames above are the real files)

I still receive the same error message.

Tomcat does not seem to take a look at any of the files given to it. /tmp/foo contains the strace -f output of a whole tomcat session

# egrep "\.der|tomcat.market|privkey|pem|pk8" /tmp/foo
13777 read(164, "rimary_root_ca.pem\0\0\1m\305\23\16\334\0\5X.50"..., 8192) = 8192
13777 read(164, "ion_authority_rsa.pem\0\0\1m\305\23\20\355\0\5X"..., 131072) = 26964

(the file with handle 164 above is /usr/lib/jvm/java-11-openjdk-amd64/lib/security/cacerts)

This is an Ubuntu system, with libpostgresql-jdbc-java:9.4.1212-1 installed. The webapp have this dependency:

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>9.4.1212</version>
</dependency>

Actually I have no idea which one tomcat uses for the datasource.

Question: how do I tell Tomcat that there are client certificates and where they are?

Árpád Magosányi
  • 1,394
  • 2
  • 19
  • 35

1 Answers1

2

The problem was that the postgres jar was too old.

Deleting libpostgresql-jdbc-java from the system, downloading and installing 42.2.8 from https://jdbc.postgresql.org/download.html (I could not find maven coordinates for it) solved the problem of not finding the certificate.

I also had to add root.crt to .postgresql, but from the error log it was straightforward.

Now the problem is that the private key cannot be read because no security provider understands it. See configure tomcat/hibernate to have a cryptographic provider supporting 1.2.840.113549.1.5.13 .

Árpád Magosányi
  • 1,394
  • 2
  • 19
  • 35