Saturday, 13 October 2018 13:06

How to Add Self-Signed Certificate to Atlassian Application Java Keystore

Written by
How to Add Self-Signed Certificate to Atlassian Application Java Keystore Steve Tsiopanos

I recently came across a situation where I needed to join Atlassian Jira and Confluence to a Synology Active Directory service 1 via a secure port (636). For this to work, the connection needed to be signed by an SSL certificate from a recognized certificate authority. However, the standard, free, method for assigning SSL certificates (in this case, LetsEncrypt) would not suffice since the certificate would need to persist for at least a year or more. This is of particular concern with applications for which updating certificate key stores will result in service downtime.  Even in a situation where a certificate was purchased a vendor signed by a Certificate Authority, one would still want to lock it in for several years.

Unfortunately, this is no longer viable as there has been an industry push within the last year to generally limit the pre-defined lifespan of such certificates 2,3. With that in mind, I had to figure out a way to use a self-signed certificate and allow Jira and Confluence to accept it when configuring a Microsoft Active Directory (Read/Write) User Directory.

Once the Synology Active Directory Server was installed and configured, the first step was to create a self-signed certificate with a reasonably long-enough lifespan as to not have to worry about it any time soon (this work is probably worthy of a full blog post, itself). Note that the goal here is to end up with an SSL search associated with the assigned Active Directory domain which can be used to secure traffic from *authorized* source. Let’s go over the layers of security:

  • Software Firewall: The Synology Firewall service should be configured to only allow port 389(unsecure)/636(secure) access from the public IP of your respective Atlassian applications.
  • Certificate Assignment: The Synology Security configuration allows you to assign a unique certificate for any service. In my case, I assigned the newly-created self-signed certificate to Active Directory service so it would be used to sign LDAPS requests over port 636.
  • Java Keystore: With Jira or Confluence, one can only configure a Microsoft Active Directory User Directory to connect via port 636/LDAPS if the certificate authority and SSL certificate are recognized.
  • Directory Administrator: You will need to securely document the domain administrator account from your Synology Active Directory Server to be used when configuring the User Directory.

With the self signed certificate assigned and the Active Directory service restarted, I moved on to the Jira and Confluence keystore configuration.

Let us start with a quick overview of how Atlassian codes and deploys its software. Historically, all applications developed by Atlassian (with the exception of recent Cloud service acquisitions) have been built on Java (implementing front-end templating libraries like Velocity) and designed to run on the JVM served by Tomcat. This has enabled Atlassian to deliver OS-agnostic installation methods, allowing administrators to install software in both Windows and Linux environments. Since the primary requirements are the JRE/JDK and persistence methods (databases like MySQL, MSSQL, etc.), it is generally up to the Atlassian System Administrator to standardize the OS and implement best practices. However, with the Java, Atlassian software also inherits the complexity and challenge of managing JVM performance parameters, Tomcat web server configuration and, as we finally get the point… the Java keystore. Since Java requires a runtime environment, generally speaking, all configuration needs to be loaded on application start-up, including any certificates which must be included in the keystore to sign HTTP client-server communication.

With the self-signed certificate assigned to the Active Directory service and the Synology Firewall configured to allow port 389/636 access from the designated Atlassian applications, we can move on to Java keystore configuration. When I first approached this issue I struggled with coming up with a quickly implemented and repeatable method for important the certificate into the respective keystore. I finally settled on a basic bash script, but I would recommend an seasoned DevOps Engineer to incorporate this work into an Ansible Playbook or SaltStack State. For reference, I have included below a sample bash script which can extract the SSL certificate from the Active Directory LDAPS service, store it locally, and inject it into the Java keystore of the respective Atlassian application.

#!/usr/bin/env bash
## This script will save a copy of the diskstation.ad.yourdomain.com SSL cert locally and import it into the JIRA Java keystore.
## ref: https://confluence.atlassian.com/kb/connecting-to-ssl-services-802171215.html

## Retrieve copy of SSL certifcate from your domain.
openssl s_client -connect ad.yourdomain.com:636 < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ad.yourdomain.com.crt

## JIRA
/opt/atlassian/jira/jre/bin/keytool -delete -keystore /opt/atlassian/jira/jre/lib/security/cacerts -alias 'ad.yourdomain.com'
/opt/atlassian/jira/jre/bin/keytool -delete -keystore /opt/atlassian/jira/jre/lib/security/cacerts -alias 'intermediateCA'
/opt/atlassian/jira/jre/bin/keytool -import -alias ad.yourdomain.com -keystore /opt/atlassian/jira/jre/lib/security/cacerts -trustcacerts -file ad.yourdomain.com.crt

## Confluence
/opt/atlassian/confluence/jre/bin/keytool -delete -keystore /opt/atlassian/confluence/jre/lib/security/cacerts -alias 'ad.yourdomain.com'
/opt/atlassian/confluence/jre/bin/keytool -delete -keystore /opt/atlassian/confluence/jre/lib/security/cacerts -alias 'intermediateCA'
/opt/atlassian/confluence/jre/bin/keytool -import -alias ad.yourdomain.com -keystore /opt/atlassian/confluence/jre/lib/security/cacerts -trustcacerts -file ad.yourdomain.com.crt

 

Requires openssl to be running on your application server.

The script above is interactive so you will need to run it and respond when prompted. Note that on first run, you may be prompted to enter or set a keystore password (the default is usually “changeit”). For everything else, you can accept the default setting and click enter until the keystores have been created / updated. As you will note in the example above, it is assumed that both Jira and Confluence run on the same server. Obviously, it would be up to you to determine where to run these commands to update the relevant Java keystores.

A word of warning: The script referenced above should be considered more as a helpful guide rather than a de facto solution. 

Once the script is run and keystores are updated, you will need to restart the respective Atlassian application services for changes to take effect. At this point, if all has gone well, you should be able to successfully connect to the Active Directory service over port 636 with your administrative credentials. Even though the instructions reference Synology Active Directory, the basic premise of updating an Atlassian application Java keystore applies to any situation where the application needs to make an *accepted* secure connection to a remote resource.

References:

1. Synology Active Directory Server https://www.synology.com/en-us/dsm/feature/active_directory 

2. “Where Did All the Three-year SSL Certificates Go?”https://www.geocerts.com/blog/where-did-all-the-three-year-ssl-certificates-go

3. CA/Browser Forum https://cabforum.org

Read 115 times Last modified on Saturday, 13 October 2018 14:14
Steve Tsiopanos

Family-smitten IT entrepreneur who enjoys running, biking, gadgets, piano & guitar, drawing and coding. Founded Annatech in 2006 and serves as DevOps Manager & Atlassian Product Owner at 14 West Global Technologies.

Certified Atlassian Professional

www.linkedin.com/in/stevetsiopanos/

Newsletter

Cron Job Starts