SSL Certificate Guide

Transport Layer Security (TLS) Self-Signed Certificates

Self-signed server TLS certificates are useful for testing server TLS configuration or for personal use when encrypting communication over HTTP.

These types of certificates are considered untrustworthy because the certificate identity has not been signed/verified by a third party certificate authority (CA). Otherwise, a self-signed certificate still ensures that communication over HTTPS is encrypted.

For long term server use, Sonatype recommends getting a certificate signed by a CA.

Generating Self Signed Server TLS Certificates

The following steps use Oracle Java 7+ keytool (Unix/Windows) to generate self-signed server certificates which can be used with Sonatype server products.

Openssl is needed only when creating certificates for use in a reverse proxy such as Apache or nginx.

  1. Generate public private key pair using keytool:

    keytool -genkeypair -keystore example.jks -storepass password -alias example.com \
     -keyalg RSA -keysize 2048 -validity 5000 \
     -dname 'CN=*.example.com, OU=Sonatype, O=Sonatype, L=Unspecified, ST=Unspecified, C=US' \
     -ext 'SAN=DNS:nexus.example.com,DNS:clm.example.com,DNS:repo.example.com,DNS:www.example.com'

    Output: example.jks

  2. Generate PEM encoded public certificate file using keytool:

    keytool -exportcert -keystore example.jks -alias example.com -rfc > example.cert
    

    Output: example.cert

  3. Convert our Java specific keystore binary".jks" file to a widely compatible PKCS12 keystore ".p12" file:

    keytool -importkeystore -srckeystore example.jks -destkeystore example.p12 -deststoretype PKCS12
    

    Output: example.p12

    (Optional) List and verify new keystore file contents:

    keytool -list -keystore example.p12 -storetype PKCS12
  4. (Optional) Extract pem (certificate) from ".p12" keystore file ( this is same as step 2, but openssl spits out more verbose contents ):

    openssl pkcs12 -nokeys -in example.p12 -out example.pem
    

    Output: example.pem

  5. Extract unencrypted private key file from ".p12" keystore file:

    openssl pkcs12 -nocerts -nodes -in example.p12 -out example.key
    

    Output: example.key

Configuring SSL Server Certificates

Sonatype Nexus

Configuring Nexus SSL

Configuring Nexus and Reverse Proxies

Eclipse Jetty

Eclipse Jetty

Apache httpd

Use either:

  SSLCertificateFile "example.pem"
  SSLCertificateKeyFile "example.key"

or

  SSLCertificateFile "example.cert"
  SSLCertificateKeyFile "example.key"

Nginx

Use either:

ssl_certificate example.pem;
ssl_certificate_key example.key;

or

ssl_certificate example.cert;
ssl_certificate_key example.key;

What are keystores and truststores?

There are two kinds of key or certificate storage files used by Oracle Java. Oracle has a good reference defining keystores and truststores.

Where does a Java client load trusted certificates from?

A Java client program loads trusted certificates from the following locations, in this order:

  1. a file specified by the system property javax.net.ssl.trustStore. This property is not set by default. If set, but the file does not exist, no truststore is used.
  2. if java-home/lib/security/jssecacerts is a valid file, trusted certificates are loaded from here. This file does not exist by default but can be created by a user using keytool.
  3. java-home/lib/security/cacerts exists by default. It is pre-loaded with well known public certificate authority root certificates that allow a client program to trust sites which have certificates signed by them. If for some reason it is missing, there will be no trusted certificates loaded into the client.

Oracle provides a summary about Customizing the Default Keystores and Truststores, Store Types and Store Passwords

When does the file ~/.keystore get used?

The keytool program creates or reads this file whenever the -keystore argument is not provided to the keytool program.

Java client programs do not normally read this file when looking for trusted certificates. This file is intended to hold user specific private keys.

Therefore, importing a remote server certificate into ~/.keystore will not usually resolve issues where trust of the remote server cannot be established . ie. solving PKIX path building failed errors.

Common keytool Operations

