Configuring Fusion for SSL

Fusion uses the Java Secure Socket Extension (JSSE) framework to enable SSL configuration for secure communication between the Fusion UI and any HTTP client.

To configure Fusion for SSL you must install an SSL certificate and enable SSL in the Fusion UI.

Installing an SSL certificate

The server has a locally-protected private key that is accessible via a JSEE keystore. The keystore maintains both the server certificate and the private key.

Important
In a production environment, SSL certificates must be signed by a trusted Certificate Authority (CA).

To store certificates, you can use the Java keytool, which is part of the JDK. When you have a signed certificate, then you create a JSSE keystore by using the keytool "import" command.

In the following example, we have a signed certificate, in pfx format, in a PKCS#12 file called fusion.keystore.p12. The following command creates a new JSSE keystore (JKS):

keytool -importkeystore -srckeystore /opt/lucidworks/fusion/apps/jetty/ui/etc/fusion.keystore.p12 \
 -srcstoretype pkcs12 -destkeystore /opt/lucidworks/fusion/jetty/ui/etc/keystore -deststoretype JKS

If you have the certificate and private key as separate files, then you need to use openssl to create a PKCS#12 file. For example:

openssl pkcs12 -export -out /home/admin/keys/keystore.pkcs12 -in /home/admin/keys/fullchain.pem -inkey /home/admin/keys/privkey.pem
Note
When prompted for a password, do not enter a blank password.

Now use keytool to import the PKCS#12 file into Java keystore format and optionally delete the PKCS#12 file:

keytool -importkeystore -srckeystore /home/admin/keys/keystore.pkcs12 -srcstoretype PKCS12 -destkeystore {fusion_path}/apps/jetty/ui/etc/keystore
Note
If your server certificate is signed by an intermediate CA rather than a root CA, you must add the intermediate certificate to the keystore before you add the server certificate.

Enabling SSL in the Fusion UI

  1. Run the following:

    cd {fusion_path}/apps/jetty/ui
    java -jar {fusion_path}/apps/jetty/home/start.jar --add-to-start=https
    Note
    This step requires an Internet connection. If no connection is available on the Fusion host, run the commands above on a separate host, then copy the resulting fusion/3.1.x/apps/jetty/ui/etc/keystore file to the Fusion host.
  2. Get the hashed version of your keystore password:

    cd {fusion_path}
    java -cp ./apps/libs/jetty-util-9.3.8.v20160314.jar org.eclipse.jetty.util.security.Password <secret>

    Where <secret> is the password you used for the keystore or the -storepass value if you generated the self-signed certificate as per the guide provided here.

  3. Edit fusion/3.1.x/apps/jetty/ui/start.ini to uncomment and add the hashed password from the previous step to these properties:

    • jetty.sslContext.keyStorePassword

    • jetty.sslContext.keyManagerPassword

    • jetty.sslContext.trustStorePassword

    For example:

    ## Keystore password
    jetty.sslContext.keyStorePassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
    
    ## Keystore type and provider
    # jetty.sslContext.keyStoreType=JKS
    # jetty.sslContext.keyStoreProvider=
    
    ## KeyManager password
    jetty.sslContext.keyManagerPassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
    
    ## Truststore password
    jetty.sslContext.trustStorePassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
  4. Set the local SSL port by editing the jetty.ssl.port property.

    For example:

    ## Connector port to listen on
    jetty.ssl.port=8864
  5. Configure ZooKeeper to use HTTPS:

    1. Start ZooKeeper if required.

    2. Run fusion/3.1.x/apps/solr-dist/server/scripts/cloud-scripts/zkcli.sh -zkhost <zkHost1>:<port1>,<zkHost2:port2>,.. -cmd put /clusterprops.json '{"urlScheme":"https"}'

  6. Restart Fusion with fusion/3.1.x/bin/fusion restart.

    HTTPS should now be enabled on port 8864.

