Cassandra SSL with its own certification authority

I want to configure my own CA for use with the cassandra cluster so that I don’t have to copy all the certificates every time I add a new node. I read several tutorials for Cassandra and SSL, but they all work with certificate copying. I lost a little in the CA process

This is what I think I need to do.

  • Create CA once
  • Create a CSR for the node, and then sign each with its CA (-> save as nodeX.crt)
  • import node0.crt into my cassandra node0 keystore, node1.crt into node1 keystore etc.

Now:

  • Do I need to add anything to a trusted store?
  • Do I need to do anything with the CA file? Copy it to each client / node server?
  • What file do I need to provide my java client? cqlsh client?

Benefit: more copies of ssl certificates between nodes. Only one for each node and you are configured.

edit:

Ok, this is how I did it. If I made any mistakes, please let me know. I left things like JCE files and the correct cassandra.yaml configuration. They must be present on the server!

openssl genrsa -out clusterCA.key 2048 openssl req -x509 -new -key clusterCA.key -days <DAYS> -out clusterCA.pem keytool -importcert -alias clusterCA -file clusterCA.pem -keystore clustertruststore -storepass <PASS> #on each cassandra host for clients. for client replace nodename with clientname keytool -genkeypair -alias <NODENAME> -keyalg RSA -keysize 2048 -dname "CN=<NODENAME>,OU=<UNITNAME>,O=<ORGANISATION>" -keypass <PASS> -keystore <NODENAME>.keystore -storepass <PASS> -validity <DAYS> keytool -keystore <NODENAME>.keystore -alias <NODENAME> -certreq -file <NODENAME>.cert -storepass <PASS> -keypass <PASS> # sign it with CA openssl x509 -req -CA clusterCA.pem -CAkey clusterCa.key -in <NODENAME>.cert -out <NODENAME>.signed -days <DAYS> -CAcreateserial # add rootCA to host keytool -keystore <NODENAME>.keystore -storepass <PASS> -alias clusterCA -import -file clusterCA.pem -noprompt keytool -keystore <NODENAME>.keystore -storepass <PASS> -alias <NODENAME> -import -file <NODENAME>.signed -keypass <PASS> ## use <NODENAME>.keystore as truststore and keystore for cassandra node / client trust/keystore ## No need to copy keystores around. You only need it on your host ## create CQLSH pem keytool -importkeystore -srckeystore <NODENAME>.keystore -destkeystore <NODENAME>_user1.p12 -deststoretype PKCS12 openssl pkcs12 -in <NODENAME>_user1.p12 -out <NODENAME>_user1.pem -nodes ## use <NODENAME>_user1.pem as certfile for cqlsh 
+6
source share
1 answer

Your strategy is very good, and I do so. You want to have your own certification authority, and then create a CSR for each node. This is much easier to manage than trusting node certificates.

  • Each node will have its own keystore that stores its cert.
  • You will want each node to have an open CA certificate in its trusted network. This only happens if the require_client_auth parameter is set to true. I would recommend doing this, since it is not difficult to configure and adds an additional level of identification, which should be considered important.

It is also important to distinguish between network encryption and client encryption . Cassandra has different settings for each (documented in the links above). If you use client-to-node encryption, you will also want to have a trusted server for client certificates. You can use the same store of trust, as well as issue certificates to customers.

On the client-node side, here is an example from a java driver test, how to configure your SSLContext using your key and trust:

 /** * @param keyStorePath Path to keystore, if absent is not used. * @param trustStorePath Path to truststore, if absent is not used. * @return {@link com.datastax.driver.core.SSLOptions} with the given keystore and truststore path for * server certificate validation and client certificate authentication. */ public SSLOptions getSSLOptions(Optional<String> keyStorePath, Optional<String> trustStorePath) throws Exception { TrustManagerFactory tmf = null; if(trustStorePath.isPresent()) { KeyStore ks = KeyStore.getInstance("JKS"); ks.load(this.getClass().getResourceAsStream(trustStorePath.get()), DEFAULT_CLIENT_TRUSTSTORE_PASSWORD.toCharArray()); tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); } KeyManagerFactory kmf = null; if(keyStorePath.isPresent()) { KeyStore ks = KeyStore.getInstance("JKS"); ks.load(this.getClass().getResourceAsStream(keyStorePath.get()), DEFAULT_CLIENT_KEYSTORE_PASSWORD.toCharArray()); kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(ks, DEFAULT_CLIENT_KEYSTORE_PASSWORD.toCharArray()); } SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf != null ? kmf.getKeyManagers() : null, tmf != null ? tmf.getTrustManagers() : null, new SecureRandom()); return new SSLOptions(sslContext, SSLOptions.DEFAULT_SSL_CIPHER_SUITES); } 

Once you create an SSLOptions object, you can just pass it to your Cluster Builder, i.e.:

 cluster = Cluster.builder() .addContactPoint(host) .withSSL(sslOptions)) .build(); 

CQLSH supports SSL through the cqlshrc file. You can find an example of how to install here .

+5
source

Source: https://habr.com/ru/post/988034/


All Articles