Enabling SSL
Solr can encrypt communications to and from clients and between nodes in SolrCloud mode with Secure Sockets Layer encryption (SSL).
This section describes enabling SSL using a self-signed certificate.
For background on SSL certificates and keys, see http://www.tldp.org/HOWTO/SSL-Certificates-HOWTO/.
Configuring Solr for SSL
Generate a Self-Signed Certificate and a Key
To generate a self-signed certificate and a single key that will be used to authenticate both the server and the client, we’ll use the JDK keytool
command and create a separate keystore.
This keystore will also be used as a truststore below.
It’s possible to use the keystore that comes with the JDK for these purposes, and to use a separate truststore, but those options aren’t covered here.
Run the commands below in the server/etc/
directory in the binary Solr distribution.
It’s assumed that you have the JDK keytool
utility on your PATH
, and that openssl
is also on your PATH
.
See https://wiki.openssl.org/index.php/Binaries for OpenSSL binaries for Windows and Solaris.
The -ext SAN=…
keytool
option allows you to specify all the DNS names and/or IP addresses that will be allowed during hostname verification if you choose to require it.
In addition to localhost
and 127.0.0.1
, this example includes a LAN IP address 192.168.1.3
for the machine the Solr nodes will be running on:
$ keytool -genkeypair -alias solr-ssl -keyalg RSA -keysize 2048 -keypass secret -storepass secret -validity 9999 -keystore solr-ssl.keystore.p12 -storetype PKCS12 -ext SAN=DNS:localhost,IP:192.168.1.3,IP:127.0.0.1 -dname "CN=localhost, OU=Organizational Unit, O=Organization, L=Location, ST=State, C=Country"
The above command will create a keystore file named solr-ssl.keystore.p12
in the current directory.
Convert the Certificate and Key to PEM Format for Use with curl
Convert the PKCS12 format keystore, including both the certificate and the key, into PEM format using the openssl
command:
$ openssl pkcs12 -in solr-ssl.keystore.p12 -out solr-ssl.pem
If you want to use curl on OS X Yosemite (10.10), you’ll need to create a certificate-only version of the PEM format, as follows:
$ openssl pkcs12 -nokeys -in solr-ssl.keystore.p12 -out solr-ssl.cacert.pem
Set Common SSL-Related System Properties
The Solr Control Script is already setup to pass SSL-related Java system properties to the JVM.
To activate the SSL settings, uncomment and update the set of properties beginning with SOLR_SSL_*
in bin/solr.in.sh
on *nix systems or bin\solr.in.cmd
on Windows.
-
*nix
-
Windows
If you setup Solr as a service on Linux using the steps outlined in Taking Solr to Production, then make these changes in /var/solr/solr.in.sh .
|
# Enables HTTPS. It is implicitly true if you set SOLR_SSL_KEY_STORE. Use this config
# to enable https module with custom jetty configuration.
SOLR_SSL_ENABLED=true
# Uncomment to set SSL-related system properties
# Be sure to update the paths to the correct keystore for your environment
SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.p12
SOLR_SSL_KEY_STORE_PASSWORD=secret
SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.p12
SOLR_SSL_TRUST_STORE_PASSWORD=secret
# Require clients to authenticate
SOLR_SSL_NEED_CLIENT_AUTH=false
# Enable clients to authenticate (but not require)
SOLR_SSL_WANT_CLIENT_AUTH=false
# SSL Certificates contain host/ip "peer name" information that is validated by default. Setting
# this to false can be useful to disable these checks when re-using a certificate on many hosts.
# This will also be used for the default value of whether SNI Host checking should be enabled.
SOLR_SSL_CHECK_PEER_NAME=true
REM Enables HTTPS. It is implicitly true if you set SOLR_SSL_KEY_STORE. Use this config
REM to enable https module with custom jetty configuration.
set SOLR_SSL_ENABLED=true
REM Uncomment to set SSL-related system properties
REM Be sure to update the paths to the correct keystore for your environment
set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.p12
set SOLR_SSL_KEY_STORE_PASSWORD=secret
set SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.p12
set SOLR_SSL_TRUST_STORE_PASSWORD=secret
REM Require clients to authenticate
set SOLR_SSL_NEED_CLIENT_AUTH=false
REM Enable clients to authenticate (but not require)
set SOLR_SSL_WANT_CLIENT_AUTH=false
REM SSL Certificates contain host/ip "peer name" information that is validated by default. Setting
REM this to false can be useful to disable these checks when re-using a certificate on many hosts.
REM This will also be used for the default value of whether SNI Host checking should be enabled.
set SOLR_SSL_CHECK_PEER_NAME=true
Client Authentication Settings
Enable either SOLR_SSL_NEED_CLIENT_AUTH or SOLR_SSL_WANT_CLIENT_AUTH but not both at the same time.
They are mutually exclusive and Jetty will select one of them which may not be what you expect.
SOLR_SSL_CLIENT_HOSTNAME_VERIFICATION should be set to false if you want to disable hostname verification for client certificates.
|
When you start Solr, the bin/solr
script includes these settings and will pass them as system properties to the JVM.
If you are running Solr in a user-managed cluster or single-node installation, you can skip to Start User-Managed Cluster or Single-Node Solr.
If you are using SolrCloud, however, you need to Configure ZooKeeper before starting Solr.
Password Distribution via Hadoop Credential Store
Solr supports reading keystore and truststore passwords from Hadoop credential store. This approach can be beneficial if password rotation and distribution is already handled by credential stores.
If you are not using a Hadoop credential store, you can skip this step.
Hadoop credential store can be used with Solr using the following two steps.
Provide a Hadoop Credential Store
Create a Hadoop credstore file and define the entries below with the actual keystore passwords.
solr.jetty.keystore.password
solr.jetty.truststore.password
javax.net.ssl.keyStorePassword
javax.net.ssl.trustStorePassword
Note that if the javax.net.ssl.*
configurations are not set, they will fallback to the corresponding solr.jetty.*
configurations.
Configure Solr to use Hadoop Credential Store
Solr requires three parameters to be configured in order to use the credential store file for keystore passwords.
solr.ssl.credential.provider.chain
-
Required
Default: none
The credential provider chain. This should be set to
hadoop
. SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH
-
Required
Default: none
The path to the credential store file.
HADOOP_CREDSTORE_PASSWORD
-
Required
Default: none
The password to the credential store.
-
*nix
-
Windows
SOLR_OPTS=" -Dsolr.ssl.credential.provider.chain=hadoop"
SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH=localjceks://file/home/solr/hadoop-credential-provider.jceks
HADOOP_CREDSTORE_PASSWORD="credStorePass123"
set SOLR_OPTS=" -Dsolr.ssl.credential.provider.chain=hadoop"
set SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH=localjceks://file/home/solr/hadoop-credential-provider.jceks
set HADOOP_CREDSTORE_PASSWORD="credStorePass123"
Configure ZooKeeper
After creating the keystore described above and before you start any SolrCloud nodes, you must configure your Solr cluster properties in ZooKeeper so that Solr nodes know to communicate via SSL.
This section assumes you have created and started an external ZooKeeper. See ZooKeeper Ensemble Configuration for more information.
The urlScheme
cluster-wide property needs to be set to https
before any Solr node starts up.
The examples below use the zkcli
tool that comes with Solr to do this.
-
*nix
-
Windows
$ bin/solr cluster --property urlSchema --value https -z server1:2181,server2:2181,server3:2181
C:\> bin/solr.cmd --property urlSchema --value https -z server1:2181,server2:2181,server3:2181
Be sure to use the correct zkhost
value for your system.
If you have set up your ZooKeeper ensemble to use a chroot for Solr, make sure to include it in the zkHost
string, e.g., --zk-host server1:2181,server2:2181,server3:2181/solr
.
Update Cluster Properties for Existing Collections
If you are using SolrCloud and have collections created before enabling SSL, you will need to update the cluster properties to use HTTPS.
If you do not have existing collections or are not using SolrCloud, you can skip ahead and start Solr.
Updating cluster properties can be done with the Collections API CLUSTERPROP command, as in this example (update the hostname and port as appropriate for your system):
$ http://localhost:8983/solr/admin/collections?action=CLUSTERPROP&name=urlScheme&val=https
This command only needs to be run on one node of the cluster, the change will apply to all nodes.
Once this and all other steps are complete, you can go ahead and start Solr.
Starting Solr After Enabling SSL
Start User-Managed Cluster or Single-Node Solr
Start Solr using the Solr control script as shown in the examples below. Customize the values for the parameters shown as needed and add any used in your system.
-
*nix
-
Windows
$ bin/solr start -p 8984
C:\> bin\solr.cmd -p 8984
Start SolrCloud
If you have defined ZK_HOST in solr.in.sh /solr.in.cmd (see Updating Solr Include Files) you can omit -z <zk host string> from all of the bin/solr /bin\solr.cmd commands below.
|
Start each Solr node with the Solr control script as shown in the examples below. Customize the values for the parameters shown as necessary and add any used in your system.
If you created the SSL key without all DNS names or IP addresses on which Solr nodes run, you can tell Solr to skip hostname verification for inter-node communications by setting the -Dsolr.ssl.checkPeerName=false
system property.
-
*nix
-
Windows
$ bin/solr start --cloud -s cloud/node1 -z server1:2181,server2:2181,server3:2181 -p 8984
C:\> bin\solr.cmd --cloud -s cloud\node1 -z server1:2181,server2:2181,server3:2181
Automatically reloading KeyStore/TrustStore
Solr Server
Solr can automatically reload KeyStore/TrustStore when certificates are updated without restarting. This is enabled by default
when using SSL, but can be disabled by setting the environment variable SOLR_SSL_RELOAD_ENABLED
to false
. By
default, Solr will check for updates in the KeyStore every 30 seconds, but this interval can be updated by passing the
system property solr.jetty.sslContext.reload.scanInterval
with the new interval in seconds on startup.
Note that the truststore file is not actively monitored, so if you need to apply changes to the truststore, you need
to update it and after that touch the keystore to trigger a reload.
SolrJ client
Http2SolrClient builder has a method withKeyStoreReloadInterval(long interval, TimeUnit unit)
to initialize a scanner
that will watch and update the keystore and truststore for changes. If you are using CloudHttp2SolrClient, you can use
the withInternalClientBuilder(Http2SolrClient.Builder internalClientBuilder)
to configure the internal http client
with a keystore reload interval. The minimum reload interval is 1 second. If not set (or set to 0 or a negative value),
the keystore/truststore won’t be updated in the client.
Example Client Actions
curl on OS X Mavericks (10.9) has degraded SSL support. For more information and workarounds to allow one-way SSL, see https://curl.se/mail/archive-2013-10/0036.html. curl on OS X Yosemite (10.10) is improved - 2-way SSL is possible - see https://curl.se/mail/archive-2014-10/0053.html. The curl commands in the following sections will not work with the system
|
If your operating system does not include curl, you can download binaries here: https://curl.se/download.html |
Create a SolrCloud Collection using bin/solr
Create a 2-shard, replicationFactor=1 collection named mycollection using the _default
configset:
-
*nix
-
Windows
bin/solr create -c mycollection --shards 2
bin\solr.cmd create -c mycollection --shards 2
The create
action will pass the SOLR_SSL_*
properties set in your include file to the SolrJ code used to create the collection.
Retrieve SolrCloud Cluster Status using curl
To get the resulting cluster status (again, if you have not enabled client authentication, remove the -E solr-ssl.pem:secret
option):
$ curl -E solr-ssl.pem:secret --cacert solr-ssl.pem "https://localhost:8984/solr/admin/collections?action=CLUSTERSTATUS&indent=on"
You should get a response that looks like this:
{
"responseHeader":{
"status":0,
"QTime":2041},
"cluster":{
"collections":{
"mycollection":{
"shards":{
"shard1":{
"range":"80000000-ffffffff",
"state":"active",
"replicas":{"core_node1":{
"state":"active",
"base_url":"https://127.0.0.1:8984/solr",
"core":"mycollection_shard1_replica1",
"node_name":"127.0.0.1:8984_solr",
"leader":"true"}}},
"shard2":{
"range":"0-7fffffff",
"state":"active",
"replicas":{"core_node2":{
"state":"active",
"base_url":"https://127.0.0.1:7574/solr",
"core":"mycollection_shard2_replica1",
"node_name":"127.0.0.1:7574_solr",
"leader":"true"}}}},
"router":{"name":"compositeId"},
"replicationFactor":"1"}},
"properties":{"urlScheme":"https"}}}
Index Documents using bin/solr post
Use bin/solr post
to index some example documents to the SolrCloud collection created above:
$ bin/solr post --solr-update-url https://localhost:8984/solr/mycollection/update example/exampledocs/*.xml
Query Using curl
Use curl to query the SolrCloud collection created above, from a directory containing the PEM formatted certificate and key created above (e.g., example/etc/
).
If you have not enabled client authentication (system property -Djetty.ssl.clientAuth=true)
, then you can remove the -E solr-ssl.pem:secret
option:
$ curl -E solr-ssl.pem:secret --cacert solr-ssl.pem "https://localhost:8984/solr/mycollection/select?q=*:*"
Index a Document using CloudSolrClient
From a java client using SolrJ, index a document.
In the code below, the javax.net.ssl.*
system properties are set programmatically, but you could instead specify them on the java command line, as in the post.jar
example above:
System.setProperty("javax.net.ssl.keyStore", "/path/to/solr-ssl.keystore.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "secret");
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
System.setProperty("javax.net.ssl.trustStore", "/path/to/solr-ssl.keystore.p12");
System.setProperty("javax.net.ssl.trustStorePassword", "secret");
System.setProperty("javax.net.ssl.trustStoreType", "pkcs12");
String zkHost = "127.0.0.1:2181";
CloudSolrClient client = new CloudSolrClient.Builder(Collections.singletonList(zkHost),Optional.empty()).withDefaultCollection("mycollection").build();
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", "1234");
doc.addField("name", "A lovely summer holiday");
client.add(doc);
client.commit();