Optional Steps to set up your firewall / load balancer:
  • Disallow all requests from 8764 from the outside world. Only localhost should be able to talk to Fusion on the non-SSL port 8764. Block all others.

  • If you are using a load balancer or web server in front of Fusion, use it to redirect all HTTP requests to use HTTPS instead.

Disabling HTTP

Note
Only do this if blocking access to HTTP using the firewall is not feasible.

To entirely disable HTTP, remove the HTTP connector from the Jetty startup configuration:

Note
You can only use this option if your SSL certificate covers a hostname that can be accessed from the local host. For example, if your SSL certificate only covers https://myfusion.com then your local machine must be able to access Fusion using this URL.
  1. Edit fusion/3.1.x/apps/jetty/ui/start.d/http.ini to change --module=http to #--module=http.

  2. Edit fusion/3.1.x/conf/fusion.properties:

    1. Make sure the Agent JVM uses the UI’s keystore by adding the following to the end of the file:

      agent.jvmOptions=-Djavax.net.ssl.trustStore={fusion_path}/apps/jetty/ui/etc/keystore -Djavax.net.ssl.trustStorePassword=<password> -Djavax.net.ssl.keyStore={fusion_path}/apps/jetty/ui/etc/keystore -Djavax.net.ssl.keyStorePassword=<password>
    2. Uncomment default.address and change it to the hostname of the server that is validated by your SSL certificate.

      Note
      If the hostname saved in default.address is not validated by your ssl certificate, UI will not start because the Agent’s liveness detector will not be able to access HTTPS port to see if Fusion is running.
      Note
      If you self-signed the certificate, the default.address must match the hostname you specified while signing the certificate. For example if my SSL certificate’s validated hostname is localhost, change #default.address = 127.0.0.1 to default.address = localhost
    3. Change ui.port to the SSL port you chose for jetty.ssl.port in UI’s start.ini file earlier.

    4. Set ui.ssl to true by changing # ui.ssl=false to ui.ssl=true

  3. Restart Fusion.

Configuring Fusion for SSL Solr/SolrCloud

To configure the Fusion HTTP client for a SSL-ed Solr or SolrCloud server, you must specify the javax.net.ssl system properties.

Step 1. Edit the configuration file

In the fusion/3.1.x/conf/fusion.properties file, add the following properties to the options api.jvmOptions, connectors.jvmOptions, and ui.jvmOptions:

    -Djavax.net.ssl.keyStore=/path/to/solr-ssl.keystore.jks \
    -Djavax.net.ssl.keyStorePassword=secret \
    -Djavax.net.ssl.trustStore=/path/to/solr-ssl.keystore.jks \
    -Djavax.net.ssl.trustStorePassword=secret

Step 2. Register SolrCloud as a search cluster in Fusion

Send a request to the REST API 'searchCluster' endpoint:

curl -u admin:pass -H 'Content-type: application/json' -X POST 'http://localhost:8764/api/apollo/searchCluster' -d '
{
  "id" : "ssl",
  "connectString" : "localhost:2181",
  "cloud" : true
}

Step 3. Test: create collection, index data, query collection

Create collection in SolrCloud with configured SSL:

curl -u admin:pass -H 'Content-type: application/json' -X POST 'http://localhost:8764/api/apollo/collections' -d '
{
  "id" : "mycollection",
  "searchClusterId" : "ssl"
}'

Index data using an existing pipeline:

curl -u admin:pass 'http://localhost:8764/api/apollo/index-pipelines/mycollection-default/collections/mycollection/index' -XPOST -H "Content-type: application/json" -d '{
  "id": "1",
  "foo_s": "bar",
  "spam_s": 42
}'

Query the collection using the default query pipeline:

curl -u admin:pass 'http://localhost:8764/api/apollo/query-pipelines/mycollection-default/collections/mycollection/select?q=*:*'

Generating a self-signed certificate

If don’t have signed certificates from an external CA, then you can generate a set of self-signed certificates using the Java keytool utility to generate a public/private key pair and generate a self-signed certificate.