Here are some common keytool operations that are needed when managing SSL certificates.

Always use the full path to your keytool executable and your intended target keystore file when executing keytool. Do this with the -keystore parameter. This helps avoid confusion about which keystore files are being modified.
Usually you will want the keytool to manipulate the system wide truststore file at java-home/lib/security/jssecacerts or java-home/lib/security/cacerts

If you are using a system wide default JSSE keystore location on either a Linux,Solaris or OSX platform, you must run the commands as the root user. You can do this either by changing to the root user (su -) first, or by using the sudo command: sudo [command].

On Windows, open a command prompt as an Administrator.

The default password used by Java for the built-in keystore is changeit. If your key-store uses a different password, you'll need to specify that password as the -storepass parameter.

Getting a Remote Certificate

This command connects to a remote server on a specific port and prints the SSL certificate to a file.

keytool -printcert -rfc -sslserver example.com:443 > example.pem

Examining Certificate File Details

To verify the validity of a certificate, you must visually examine the contents in human readable (non-rfc) form. Each certificate in the chain will be demarcated by a line containing Certificate[n]:, where n is the order number of the certificate.

keytool -printcert -file example.pem

Getting a Remote Certificate Through A HTTP Proxy Server

Sometimes your HTTP Proxy server may be modifying the remote certificate. In that case it is important that keytool uses the proxy server when fetching the certificate. Use special -J options to do this.

keytool -J-Dhttps.proxyHost=<proxy_hostname> -J-Dhttps.proxyPort=<proxy_port> -printcert -rfc -sslserver <remote_host_name:remote_ssl_port>

On recent Windows systems and on Gnome 2.x systems it is possible to tell keytool to use the system proxy settings (both these systems let you set proxies globally through their user interface). In that case, use the following:

keytool -J-Djava.net.useSystemProxies=true -printcert -rfc -sslserver <remote_host_name:remote_ssl_port>

Replace <proxy_hostname> and <proxy_port> with the HTTP proxy server that Nexus is configured with under Administration -> Server. Replace <remote_host_name:remote_ssl_port> with one of the remote host and port having the certification problem. You can omit the port if it is the default 443.

Getting a Remote Certificate of a HTTP Proxy Server

Configuring a client to trust the HTTP proxy server certificate is often much better than trusting every unique remote certificate accessed through the proxy.

Use the command as described in Getting a Remote Certificate Through A HTTP Proxy Server.

Then, examine the certificate and look for the Certificate[n]: entry that has an Issuer: line that correlates to your HTTP proxy server. Usually this will be the last certificate.

You can then count that number of entries down, demarcated by -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines, in the encoded certificate file, and copy that certificate entirely to a new file ( including the begin and end certificate parts ). The new file then contains only the certificate of your HTTP proxy server.

At this point you may wish to examine it and then import the HTTP proxy certificate using the standard command into a keystore.

Import a Certificate to a Truststore

Once you have the remote certificate, it can be imported into the default JVM truststore using the default store password.

If you are using a specific keystore, change the storepass and keystore used:

keytool -importcert -file example.pem -alias example.com -storepass changeit -keystore $JAVA_HOME/lib/security/cacerts

Explicitly Trusting a Self-Signed or Private Certificate in a Java Based Client

If you generate a self-signed certificate, and want a Java based client to explicitly trust this certificate, then you need to make sure the trust store used your client, trusts at least one member of the certificate chain.

Suppose you have a server at https://example.com using a self-signed or private certificate:

  1. (Required) Get the certificate from the server into a PEM encoded file on your Java client host:
    keytool -printcert -rfc -sslserver example.com > example.pem
    
  2. (Optional/Advised) Inspect the certificate you just downloaded to verify it looks OK:
    keytool -printcert -file example.pem
    
  3. (Required) Import the certificate into the default Java truststore location under a relevant alias, using the default truststore password:
    keytool -importcert -file example.pem -alias example.com -storepass changeit -keystore $JAVA_HOME/lib/security/cacerts
    

