Certbot and Tomcat - Certificates Obtained but Not Converted to JKS and Configured with Tomcat (FIXED!)

I tried to renew the cert for my site gpsowl.com using
​sudo ./letsencrypt renew
some days ago. It seemed to work. Later I noticed cert has expired, but I can’t renew, now I get the message “Cert not yet due for renewal”.

I don’t know what to do, any ideas?

Did you reload/restart your webserver? You need to reload your web server in order for your server to start serving the renewed certificate. Right now your server is serving a Let’s Encrypt certificate that expired on May 5th (https://crt.sh/?id=84611419).

It looks Let’s Encrypt issued a certificate for your domain successfully earlier today (https://crt.sh/?id=140104828).

yes, tomcat restarted

I tried running another command I found here on the forum, didn’t seem to help. Can’t remember what it was now… did not seem to help

Are you using /etc/letsencrypt/live/gpsowl.com/ in your Tomcat config? If you paste the TLS-related portions of your config here, we can see what certificate file your server is configured to use. You might be referencing the certificate files in /etc/letsencrypt/archive by mistake.

1 Like
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true" URIEncoding="UTF-8"
           SSLCertificateFile="/etc/letsencrypt/live/fullchain.pem"
           keystoreFile="/etc/letsencrypt/live/gpsowl.com/privkey.pem"
           clientAuth="false" sslProtocol="TLS" />

It turns out that the files in live are linked to the archive, but I don’t know why. Also, the folders were readonly by root.

I’m getting this error now:

20-May-2017 21:30:26.462 SEVERE [main] org.apache.coyote.AbstractProtocol.init Failed to initialize end point associated with ProtocolHandler [“http-nio-8443”]
java.io.IOException: Invalid keystore format

"/etc/letsencrypt/live/fullchain.pem" or "/etc/letsencrypt/live/gpsowl.com/fullchain.pem"? The former doesn't exist.

Fixed the path; still getting Invalid keystore format

I added a new key (-0001) and the date on the file is a couple days ago. https://www.digicert.com/help/ says it is still expired. Don’t know what to do next.

Could you run

ls /etc/letsencrypt/live

and also

openssl x509 -in /etc/letsencrypt/live/gpsowl.com-0001/cert.pem -text -noout

?

Is it possible that you converted and imported things from /etc/letsencrypt into that avox.jks some time ago? If so, maybe your old certificate is still stored and represented within that file in some way, and then the conversion and import process would need to be repeated in connection with the certificate renewal?

Also, is there any possibility that you have another web server or reverse proxy such as an Apache, nginx, squid, or similar instance that’s actually listening directly on port 443 and then forwarding requests through to Tomcat? If so, maybe your old certificate is hard-coded in the configuration for the reverse proxy, or maybe it also needs to be restarted.

Hi @gerryscat

The fact that you were using a PEM as the keystore files makes me suspect you don’t quite understand how Java Key Stores Work

There is a fairly detailed walk through here: Using LetsEncrypt Certificates on Tomcat 8.x on Windows

Generally it’s a good idea to answer all the questions in the help section as it helps narrow down the root cause

I suspect this is what has happend

A) You have issued a new certificate for your domain (cannot verify this without your domain name)
B) Certbot has created the key and certificate in the usual location
C) You have not created the keystore out of those certificates in b
D) You have not applied your keystore to Tomcat
E) You have not restarted your tomcat. As such it’s still using the old key store with your old certificate

Andrei

Hello @gerryscat,

renew command will renew your cert but won't install it in your keystore, you need to do it manually or you can automate it in the renew process but you should provide a script to perform the needed steps to recreate your keystore with the new cert and reload your tomcat.

You are using Nio Protocol so you can't use this directive SSLCertificateFile, this is only valid for APR Protocol.

First you need to renew your cert but you already did, the problem here is that you have generated several certs

CRT ID     DOMAIN (CN)  VALID FROM              VALID TO                EXPIRES IN  SANs
141619623  gpsowl.com   2017-May-21 03:03 CEST  2017-Aug-19 03:03 CEST  88 days     gpsowl.com
                                                                                    www.gpsowl.com

140104828  gpsowl.com   2017-May-18 04:12 CEST  2017-Aug-16 04:12 CEST  85 days     gpsowl.com

133064925  gpsowl.com   2017-May-05 03:13 CEST  2017-Aug-03 03:13 CEST  72 days     gpsowl.com
                                                                                    www.gpsowl.com

