Let’s Encrypt on an API Server

home-oss-logos-tomcatby Mike Robinson
Professor & Head of Systems
Consortium Library
University of Alaska Anchorage

This recipe is part of a series about my experiences moving our library servers and services to Let’s Encrypt for TSL/HTTPS certificates.  This  recipe will be describing how I installed certificates from Let’s Encrypt on an API server, more specifically an Apache Tomcat 7 web application called Web Services from SirsiDynix which is installed on a local server running CentOS 6.  At our library, Web Services provides integration between two SirsiDynix products–Enterprise OPAC, BookMyne mobile application–and the library management system, mostly for “my account” functions such as holds and renewals.  In addition, we use Web Services to integrate real-time availability from the the library management system in the search results for Enterprise, Summon, and Ebsco Discovery Services.

Note: these instructions are for Enterprise installed on a local server, if your Web Services server is hosted by SirsiDynix, you would need to work with them to install HTTPS certificates.

Here are the overall steps on a local Web Services server that you have shell access to with root or appropriate sudo privileges.

  • Get the client application.
  • Use the client application to generate certificates.
  • Configure Tomcat to use the certificates.
  • Set up a routine for renewal of certificates.

letsencryptGet the Client Application

Let’s Encrypt recommends using a client application called certbot to obtain certificates.   For a number of distros (Ubuntu, ArchLinux, Gentoo, CentOS RHEL 7), the client is available via the common package manager for that distro and can be installed with one command.  Our server is still on CentOS 6, so we have a few extra steps.

  • Enable the EPEL (Extra Packages for Enterprise Linux) repository.  This will make additional dependencies available to the certbot client.
$ sudo yum install epel-release
  • Create a directory for where the certbot client will live, this can be anywhere but I selected /usr/local/ and named the directory letsencrypt.
$ sudo mkdir /usr/local/letsencrypt
$ cd /usr/local/letsencrypt
  • Download the certbot client and make it executable.
$ sudo wget https://dl.eff.org/certbot-auto
$ sudo chmod a+x certbot-auto

Generate Certificates

The certbot client is actually a script that performs a number of tasks, see this previous recipe for more details.

  • Run the certbot client to install certificates in manual mode.
$ cd /usr/local/letsencrypt
$ sudo ./certbot-auto --standalone --standalone-supported-challenges http-01 certonly -d jlc-service.uaa.alaska.edu

The  –standalone switch tells certbot to install the certificates in the /etc/letsencrypt/ directory.  The –standalone-supported-challenges http-01 switch tells certbot to bind temporarily to port 80 to verify that you own the server.  Therefore port 80 must be available via the firewall and have no services running on it during this step.

  • Answer the questions the client will ask and wait for it to finish.
email address?
I put in my email address.
Agree to Let's Encrypt's terms
yes

Configure Tomcat to Use the Certificates

There are two possible methods for installing HTTPS certificates for Apache Tomcat depending on how the application is configured:

  • Direct access – configure Tomcat to use a Java Key Store that houses the certificates
  • Proxy access – configure Apache to use the certificates

Web Services uses direct access to the Tomcat application so we be creating a Java Key Store to house the certificates.  Our previous recipe on installing Let’s Encrypt certificates on an OPAC Server covered configuring Tomcat for proxy access via Apache.

  • Install Java Development Kit version 1.7 or higher so that TLSv1.2 is available.
$ sudo yum install java-1.8.0-openjdk
  • Change directory to where your Tomcat configuration files are located, in our case that’s in /opt.
$ cd /opt/tomcat/conf
  • Bundle Let’s Encrypt certificates into a single file in the PKCS #12 format.
$ sudo openssl pkcs12 -export -in /etc/letsencrypt/live/jlc-service.uaa.alaska.edu/fullchain.pem -inkey /etc/letsencrypt/live/jlc-service.uaa.alaska.edu/privkey.pem -out <boundcertificates>.p12 -name <aliasname>
  • Answer the question to create the export password.
Enter export password: <firstpassword>
Verify password: <firstpassword>
  • Create the Java Key Store.
$ sudo keytool -importkeystore -deststorepass <secondpassword> -destkeypass <thirdpassword> -destkeystore <keystorename>.jks -srckeystore <boundcertificates>.p12 -srcstoretype PKCS12 -srcstorepass <firstpassword> -alias <aliasname>