The keytool option "-genkeypair" generates a public/private key pair. It wraps the public key into an X.509 v3 self-signed certificate, which is stored as a single-element certificate chain. This certificate chain and the private key are stored in a new keystore entry identified by alias. The full set of arguments to this command are:

-genkeypair
    {-alias alias}
    {-keyalg keyalg}
    {-keysize keysize}
    {-sigalg sigalg}
    [-dname dname]
    [-keypass keypass]
    {-startdate value}
    {-ext ext}*
    {-validity valDays}
    {-storetype storetype}
    {-keystore keystore}
    [-storepass storepass]
    {-providerClass provider_class_name {-providerArg provider_arg}}
    {-v}
    {-protected}
    {-Jjavaoption}

Arguments of interest are:

  • keyalg specifies the algorithm to be used to generate the key pair. This must be RSA in order to talk to browser clients IE and Navigator.

  • keysize specifies the size of each key to be generated. Depends on keyalg. For RSA, this should be 2048.

  • dname specifies the X.500 Distinguished Name to be associated with the alias, and is used as the issuer and subject fields in the self-signed certificate. If no distinguished name is provided at the command line, the user will be prompted for one. An X.500 Distinguished name is a set of named fields, of these, the field named "CN", ("Common Name"), is the internet-facing fully qualified domain name of the server.

  • keypass is a password used to protect the private key of the generated key pair. If no password is provided, the user is prompted for it. If you press RETURN at the prompt, the key password is set to the same password as that used for the keystore. keypass must be at least 6 characters long.

  • ext is used to embed extensions into the certificate generated. For Fusion, the server certificate should include the "SAN" or SubjectAlternativeName extension which allows alternative URIs and IP addresses to be associated with this certificate.

Keystore files created by the keystore tool are in the JKS format, which is a proprietary file format capable of storing multiple key-pairs, certificates, and symmetric encryption keys, and with all entries indexed by the keypair alias.

To generate a self-signed certificate for the Fusion UI running as "localhost", we use the following arguments:

keytool -genkeypair \
 -alias localhost -keyalg RSA -keysize 2048 \
 -keypass secret -storepass secret \
 -validity 365 -keystore my.keystore.jks \
 -ext SAN=DNS:localhost,IP:127.0.0.1 \
 -dname "CN=localhost, OU=org unit, O=org, L=loc, ST=st, C=country"
Note
The value for CN must match the hostname you will be using to access Fusion. For example, if will use the URL https://myfusion.com:8864 to access the UI then the CN should have the value myfusion.com.

This keystore file can now be imported to the Fusion UI keystore. To check the generated keystore we use the openssl tool to pretty-print the signed certificate in the file my.keystore.jks. This is not strictly necessary; this should always be done before sending the certificate to a CA to get it signed properly in order to verify that the certificate information is complete and correct.

To get from the keystore JKS format to a human-readable printout, it must be converted to the text-based "PEM" format, which is ASCII (Base64) armored data prefixed with a —– BEGIN … line. This requires three steps.

First, we use the keytool to convert the proprietary JKS format to the PKCS #12 format:

keytool -importkeystore \
 -srckeystore my.keystore.jks -destkeystore my.keystore.p12 \
 -srcstoretype jks -deststoretype pkcs12

This command prompts for passwords - as before, the password is "secret".

Next, we use openssl to convert the PKCS format to PEM format:

openssl pkcs12 -in my.keystore.p12 -out my.keystore.pem

Finally, to pretty-print the certificate, we use the following openssl command:

openssl x509 -in my.keystore.pem -text -noout