So you need to identify which is the right one, I think is the one containin domain and ww domain. I suppose that the right cert containing both domains is located at /etc/letsencrypt/live/gpsowl.com/ and the cert containing only your domain is located at /etc/letsencrypt/live/gpsowl.com-0001/

To identify how many domains contains your cert can use this:

echo | openssl x509 -in /etc/letsencrypt/live/gpsowl.com/cert.pem -noout -text | grep DNS:

echo | openssl x509 -in /etc/letsencrypt/live/gpsowl.com-0001/cert.pem -noout -text | grep DNS:

Once you have identified the right cert, you need to recreate the keystore with the new key and cert.

0.- Create a dir to store your keystore, I'm using /etc/tomcat8/keystore/ for this example, you should use the path that you want.

mkdir -p /etc/tomcat8/keystore/

1.- Create a pkcs12 store (change HERETHEPASSWORD with the password you want):

openssl pkcs12 -export -in /etc/letsencrypt/live/gpsowl.com/fullchain.pem -inkey /etc/letsencrypt/live/gpsowl.com/privkey.pem -out /etc/tomcat8/keystore/gpsowl.com.p12 -password pass:HERETHEPASSWORD

2.- Import pkcs12 store into a keystore (change HERETHEPASSWORD with the password used in previous command):

keytool -importkeystore -srckeystore /etc/tomcat8/keystore/gpsowl.com.p12 -srcstoretype pkcs12 -srcstorepass HERETHEPASSWORD -destkeystore /etc/tomcat8/keystore/gpsowl.com.keystore -deststoretype jks -deststorepass HERETHEPASSWORD

3.- Configure your tomcat to use the right keystore and pass:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true" URIEncoding="UTF-8"
keystoreFile="/etc/tomcat8/keystore/gpsowl.com.keystore"
keystorePass="HERETHEPASSWORD"
clientAuth="false" sslProtocol="TLS" />

4.- Restart or reload your tomcat.

I hope this helps.

Cheers,
sahsanu

1 Like

nice summary mate :smiley:

1 Like

Thanks to other people for following up on this possibility. It sounds like there’s a consensus that this is the problem—I’ll try to keep this in mind when people are using Tomcat in the future!

$ ls /etc/letsencrypt/live
gpsowl.com/ gpsowl.com-0001/

$ openssl x509 -in /etc/letsencrypt/live/gpsowl.com-0001/cert.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
03:3b:a3:32:3d:88:7b:63:a9:ea:3d:c4:5e:e3:b8:97:23:51
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Let’s Encrypt, CN=Let’s Encrypt Authority X3
Validity
Not Before: May 18 02:12:00 2017 GMT
Not After : Aug 16 02:12:00 2017 GMT
Subject: CN=gpsowl.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:d2:28:94:f0:ad:f0:9f:4e:39:63:f7:4d:1e:22:
fd:5f:4c:1e:2d:9e:dc:67:31:d7:07:05:48:7a:3c:
30:b5:12:83:f0:29:02:57:15:e6:68:55:13:96:35:
55:11:b4:d2:f4:2f:a0:e2:ef:c4:80:62:af:7d:37:
70:fd:1a:b2:86:a3:bb:1e:c0:8d:87:62:00:92:fc:
61:1a:4e:51:1e:79:25:20:df:71:69:f9:2b:6a:97:
af:23:40:df:b0:79:65:a7:76:ec:0f:36:7a:ad:51:
01:b7:52:70:ec:52:2b:d1:bc:59:54:d2:83:f6:ac:
7c:67:c5:dd:18:93:26:e9:50:30:b4:95:2c:23:fb:
3d:64:2e:c3:c2:c9:f1:aa:9a:e4:c5:23:c7:8a:33:
20:97:a8:0e:02:bc:e9:f6:4d:c1:f4:07:34:5e:f8:
be:2c:f1:74:60:28:3f:86:d7:57:5e:c3:c6:89:96:
f9:3d:2c:ab:55:26:7e:7c:8d:cf:3a:73:0a:36:cc:
60:80:ed:16:b3:4b:99:d7:56:d4:f4:bd:c5:28:3c:
04:d5:94:3f:0c:ce:45:23:5c:8d:79:d5:d2:1c:bf:
55:7e:dd:7a:db:e0:b2:d8:57:97:fd:21:b1:e5:1a:
6a:2e:f1:00:a3:19:87:7e:55:cf:0c:5c:cc:fb:22:
15:35
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
2B:E4:C7:28:FE:EF:57:CC:48:77:2F:8A:6A:5C:A4:3C:BE:EC:71:23
X509v3 Authority Key Identifier:
keyid:A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1

        Authority Information Access:
            OCSP - URI:http://ocsp.int-x3.letsencrypt.org/
            CA Issuers - URI:http://cert.int-x3.letsencrypt.org/

        X509v3 Subject Alternative Name:
            DNS:gpsowl.com
        X509v3 Certificate Policies:
            Policy: 2.23.140.1.2.1
            Policy: 1.3.6.1.4.1.44947.1.1.1
              CPS: http://cps.letsencrypt.org
              User Notice:
                Explicit Text: This Certificate may only be relied upon by Relying Parties and only in                  accordance with the Certificate Policy found at https://letsencrypt.org/repository/

