The CheckTheCrowd web application is hosted on Apache Tomcat which provides a pretty good, albeit generic documentation on how to achieve this setup.
In summary, enabling SSL on Tomcat requires three things:
- Creating a Java keystore which contains the private key that Tomcat would use to start SSL handshakes
- Ensuring that you or your website owns the private key by having it signed by a trusted authority which in turn, issues a digital certificate verifying your ownership of the key
- Configuring a Tomcat connector to listen on HTTPS from a specified port
Thankfully, I learned about StartSSL which provides free SSL certificates with one year validity (a new one can be generated upon expiry).
Below are the steps I took to set-up Tomcat SSL using StartSSL certificates.
Disclaimer: I learned most of these steps from this blog post.
1. Creating the Java Keystore File (.jks)
As per the Tomcat documentation, the first thing I needed to do was to generate a Java keystore which would hold my private key. This was done by using the keytool command that is part of JDK.
keytool -genkey -keysize 2048 -keyalg RSA -sigalg SHA1withRSA \ -alias [name of server] -keystore [name of keystore].jks \ -keypass [password] -storepass [password] -dname "CN=[domain name], \ OU=Unknown, O=[website], L=[city], ST=[state], C=[country]"Note that due to a Tomcat limitation, the keypass and storepass must be the same. The dname entry is optional; if not provided, these details will be asked by keytool during the process.
keytool -genkey -keysize 2048 -keyalg RSA -sigalg SHA1withRSA \ -alias webserver -keystore checkthecrowd.jks \ -keypass ****** -storepass ****** -dname "CN=checkthecrowd.com, \ OU=Unknown, O=CheckTheCrowd, L=Singapore, ST=Unknown, C=SG"At this point, my keystore already contains the private key required by Tomcat to start an SSL connection.
I can already start using this keystore to enable SSL in Tomcat, but a rogue entity can hijack the connection and pretend that his private key was issued by CheckTheCrowd. This rogue entity can then trick my users that they are securely connected to CheckTheCrowd when in fact they are connected to something else.
To solve this, I need to acquire a signed certificate to prove that my private key is associated to my domain (checkthecrowd.com).
2. Creating a Certificate Request File (.csr)
A certificate request is submitted to a certificate provider and an SSL certificate is generated based on this file.
keytool -certreq -alias [name of server] -file [name of request].csr \ -keystore [name of keystore].jksNote that this command would ask for the password previously set for the keystore.
keytool -certreq -alias webserver -file checkthecrowd.csr \ -keystore checkthecrowd.jks
3. Submitting the Certificate Request to StartSSL
I needed to signup for an account in order to use StartSSL. Signing-up involves generating a signed private key which proves my identity. Here onwards, the key is used by StartSSL to authenticate my access to their website.
Note that it is important to keep a back-up copy of this private key for future use. This file needs to be imported on all computers used to access StartSSL.
|Figure 1: StartSSL|
Once I have an account, I can use the Control Panel to generate my certificate. The first step is to validate that I own the domain checkthecrowd.com. The aptly named Validation Wizard takes care of this.
Once my domain is validated, I used the Certificates Wizard to submit my certificate request (.csr file):
- Select Web Server SSL/TLS Certificate.
- Because I already have a private key and a certificate request, I skip the next screen
- I pasted the contents of my certificate request (.csr file) to the text area provided
- When finished, the generated certificate is displayed on another text area -- I copied this and saved to a file called ssl.crt.
The next step is import the generated certificate to my keystore. The StartSSL certificate chain also needed to be imported.
The StartSSL certificate chain can be downloaded from:
I again used keytool to import these certificates:
keytool -import -alias [ca alias] -file [ca file].cer \ -keystore [keystore name].jks -trustcacerts keytool -import -alias [class1 alias] -file [class1 file].pem \ -keystore [keystore name].jks -trustcacerts keytool -import -alias [name of server] -file ssl.crt \ -keystore [keystore name].jksThe first two commands imported the certificate chain as trusted certificates, the last command imported the signed certificate.
keytool -import -alias startsslca -file ca.cer \ -keystore checkthecrowd.jks -trustcacerts keytool -import -alias startsslca1 -file sub.class1.server.ca.pem \ -keystore checkthecrowd.jks -trustcacerts keytool -import -alias webserver -file ssl.crt \ -keystore checkthecrowd.jksListing the contents of my keystore verified that I have 3 certificates:
# keytool -list -keystore checkthecrowd.jks webserver, Aug 5, 2013, PrivateKeyEntry, Certificate fingerprint (SHA1): [...] startsslca, Aug 5, 2013, trustedCertEntry, Certificate fingerprint (SHA1): [...] startsslca1, Aug 5, 2013, trustedCertEntry, Certificate fingerprint (SHA1): [...]
5. Configure Tomcat with SSL
Enabling SSL with Tomcat involves creating a new connector which listens to HTTPS connections. This connector needs to know the location of the keystore file as well as the password to access the keystore.
For convenience, I placed my keystore under $TOMCAT_HOME.
<!-- Define a SSL HTTP/1.1 Connector on port 8443 This connector uses the JSSE configuration, when using APR, the connector should be using the OpenSSL style configuration described in the APR documentation --> <Connector protocol="HTTP/1.1" port="8443" maxThreads="200" scheme="https" secure="true" SSLEnabled="true" keystoreFile="checkthecrowd.jks" keystorePass="******" clientAuth="false" sslProtocol="TLS"/>Note that by default, the Tomcat HTTPS port is 8443.
That's all there is to it! After bouncing Tomcat, I am now able to access CheckTheCrowd via HTTPS from port 8443: https://checkthecrowd.com:8443/.
The next step is to configure Apache httpd to forward HTTPS requests to port 8443. I still haven't figured out how to do this yet, so if you have an idea, let me know!