This converts the PEM format to text format, and writes the output to the terminal. The output is:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1442779707 (0x55ff123b)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=country, ST=st, L=loc, O=org, OU=org unit, CN=localhost
        Validity
            Not Before: Apr  8 07:39:35 2015 GMT
            Not After : Apr  7 07:39:35 2016 GMT
        Subject: C=country, ST=st, L=loc, O=org, OU=org unit, CN=localhost
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (2048 bit)
                Modulus (2048 bit):
                    00:96:04:46:6c:be:7f:ec:ea:18:fa:28:11:a9:fb:
                    3d:07:c5:3c:49:39:57:11:24:1d:75:47:5d:76:26:
                    4b:73:c0:ea:44:7a:a5:59:3a:a7:4b:16:eb:1f:be:
                    05:f1:2a:be:62:72:2c:67:ec:d3:8b:ad:76:af:dc:
                    6d:14:ca:c9:75:5a:76:24:80:c6:f8:55:b0:27:6a:
                    fa:a8:1b:4b:5c:55:93:49:ff:f8:84:67:29:56:80:
                    ca:c1:d8:c4:8c:b8:57:a4:78:6a:e8:e0:2c:51:74:
                    fb:fb:52:3d:d3:e9:58:e5:11:79:5f:5a:70:ec:c3:
                    de:d7:56:36:67:fd:52:dd:73:60:f7:93:9f:00:c0:
                    36:49:65:7d:77:45:76:34:0e:81:38:96:2b:19:b0:
                    30:8b:ac:2f:ae:dd:92:41:78:da:47:32:02:f7:0d:
                    04:f5:51:85:dc:06:58:08:9b:d2:a0:69:52:ac:b2:
                    7d:c7:bd:16:1d:9e:af:e2:2b:6a:61:8e:cb:a9:ec:
                    fc:01:fe:6b:34:49:1c:d8:75:8b:ca:ec:ea:fd:93:
                    0a:8b:34:6b:77:98:ec:83:6f:d2:bc:81:ec:f5:18:
                    48:41:db:92:da:ef:19:19:27:5b:05:5f:8c:6e:1e:
                    9d:e5:90:42:6f:36:8f:11:49:05:aa:dd:a5:c9:0a:
                    fe:81
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:localhost, IP Address:127.0.0.1
            X509v3 Subject Key Identifier:
                E1:D1:66:F6:1F:5A:18:1A:82:33:A7:32:0E:0B:EA:8E:C0:D3:ED:05
    Signature Algorithm: sha256WithRSAEncryption
        56:a8:31:c0:94:8f:5a:80:27:17:36:ba:e0:ff:e6:59:13:9e:
        67:6b:1e:7d:67:04:5c:e1:88:9e:d9:89:11:ca:88:a0:21:4c:
        90:a8:8b:9d:b5:ba:0f:92:65:da:c5:a9:91:82:17:46:55:43:
        82:78:92:b1:f9:f5:2b:65:5e:b0:93:03:3b:94:83:bb:fe:9b:
        09:a9:f3:82:d2:4d:b5:72:e9:ee:75:15:31:3d:18:a7:c1:e8:
        45:44:1d:40:d2:eb:96:b7:01:41:dd:9d:1c:31:e6:45:4a:c2:
        3d:ec:22:1a:35:ec:38:62:e8:3d:b3:30:10:d3:88:09:5a:87:
        54:87:fb:92:d6:0e:74:52:3c:f2:c3:f5:70:61:ea:72:3f:cd:
        65:72:34:6f:51:94:13:e0:7a:73:bb:57:c8:ad:98:f7:3f:43:
        4d:75:96:db:cf:2e:e6:82:1c:c2:97:38:2d:37:06:c4:27:db:
        87:82:6b:c6:01:71:f7:e9:1f:69:62:0d:cc:54:e9:f4:25:86:
        6a:e2:38:72:c3:9c:53:b4:6e:4f:ae:8a:09:36:14:f0:10:57:
        9c:c9:a8:a3:a5:e6:db:d1:d4:39:95:f3:54:95:4f:2f:db:59:
        b6:bd:77:00:77:c2:9d:4f:d9:04:d5:af:33:bb:2e:0f:65:a9:
        74:ff:66:f2