Forcing Apache Maven to Implicitly Trust a Self-Signed Certificate

Apache Maven has a system property maven.wagon.http.ssl.insecure that can be set to implicitly trust a self-signed certificate from a HTTPS remote repository.

The system property will only work if:

  1. it is set in the environment variable MAVEN_OPTS
  2. the remote certificate has a single certificate in the certificate chain ( ie. self-signed)

The property will not work at mvn invocation time. For example, this will not work: mvn -Dmaven.wagon.http.ssl.insecure=true install

You must set this instead inside the MAVEN_OPTS environment variable value.

One method to do this explicitly to Maven, is to create a file $HOME/.mavenrc ( or on Windows %HOME%/.mavenrc ) and set MAVEN_OPTS in there. This file will be sourced every time you invoke Maven.

Forcing Apache Maven to Trust A Certificate Issued by An Organizational Certificate Authority

When your organization has a private certificate authority issuing server certificates, a common problem is that the system property maven.wagon.http.ssl.insecure will not help. This is because the certificate chain used by the Nexus HTTPS connection contains more than one certificate. The certificate chain hierarchy might look something like this:

root CA (root organizational certificate authority)
  - sub-org CA 1 (sub-organizational certificate authority)
    - sub-org CA 2 (sub-organizational certificate authority)
      - Nexus server certificate

Each branch in the tree is a certificate - so this chain contains 4 certificates.

The Maven property checks if the chain contains only one certificate, which implies it is self-signed. If it contains more than one as above, and none of the other certificates are in the Java trust store used by the Java process running Maven, then the only workarounds are to explicitly import the server certificate into the default truststore or have the Nexus server certificate chain be signed by a public certificate authority already in the default Java trust store.

Querying Remote SSL Protocol and Cipher Support

Some secure connection problems may occur because the remote does not support a protocol or cipher needed by the client. There is a tool called nmap you can use to see what protocols are supported by the remote.

Below is an example command and output that tests a secure connection to localhost:8453 :

nmap --script +ssl-enum-ciphers -p 8453 localhost

Starting Nmap 6.47 ( http://nmap.org ) at 2015-11-20 11:40 AST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00013s latency).
PORT     STATE SERVICE
8453/tcp open  unknown
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_RSA_WITH_AES_128_CBC_SHA - strong
|     compressors: 
|       NULL
|   TLSv1.1: 
|     ciphers: 
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_RSA_WITH_AES_128_CBC_SHA - strong
|     compressors: 
|       NULL
|   TLSv1.2: 
|     ciphers: 
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - strong
|       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - strong
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - strong
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - strong
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_RSA_WITH_AES_128_CBC_SHA256 - strong
|       TLS_RSA_WITH_AES_128_GCM_SHA256 - strong
|     compressors: 
|       NULL
|_  least strength: strong

Nmap done: 1 IP address (1 host up) scanned in 0.23 seconds
Have more questions? Submit a request

2 Comments

  • 0
    Avatar
    Olivier Dupré

    Hi Peter,

     

    I followed all the 5+1 steps to configure my NGinX in front of Nexus 3, but I still cannot login with Docker.

    I'm running Docker 1.11 and NGinX 1.10 on Ubuntu, and generated certificates with JDK8 and openssl 1.0.2g.

    At best, I have a HTTP 404, at worst "x509: certificate signed by unknown authority".

    First case, I'm going through NGinX and got an HTTP 404 reply, second case I'm querying directly Nexus and got that message: "Error response from daemon: Get https://nexus.adgroupe.priv:8381/v1/users/: x509: certificate signed by unknown authority".

     

    I'm a bit lost. Just can't have Nexus 3 working as a Docker (secured) registry.

    Olivier

  • 0
    Avatar
    Peter Lynch

    We are closing this article for comments.

    If you have a support license, please contact us by submitting a support ticket.

    If you do not have a support license, please use our Nexus Users List or our other free support resources.

Article is closed for comments.
Powered by Zendesk