Connecting to SSL services

This Knowledge Base article was written specifically for the Atlassian Server platform. Due to the Restricted functions in Atlassian Cloud apps, the contents of this article cannot be applied to Atlassian Cloud applications.

The content on this page relates to platforms which are not supported. Consequently, Atlassian Support cannot guarantee providing any support for it. Please be aware that this material is provided for your information only and using it is done so at your own risk.

This page describes how to get web applications like JIRA and Confluence connecting to external servers over SSL, via the various SSL-wrapped protocols. For instance, you may want to:

  • Refer to an https://... URL in a Confluence macro.
  • Use an IMAPS server to retrieve mail in JIRA.
  • Use SMTP over SSL (SMTPS) to send mail in JIRA.
  • Connect to a LDAP directory over SSL.
  • Set up Application Links over SSL.

This does not cover running your application over SSL. Please see your product's documentation to run it over SSL:

On this page:

Problem Symptoms

Attempting to access URLs that are encrypted with SSL (for example HTTPS, LDAPS, IMAPS) throws an exception and your application refuses to connect to it. For example:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
 at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:441)
 at javax.mail.Service.connect(Service.java:233)
 at javax.mail.Service.connect(Service.java:134)

This is the same as the following error that's generated in Chrome when visiting a page that's encrypted with a self-signed certificate, except Java can't "Proceed anyway", it just refuses the certificate:

The Cause

Whenever your application attempts to connect to another application over SSL (e.g.: HTTPS, IMAPS, LDAPS), it will only be able to connect to that application if it can trust it. The way trust is handled in the Java world (this is what your application is written in) is that you have a keystore (typically $JAVA_HOME/lib/security/cacerts) or also known as the trust store. This contains a list of all the known CA certificates and Java will only trust certificates that are signed by those CA certificate or public certificates that exist within that keystore. For example, if we look at the certificate for Atlassian:

We can see the *.atlassian.com certificate has been signed by the intermediate certificates, DigiCert High Assurance EV Root CA and DigiCert High Assurance CA-3. These intermediate certificates have been signed by the root Entrust.net Secure Server CA. Those three certificates combined are referred to as the certificate chain. As all of those CA certificates are within the Java keystore (cacerts), Java will trust any certificates signed by them (in this case, *.atlassian.com). Alternatively, if the *.atlassian.com certificate was in the keystore, Java would also trust that site.

This problem comes from a certificate that is either self-signed (a CA did not sign it) or the certificate chain does not exist within the Java keystore. Subsequently, your application doesn't trust the certificate and fails to connect to the application.

Resolution

In order to resolve this, the public certificate need to be imported in the Java keystore that your application uses. In the example above, this is *.atlassian.com and we cover how to install it below.

There are 2 ways to import a public SSL certificate into a JVM:

Using Portecle

  1. Download and install the Portecle app onto the server that runs your application.
    (warning) This is a third-party application and not supported by Atlassian.
  2. Ensure the <JAVA_HOME> variable is pointing to the same version of Java that your application uses. See our Setting JAVA_HOME docs for further information on this.
    (info) If running on a Linux/UNIX server, X11 will need to be forwarded when connecting to the server (so you can use the GUI), as below:

    ssh -X user@server
  3. Select the Examine menu and then click Examine SSL/TLS Connection:
  4. Enter the SSL Host and Port of the target system:
  5. Wait for it to load, then select the public certificate and click on PEM:
  6. Export the certificate and save it.
  7. Go back to the main screen and select the Open an existing keystore from disk option, select cacerts (for example $JAVA_HOME/lib/security/cacertsthen enter the password (the default is changeit).
  8. Select the Import a trusted certificate into the loaded keystore button:
  9. Select the certificate that was saved in step 6 and confirm that you trust it, giving it an appropriate alias (e.g.: confluence).
    1. You may hit this error: 
    2. If so, hit OK, and then accept the certificate as trusted.
  10. Save the Key Store to disk:
  11. Restart your application.
  12. Test that you can connect to the host.

Command Line Installation

  1. Fetch the certificate, replacing google.com with the FQDN of the server JIRA is attempting to connect to:
    Unix:

    openssl s_client -connect google.com:443 < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt

    Windows:

    openssl s_client -connect google.com:443 < NUL | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt

    (info) The command above will only be executed if you have Sed for Windows as well as OpenSSL installed on your environment. If you don't have Sed or OpenSSL or you don't want to install it, use the instructions below as an alternative. Issue the following command:

    openssl s_client -connect google.com:443

    Save the output to a file called public.cert. Edit the the public.cert file so it contains only what is between the BEGIN CERTIFCATE and END CERTIFICATE lines. This is how your file should look like after you edited it:

    -----BEGIN CERTIFICATE-----
    < Certificate content as fetched by the command line. 
    Don't change this content, only remove what is before 
    and after the BEGIN CERTIFICATE and END CERTIFICATE. 
    That's what your Sed command is doing for you :-) >
    -----END CERTIFICATE-----
  2. Import the certificate:

    <JAVA_HOME>/bin/keytool -import -alias <server_name> -keystore <JAVA_HOME>/jre/lib/security/cacerts -file public.crt

    Then enter the password if prompted (the default is changeit).

 

Alternative KeyStore Locations

Java will normally use a system-wide keystore in $JAVA_HOME/jre/lib/security/cacerts, but it is possible to use a different keystore by specifying a parameter, -Djavax.net.ssl.trustStore=/path/to/keystore, where '/path/to/keystore' is the absolute file path of the alternative keystore. Information on how to configure JIRA startup variables can be found here.

However, setting this is not recommended because if Java is told to use a custom keystore (eg. containing a self-signed certificate), then Java will not have access to the root certificates of signing authorities found in $JAVA_HOME/jre/lib/security/cacerts, and accessing most CA-signed SSL sites will fail. It is better to add new certificates (eg. self-signed) to the system-wide keystore (as above).

Debugging

Problems are typically one of two forms:

  • The certificate was installed into the incorrect keystore.
  • The keystore does not contain the certificate of the SSL service you're connecting to.

 

Last modified on Jan 6, 2017

Was this helpful?

Yes
No
Provide feedback about this article

Not finding the help you need?

Ask the community

Powered by Confluence and Scroll Viewport.