Securing Cassandra CQLSH
At Data-Aces, we provide managed services running Cassandra for our customers. With more and more attention being given to data security these days, end-to-end encryption of ALL communication is becoming a mandatory requirement. This includes traffic between the Cassandra nodes or from client to the Cassandra cluster. The default config file (Cassandra.yaml) is configured for normal, unencrypted communication between clients and Cassandra on port 9042.
It is fairly easy to setup client to cluster encryption by creating certificates and adding them to Java keystore/truststore. This process is documented here: https://docs.datastax.com/en/cassandra/3.0/cassandra/configuration/secureSSLClientToNode.html
# If enabled and optional is set to true encrypted and unencrypted connections are handled.
However, following these steps above as is did not work in our cluster. This is because, it refers to certfile without giving us an important caveat: cqlsh is a python application and does not use the Java keystore/truststore setup for normal Cassandra and Java clients.
Instead, the certificate in ‘keystore.jks’ needs to be converted to PKCS12 format. Luckily, keytool has an inbuilt facility to convert to PKCS12 format.
keytool -importkeystore -srckeystore keystore -destkeystore pkcs12ks -deststoretype PKCS12 -srcstorepass keystorepassword -deststorepass keystorepassword
This will create a keystore file named ‘pkcs12ks’ in the current directory.
The next step is to create a PEM file from this keystore as follows
openssl pkcs12 -in pkcs12ks -nokeys -out cqlsh.pem -passin pass:keystorepassword
Setting up .cqlshrc file
Now that we have our PEM file, we can point to it in the cqlshrc file
[connection] factory = cqlshlib.ssl.ssl_transport_factory [ssl] certfile = /home/user/cqlsh.pem validate = false
Note that setting ‘validate=true’ implies that the certificate needs to be validated at connection time.
Now, you can run cqlsh as follows
$ cqlsh <host_ip> --ssl