VoltDB hashes usernames and passwords both within the database server and while passing them across the network. However, the network communication itself is not encrypted by default. You can enable Transport Layer Security (TLS) — the recommended upgrade from Secure Socket Layer (SSL) communication — for the HTTP port, which affects the VoltDB Management Center and the JSON interface. You can also extend TLS encryption to all external interfaces (HTTP, client, and admin), the internal interface, and the port used for database replication (DR) for more thorough security. The following sections summarize how to enable TLS for the servers in a cluster, including:
Configuring TLS encryption on the server
Choosing which ports to encrypt
Using the VoltDB command line utilities with TLS
Implementing TLS communication in Java client applications
Configuring Database Replication (DR) using TLS
TLS, like its predecessor SSL, uses certificates to validate the authenticity of the communication. You can either use a certificate created by a commercial certificate provider (such as Digitcert, GeoTrust, or Symantec) or you can create your own certificate. If you use a commercial provider, that provider also handles the authentication of the certificate. If you create a local or self-signed certificate, you need to provide the certificate and authentication to the server and clients yourself.
If you purchase a commercial certificate, the server configuration must include a pointer to the certificate in the
<keystore>
element. So, for example, if the path to the certificate is
/etc/ssl/certificate
, you can enable TLS for all external interfaces by including the following XML
in the database configuration file:
<ssl enabled="true" external="true"> <keystore path="/etc/ssl/certificate" password="mysslpassword"/> </ssl>
If you choose to use a locally created certificate, you must first generate the certificate key store and trust store. You can create a local certificate using the Java keytool utility. Creating the key store and trust store requires several steps including:
Creating a key store and password
Creating a key signing request
Creating and signing the certificate
Importing the certificate into the key store
Creating the associated trust store
There are a number of different options when performing this task. It is important to understand how these options affect the resulting certificate. Be sure to familiarize yourself with the documentation of the keytool utility before creating your own certificate. The following example uses some common options to generate a self-signed certificate key store and trust store.
$ keytool -genkey -keystore mydb.keystore \ -storepass mypasswd -alias mydb \ -keyalg rsa -validity 365 -keysize 2048 $ keytool -certreq -keystore mydb.keystore \ -storepass mypasswd -alias mydb \ -keyalg rsa -file mydb.csr $ keytool -gencert -keystore mydb.keystore \ -storepass mypasswd -alias mydb \ -infile mydb.csr -outfile mydb.cert -validity 365 $ keytool -import -keystore mydb.keystore \ -storepass mypasswd -alias mydb \ -file mydb.cert $ keytool -import -keystore mydb.truststore \ -storepass mypasswd -alias mydb \ -file mydb.cert
Once you create the key store and the trust store, you can reference them in the database configuration file to enable TLS when initializing the database root directory. For example:
<ssl enabled="true" external="true"> <keystore path="/etc/ssl/local/mydb.keystore" password="mypasswd"/> <truststore path="/etc/ssl/local/mydb.truststore" password="mypasswd"/> </ssl>
If TLS encryption is enabled, the HTTP is always encrypted. You can selectively choose to encrypt other ports as well. You specify which ports to encrypt using attributes of the <ssl> element:
External ports (external), including the client and admin ports
Internal ports (internal), used for intra-cluster communication between the nodes of the cluster
Extranet ports (dr), including the replication port used for DR
For each type of port, you specify that the ports are either enabled ("true") or disabled ("false"). The default is false. For example, the following configuration enables TLS encryption on the external, internal, and DR ports:
<ssl enabled="true" external="true" internal="true" dr="true"> <keystore path="/etc/ssl/local/mydb.keystore" password="mypasswd"/> <truststore path="/etc/ssl/local/mydb.truststore" password="mypasswd"/> </ssl>
Note that if you enable TLS encryption for the DR port, other clusters replicating from this cluster must include the appropriate client configuration when they enable DR. See Section 12.7.5, “Configuring Database Replication (DR) With TLS/SSL” for information on setting up TLS when configuring DR.
Also, enabling TLS encryption on the internal port means that all intra-cluster communication must be encrypted and decrypted as it passes between nodes. Consequently, any operations that require interactions between cluster nodes (such as K-safety or multi-partition transactions) may take longer and therefore impact overall latency. Be sure to benchmark your application with and without TLS encryption before enabling internal port encryption on production systems.
Finally, it is important to note that all ports where TLS is enabled and all the servers within a single cluster use the same certificate.
Once you enable TLS for the external interfaces on your database servers, you must also enable TLS on the command line utilities so they use the appropriate protocols to connect to the servers. (The voltdb utility is the one exception. Since it only operates on the local server it does not require a network connection.)
When invoking the command line utilities, such as voltadmin and sqlcmd, you
use the --ssl
option to activate encryption with TLS-enabled VoltDB servers. If the servers are using a
commercially-provided certificate, you can specify the --ssl
option without an argument. For
example:
$ sqlcmd --ssl
If the servers are using a local or self-signed certificate you must also specify a Java properties file as an
argument to the --ssl
option. For example:
$ sqlcmd --ssl=localcert.txt
The properties file must declare two properties that specify the path to the trust store and the trust store
password, respectively. So, using the trust store generated by the example in Section 12.7.1, “Configuring TLS/SSL on the VoltDB Server”, the
localcert.txt
file could be:
trustStore=/etc/ssl/local/mydb.truststore trustStorePassword=mypasswd
Just as the command line tools must specify how to connect to an TLS-enabled server, client applications must also
establish an appropriate connection. Using the VoltDB Java API, you can enable TLS by setting the appropriate attributes
of the client configuration. Specifically, if you are using a self-signed certificate, you must provide the path to the
trust store and its password. You can do this using either the .setTrustStore() or .setTrustStoreConfigFromPropertyFile().
For example, the following two commands are equivalent, assuming the localcert.txt
file matches the
properties file described in Section 12.7.3, “Using the VoltDB Command Line Utilities with TLS/SSL”:
clientConfig.setTrustStore("/etc/ssl/local/mydb.truststore", "mypasswd"); clientConfig.setTrustStoreConfigFromPropertyFile("localcert.txt");
After setting the trust store properties you can enable TLS communication using the .enableSSL() method and create the client connection. For example:
ClientConfig clientConfig = new ClientConfig("JDoe", "JDsPasswd"); clientConfig.setTrustStoreConfigFromPropertyFile("localcert.txt"); clientConfig.enableSSL(); client = ClientFactory.createClient(clientConfig);
When using a commercially generated certificate, you do not need to specify the trust store and can use just the .enableSSL() method.
When using TLS encryption on the DR port, the DR snapshots and binary logs are encrypted as they pass from the producer cluster to the consumer cluster. This means that the producer must not only have TLS enabled for the DR port, but the consumer cluster must use the appropriate TLS credentials when it contacts the producer.
So, for example, in passive DR, the master cluster must have TLS enabled for the DR port and the replica must be configured to use TLS when connecting to the master. In XDCR, you enable TLS for all clusters in the XDCR relationship. So each cluster must both enable TLS for its DR port as well as configure TLS for its connections to the other clusters.
Section 12.7.1, “Configuring TLS/SSL on the VoltDB Server” describes how to enable TLS encryption for the DR port, which must be done
before the cluster starts. To configure TLS connectivity at the other end, you add the ssl
attribute to the <connection>
element within the
DR configuration. The value of the ssl
attribute is either blank — for
commercial certificates — or the path to a Java properties file specifying the trust store and password for the
remote cluster(s) when using a locally-generated certificate. These attribute values are the same as the
--ssl
argument you use when running the command line utilities described in Section 12.7.3, “Using the VoltDB Command Line Utilities with TLS/SSL”.
For example, when configuring TLS encryption for passive DR, the master cluster must enable TLS on the DR port and
the replica must specify use of TLS in the <connection>
element. The respective
configuration files might look like this:
<ssl enabled="true" dr="true">
<keystore path="/etc/ssl/local/mydb.keystore" password="mypasswd"/>
<truststore path="/etc/ssl/local/mydb.truststore" password="mypasswd"/>
</ssl>
<dr id="2" role="replica">
<connection source="MasterSvrA,MasterSvrB" ssl="/usr/local/mastercert.txt">
</dr>
Note that the replica does not need to enable TLS for its DR port, since it is a consumer and its own port is not used.
For XDCR, each cluster must both enable DR for its own port and specify the TLS credentials for the remote clusters. The configuration file might look like this:
<ssl enabled="true" dr="true"> <keystore path="/etc/ssl/local/mydb.keystore" password="mypasswd"/> <truststore path="/etc/ssl/local/mydb.truststore" password="mypasswd"/> </ssl> <dr id="1" role="xdcr"> <connection source="NYCSvrA,NYCSvrB" ssl="/usr/local/nyccert.txt"> </dr>
Note that when using locally-generated certificates, there is only one properties file specified in the ssl
attribute. So all of the clusters in the XDCR relationship must use the same certificate.
When using commercially purchased certificates, the ssl
attributes is left blank; so
each cluster can, if you choose, use a separate certificate.