Signature Algorithm: sha256WithRSAEncryption
     70:34:d5:08:9f:6a:1d:5c:ed:5c:e6:54:a3:93:34:63:dd:55:
     7c:57:4a:cc:0c:81:be:6d:bc:02:99:e2:59:9f:6d:a5:4b:14:
     1c:1b:52:eb:45:01:7e:e9:fe:5e:9b:69:dd:db:26:ff:47:30:
     46:27:fb:01:9c:10:db:02:72:5c:ae:44:9a:c7:5c:53:d2:92:
     a8:2c:a8:7a:b7:e5:d0:6a:56:15:51:5e:28:6f:d4:a3:48:51:
     a1:d8:53:30:36:92:48:3a:fb:6b:62:86:db:1a:bf:4a:b5:2b:
     52:20:c2:78:49:a4:b1:09:22:f4:86:69:71:38:56:a8:3b:c1:
     79:80:cd:dd:83:b2:c6:ed:76:96:6e:f5:97:9d:ba:6f:9e:1a:
     1b:8b:de:15:d3:df:66:7b:d8:f3:70:dc:3e:cd:eb:c8:36:95:
     36:22:73:81:dc:f3:0d:2a:d3:95:f8:5d:15:a6:ee:76:74:d4:
     f6:ac:5e:7c:9f:9e:88:e2:75:c3:5a:46:37:99:5f:66:a0:59:
     f8:f8:44:61:aa:59:fb:3a:a6:60:26:3a:b8:3e:ef:5d:31:c1:
     c5:97:2f:01:4f:87:0f:f4:07:58:c2:c6:9d:43:f5:ca:ee:78:
     11:63:30:86:b7:bf:27:5a:07:bd:7f:48:ec:f2:b6:e4:ec:84:
     71:eb:1b:dc

I don’t understands at all… I just followed the installation instructions and bam, https worked. I didn’t even edit my server.xml file, which was very strange.
A) gpsowl.com
B) okay
C) huh - have not seen instructions for this, have a link?
D) yup
E) restarted lots of times

Thank you so much, that worked! I made a small mod, looks like:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true" URIEncoding="UTF-8"
           SSLCertificateFile="/etc/letsencrypt/live/gpsowl.com/fullchain.pem"
           keystoreFile="/etc/tomcat8/keystore/gpsowl.com.keystore"
           keystorePass="xxxxxxx" keyAlias="tomcat"
           clientAuth="false" sslProtocol="TLS" />

Hi @gerryscat,

Your are welcome, I'm glad it worked but...

As I said, you are using Nio Protocol protocol="org.apache.coyote.http11.Http11NioProtocol" and using this protocol you should not use the directive SSLCertificateFile because it is only valid if you are using APR Protocol.

If you check your logs you will see a WARNING like this:

WARNING [main] org.apache.catalina.startup.SetAllPropertiesRule.begin [SetAllPropertiesRule]{Server/Service/Connector} Setting property 'SSLCertificateFile' to '/etc/letsencrypt/live/gpsowl.com/fullchain.pem' did not find a matching property.

Also, I didn't put the keyAlias directive because if you follow the instructions I provided I've defined no alias in the keystore, so I really doubt that it can work for you, indeed tomcat should not start in port 8443 because of that and if you check your logs you will see a SEVERE error, something like this:

SEVERE [main] org.apache.coyote.AbstractProtocol.init Failed to initialize end point associated with ProtocolHandler ["http-nio-8443"]
 java.io.IOException: Alias name tomcat does not identify a key entry

So, you don't need to specify this directive. If you like this directive for some reason :wink: put the right default alias... in this case is 1.

keyAlias="1"

Cheers,
sahsanu

I’ll check the logs later.

It did not work until I added the SSLCertificateFile part, so that’s weird.