Configuring Fusion for SSL

The Fusion UI can be run over SSL for secure communication between any HTTP client and Fusion. Fusion uses the Java Secure Socket Extension (JSSE) framework to implement this functionality.

SSL provides both authentication and encryption services:

  • Authentication is carried out via digitally signed certificates and the exchange of public/private key data.

  • All data sent between the client and server is encrypted.

To configure Fusion for SSL you must:

  • Obtain a signed certificate that will be sent to web clients for authentication and put it in a JSSE keystore.

  • Configure the Fusion UI server to run on a secure port and use the SSL protocol.

SSL certificates

The SSL protocol is based on public-key cryptography where encryption keys come in public key, private key pairs. An SSL certificate is used to verify the authenticity of a particular server. It contains the web site name, contact email address, company information and the public key used to encrypt the communication which is shared with the entities that communicate with the owner of the public/private key pair.

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, so that when a server authenticates itself to the client, it uses the private key from its keystore for the initial SSL handshake.

Importing certificates into the JSSE keystore

In a production environment, SSL certificates must be signed by a trusted third-party organization called a CA (Certificate Authority). Contact your sys admin to get a signed SSL certificate.

To store certificates, you can use the Java keytool Key and Certificate Management utility which is part of the JDK.

If you have signed certificates, then you create a JSSE keystore by using the keytool "import" command. In the following example, we have a signed certificate from a CA, in pfx format in a pkcs12 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 lucidworks.io.jks -deststoretype JKS

If you have the cert and private key as separate files, then you need to use openssl to create a pkcs12 file.

If you have an intermediate CA certificate, you can use it to generate the private key and certificate file using openssl.

Enabling SSL in the Fusion UI

  1. Run the following:

    cd $FUSION/apps/jetty/ui
    java -jar $FUSION/apps/jetty/home/start.jar --add-to-start=https
  2. Get the hashed version of your keystore password:

    cd $FUSION
    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.

  3. Edit $FUSION/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 support HTTPS:

    $FUSION/bin/zookeeper start
    
    $FUSION/apps/solr-dist/server/scripts/cloud-scripts/zkcli.sh -zkhost $HOSTNAME:9983 -cmd put /clusterprops.json '{"urlScheme":"https"}'
    
    $FUSION/bin/zookeeper stop
  6. Start Fusion with $FUSION/bin/fusion start.

    HTTPS should now be enabled on port 8864.

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/conf/fusion.properties file, add the following properties to the options api.jvmOptions, connectors.jvmOptions, and ui.jvmOptions:

    -Djavax.net.ssl.keyStore=/path/to/your/solr-ssl.keystore.jks \
    -Djavax.net.ssl.keyStorePassword=secret \
    -Djavax.net.ssl.trustStore=/path/to/your/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"

We check our work using the openssl tool to pretty-print the signed certificate in 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