Configuring Fusion for SSL

Fusion’s UI (which is accessed through the Proxy service) can run over SSL for secure communication with any HTTP client, using the Java Secure Socket Extension (JSSE) framework. SSL is configured in Fusion’s authentication proxy.

To configure Fusion for SSL:
  1. Load the keystore with a signed SSL certificate

  2. Enable SSL

  3. Disable HTTP access (optional but recommended)

If you have additional nodes dedicated to indexing, see the instructions for Configuring Fusion for SSL Solr/SolrCloud.

1. Load an SSL certificate

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.

You can load self-signed certificates or certificates signed by a CA into Fusion Server.

Loading self-signed certificates into the keystore

If Fusion is behind a firewall, you can use a self-signed certificate for SSL communication with other hosts in your internal network.

How to load the keystore with a self-signed certificate
  1. Run the command below, and fill in values where prompted.

    Important
    When prompted for your first and last name, you must input the IP address or hostname of the server.
    • Linux:

      keytool -genkey -keyalg RSA -alias selfsigned -keystore fusion/4.1.x/apps/jetty/proxy/etc/keystore -storepass changeit -validity 360 -keysize 2048
    • Windows:

      keytool -genkey -keyalg RSA -alias selfsigned -keystore fusion/4.1.x\apps\jetty\proxy\etc\keystore -storepass changeit -validity 360 -keysize 2048

    Example output:

    keytool -genkey -keyalg RSA -alias selfsigned -keystore /home/ndipiazza/Downloads/fusion/4.1.1/apps/jetty/proxy/etc/keystore -storepass changeit -validity 360 -keysize 2048
    What is your first and last name?
      [Unknown]: localhost
    What is the name of your organizational unit?
      [Unknown]:
    What is the name of your organization?
      [Unknown]:
    What is the name of your City or Locality?
      [Unknown]:
    What is the name of your State or Province?
      [Unknown]:
    What is the two-letter country code for this unit?
      [Unknown]:
    Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
      [no]:  yes
    Enter key password for <selfsigned>
        	(RETURN if same as keystore password):

    The keystore password may be blank (no password).

Loading signed certificates into the 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/proxy/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.

2. Enable SSL

Before beginning these steps, make sure you have loaded an SSL certificate into Fusion Server.

How to enable SSL in the authentication proxy
  1. Run the following:

    cd fusion/4.1.x/apps/jetty/proxy/
    java -jar fusion/4.1.x/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/4.1.x/apps/jetty/proxy/etc/keystore file to the Fusion host.

    Example output:

    INFO: ssl             initialised (transitively) in ${jetty.base}/start.ini
    INFO: https           initialised in ${jetty.base}/start.ini
    INFO: Base directory was modified
  2. Get the hashed version of your keystore password:

    cd fusion/4.1.x
    java -cp ./apps/libs/jetty-util-9.3.8.v20160314.jar org.eclipse.jetty.util.security.Password 

    Where <password> is the password you used for the keystore, or ? for no password.

    Example output:

    2018-05-15 12:32:48.988:INFO::main: Logging initialized @133ms
    changeit
    OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0
    MD5:b91cd1a54781790beaa2baf741fa6789
  3. Edit fusion/4.1.x/apps/jetty/proxy/start.ini:

    1. Uncomment the following properties:

      • jetty.sslContext.keyStorePassword

      • jetty.sslContext.keyManagerPassword

      • jetty.sslContext.trustStorePassword

    2. Use the OBF-encrypted password from step 2 as the value for all three of the uncommented properties.

      For example:

      ## Keystore password
      jetty.sslContext.keyStorePassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
      
      ...
      
      ## KeyManager password
      jetty.sslContext.keyManagerPassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
      
      ## Truststore password
      jetty.sslContext.trustStorePassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
    3. Set the local SSL port by uncommenting the jetty.ssl.port property.

      For example:

      ## Connector port to listen on
      jetty.ssl.port=8443
    4. Save the file.

  4. Configure ZooKeeper to use HTTPS:

    1. Start ZooKeeper if required.

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

  5. Start Fusion with fusion/4.1.x/bin/fusion start.

    HTTPS should now be enabled on port 8443.

3. Disable HTTP

Often, when HTTPS is enabled then it is best to disable HTTP access. Ideally you should do this at the firewall.

Disabling HTTP on the firewall

  • Disallow all requests for port 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 in Fusion Server

Important
Ideally, you should disable HTTP access using the firewall. Follow the steps below only if doing this on the firewall is not feasible.

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 certificate only covers https://fusion.com then your local machine must be able to access Fusion from that exact host. If needed, make a change to the hosts file so that this can work.

How to disable HTTP
  1. Edit fusion/4.1.x/apps/jetty/proxy/start.d/http.ini.

  2. Change this line:

    --module=http

    to

    #--module=http
  3. Save the file.

  4. Edit fusion/4.1.x/conf/fusion.properties.

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

    agent.jvmOptions=-Djavax.net.ssl.trustStore="${FUSION_HOME}/apps/jetty/proxy/etc/keystore" -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.keyStore="${FUSION_HOME}/apps/jetty/proxy/etc/keystore" -Djavax.net.ssl.keyStorePassword=changeit

    Replace changeit with your Fusion keystore password.

  6. Uncomment the default.address and change it to the hostname of the server that is validated by your SSL certificate.

    If the hostname saved in default.address is not validated by your SSL certificate, Proxy will not start because the agent’s liveness detector will not be able to access HTTPS port to see if Fusion is running.

    Important
    If you self-signed the certificate, then the default.address must match the hostname you specified while signing the certificate. Failure to do this will result in the Proxy process not starting once you have disabled HTTP.

    For example if my SSL certificate’s validated hostname is “fusion.com”, then change

    #default.address = 127.0.0.1

    to

    default.address = fusion.com
  7. Change the proxy.port to the SSL port you chose.

    Change

    proxy.port=8764

    to

    proxy.port=8864
  8. Uncomment proxy.ssl and change its value to "true":

    Change

    # proxy.ssl=false

    to

    proxy.ssl=true
  9. Restart Fusion:

    {fusion_path}/bin/fusion restart

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/4.1.x/conf/fusion.properties file, add the following properties to the options api.jvmOptions, connectors.jvmOptions, and proxy.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/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/collections' -d '
{
  "id" : "mycollection",
  "searchClusterId" : "ssl"
}'

Index data using an existing pipeline:

curl -u admin:pass 'http://localhost:8764/api/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/query-pipelines/mycollection-default/collections/mycollection/select?q=*:*'