The <boundcertificates>, <aliasname>,<firstpassword>, <secondpassword>, <thirdpassword>, and <keystorename> that you assign in these two commands should be recorded and kept in a safe place so these steps can be repeated again when needed.

  • Edit the Tomcat configuration file to tell it to use the certificates on port 8443.
$ sudo nano server.xml

In our case, there was a default entry for 8443 using vendor self-signed certificates and configuration which allowed insecure SSL v2 & v3.

<Connector port="8443"
 protocol="HTTP/1.1"
 SSLEnabled="true"
 maxThreads="150"
 connectionTimeout="20000"
 URIEncoding="UTF-8"
 compression="on"
 compressionMinSize="1000"
 noCompressionUserAgents="gozilla, traviata"
 compressableMimeType="text/html,text/xml,text/css,text/javascript"
 xpoweredBy="false"
 scheme="https"
 secure="true"
 keystoreFile="keystore"
 keystorePass="secret"
 clientAuth="false"
 sslProtocol="TLS"
 server="SirsiDynix IlsWS"
 />

We changed it to the following.

<Connector port="8443"
 protocol="HTTP/1.1"
 SSLEnabled="true"
 maxThreads="150"
 connectionTimeout="20000"
 URIEncoding="UTF-8"
 compression="on"
 compressionMinSize="1000"
 noCompressionUserAgents="gozilla, traviata"
 compressableMimeType="text/html,text/xml,text/css,text/javascript"
 xpoweredBy="false"
 scheme="https"
 keystoreFile="/opt/tomcat/conf/<keystorename>.jks"
 keystorePass="heckle"
 keyAlias="tomcat"
 keyPass="<thirdpassword>"
 clientAuth="false"
 sslEnabledProtocols = "TLSv1.2,TLSv1.1,TLSv1"
 ciphers="TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
     TLS_RSA_WITH_AES_128_CBC_SHA,
     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
     TLS_RSA_WITH_AES_128_CBC_SHA256,
     TLS_RSA_WITH_AES_128_GCM_SHA256,
     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
     TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
     TLS_RSA_WITH_AES_256_CBC_SHA,
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
     TLS_RSA_WITH_AES_256_CBC_SHA256,
     TLS_RSA_WITH_AES_256_GCM_SHA384,
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
     TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
 server="SirsiDynix IlsWS"
 />
  • Restart Tomcat service
$ sudo service Tomcat7 restart
  • jlc-service-ssltestTest the certificates to make sure they are installed correctly for the domain.
https://www.htbridge.com/ssl/?id=f22d84bbcf50bb5c265cf125412f1e3626e90271101601b4b9130170c7844601

Note: I normally use https://www.ssllabs.com/ssltest/  but it only supports testing on port 443.  HT Bridge provides testing on any port you specify.

That’s it, our library API server is now using free HTTPS certificates issued by Let’s Encrypt.  We can now work on moving our production OPAC server to HTTPS (we covered moving our test OPAC server to HTTPS in the previous recipe).

Certificate Renewal

Let’s Encrypt will only issue certificates for 90 days for some good reasons but this comes as quite a shock to administrators who are used to  1-3 year renewal periods.  The idea is that renewal will be automatic so that you will only need to manually deal with certificates when first issuing them or when making changes to domain names.

  • Screenshot - 07262016 - 01:43:45 PMPerform a dry-run to renew certificates without making a real request.  You should get a message that the test succeeded.
$ cd /usr/local/letsencrypt
$ sudo ./certbot-auto renew --dry-run
  • Add a cron or systemd job to run the command automatically.  The certificates will only renew if they are going to expire in 30 days or less.  Let’s Encrypt recommends running the renewal command twice a day.  I’m old school so decided to use crontab.

$ sudo crontab -e

Here is an example entry to run renewal once a day at 4:25am.
25 04 * * * /usr/local/letsencrypt/./certbot-auto renew –quiet

  • Bundle the renewed certificates into a single PKCS file and create (i.e. replace) the Java Key Store using the steps outlined above and restart Tomcat service.  It should be fairly straightforward to create a bash script that performs these steps and schedule it to run automatically.

Next Recipe

This completes the initial series of recipes on installing Let’s Encrypt certificates on a variety of local servers at our library.   Other recipes I plan on trying in the future are:

  • Best practices for preparing your website to migrate to HTTPS
  • Trying to install Let’s Encrypt certificates on ILS server
  • Trying to install Let’s Encrypt certificates on several different commercial Web hosting platforms
  • Trying to install Let’s Encrypt certificates on other types of servers (VPN, Squid proxy, mail)

So stay tuned!