Problem
You have received a RSA certificate from your organization to enable HTTPS within Sonatype Nexus Repository 2 & 3 or Sonatype IQ Server. You've imported the certificate into a Java keystore file and pointed the Jetty configuration at it.
The server appears to start up fine without errors, and the logs indicate that the server is listening on the secure port. You have confirmed that the server is listening on that port with network tools (netstat, lsof).
However, when you access the secure port in a web browser or command line tool, even from the same host as the server, you can't connect to the secure port. What is going wrong?
Symptoms
Nexus Repository Manager Server or Sonatype IQ Server appears to start on the secure port without error, with default log messages similar to:
*SYSTEM org.eclipse.jetty.util.ssl.SslContextFactory - Enabled Protocols [TLSv1, TLSv1.1, TLSv1.2] of [SSLv2Hello, SSLv3, TLSv1, TLSv1.1, TLSv1.2] *SYSTEM org.eclipse.jetty.server.AbstractConnector - Started InstrumentedSslSelectChannelConnector@0.0.0.0:8070
If the server is started with low level network logging by using -Djavax.net.debug=ssl, and an https connection is attempted to it, the server side stderr log will contain:
%% Initialized: [Session-2, SSL_NULL_WITH_NULL_NULL] qtp1617118153-268, fatal error: 40: no cipher suites in common javax.net.ssl.SSLHandshakeException: no cipher suites in common %% Invalidated: [Session-2, SSL_NULL_WITH_NULL_NULL] qtp1617118153-268, SEND TLSv1.2 ALERT: fatal, description = handshake_failure qtp1617118153-268, WRITE: TLSv1.2 Alert, length = 2 qtp1617118153-268, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: no cipher suites in common
Java keytool client commands fail with "No certificate from the SSL server":
> keytool -printcert -sslserver localhost:8070 -v keytool error: java.lang.Exception: No certificate from the SSL server java.lang.Exception: No certificate from the SSL server at sun.security.tools.keytool.Main.doPrintCert(Main.java:2429) at sun.security.tools.keytool.Main.doCommands(Main.java:1069) at sun.security.tools.keytool.Main.run(Main.java:343) at sun.security.tools.keytool.Main.main(Main.java:336) Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:992) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153) at sun.security.provider.certpath.ssl.SSLServerCertStore.engineGetCertificates(SSLServerCertStore.java:109) at java.security.cert.CertStore.getCertificates(CertStore.java:151) at sun.security.tools.keytool.Main.doPrintCert(Main.java:2418) ... 3 more Caused by: java.io.EOFException: SSL peer shut down incorrectly at sun.security.ssl.InputRecord.read(InputRecord.java:505) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973) ... 12 more
Web browsers cannot load the application user interface on the secure port - for example:
Google Chrome may report "unexpectedly closed the connection":
Google Chrome may also report: ERR_SSL_VERSION_OR_CIPHER_MISMATCH
Firefox may report the connection "was interrupted while the page was loading":
Firefox may report: "Cannot communicate securely with peer: no common encryption algorithm(s). Error code: SSL_ERROR_NO_CYPHER_OVERLAP
Safari reports "can't establish a secure connection to the server":
curl commands receive an error: "Server aborted the SSL handshake":
> curl -v https://localhost:8070 * Rebuilt URL to: https://localhost:8070/ * Trying ::1... * Connected to localhost (::1) port 8070 (#0) * Server aborted the SSL handshake * Closing connection 0 curl: (35) Server aborted the SSL handshake
wget commands report "Unable to establish SSL connection"
> wget https://localhost:8070 --2016-08-10 12:23:07-- https://localhost:8070/ Resolving localhost... ::1, 127.0.0.1, fe80::1 Connecting to localhost|::1|:8070... connected. Unable to establish SSL connection.
Cause
The cause is that you were likely provided a certificate file only, instead of
- a PKCS12 formatted keystore file containing both the private key and certificate or
- a certificate with a complete certificate chain, which includes your organization's intermediary signing authority certificate
Please see the note in the Jetty documentation:
You need both the private key and the certificate in the JSSE keystore. You should load the certificate into the keystore used to generate the CSR with keytool. If your key pair is not already in a keystore (for example, because it has been generated with OpenSSL), you need to use the PKCS12 format to load both key and certificate (see PKCKS12 Keys &Certificates).
A giveaway that you were given a single public certificate is that the aliased entry in the Jetty keystore file in which you imported the certificate shows the following:
Entry type: trustedCertEntry
... instead of ...
Entry type: PrivateKeyEntry
You can print the keystore contents by using the keytool -list -v -keystore mykeystorefile.jks
command.
Solution
Contact the team who gave you the certificate file and ask them to review the Jetty documentation above. Stipulate that in order for Sonatype products to terminate SSL connections, Java keystore files require the private key used to generate the Certificate Signing Request or a complete certificate chain including all the intermediate CA certificates.
You may notice generating a self-signed certificate using keytool does not have this problem. This is because the keytool -gencert command creates a private key by default.
How can I tell if I was given a PKCS12 private key + certificate?
Use a keytool command to check if the file you were given was a valid PKCS12 keystore file.
> keytool -list -keystore the-file-you-were-given-by-your-certificate-team.pkcs12 -storetype PKCS12
If this command errors, or gives output that does not indicate the contents contain a PrivateKeyEntry, then you need to check the file with your certificate issuer.
How can I tell if I was given a only a single certificate?
Use a keytool command:
> keytool -printcert -file the-file-you-were-given-by-your-certificate-team.pem -rfc
If the output contains only 1 line that reads
-----BEGIN CERTIFICATE-----
...then this is a single certificate, not signed by an intermediary certificate authority or ROOT CA.