Cassandra SSL с собственным центром сертификации
Я хочу настроить свой собственный ЦС для использования с кластером cassandra, чтобы мне не приходилось копировать все сертификаты каждый раз, когда я добавляю новый узел. Я прочитал несколько учебников для Cassandra и SSL, но все они работают с копированием сертификатов. Я немного потерялся в процессе CA
Это то, что я думаю, мне нужно сделать
- Создайте CA один раз
- Создайте CSR для каждого узла и затем подпишите каждый с помощью my CA (-> save as nodeX.crt)
- импортируйте node0.ЭЛТ к моему Кассандра node0 keystore, node1.crt в хранилище ключей node1 etc
Теперь:
- Нужно ли что-то добавлять в truststore?
- Нужно ли что-то делать с файлом CA? Скопировать его на каждый клиент / сервер узла?
- какой файл мне нужно предоставить клиенту java? клиент cqlsh?
Преимущество: больше нет копирования ssl-сертификатов между узлами. Только по одному для каждого узла, и все готово.
Правка:
ОК, Вот как я это сделал. Если бы я их сделал ошибки, пожалуйста, дайте мне знать. Я опустил такие вещи, как файлы JCE и настоящая Кассандра.и YAML конфигурации. Они должны присутствовать на сервере!
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
1 ответ:
Ваша стратегия очень разумна, и именно так я бы и поступил. Вы хотите иметь свой собственный центр сертификации, а затем создать CSR для каждого узла. Это гораздо проще в управлении, чем доверять сертификатам узлов по отдельности.
- каждый узел будет иметь свое хранилище ключей, хранящее его сертификат.
- вы хотите, чтобы каждый узел имел открытый сертификат CAs в своем хранилище доверия. Это только в том случае, если для параметра require_client_auth установлено значение true. Я бы рекомендовал сделать это, так как это не слишком сложно настроить и добавляет дополнительный уровень идентификации, который следует считать важным.
Также важно различать междоузельное шифрование и клиентское шифрование. Кассандра имеет различные настройки для каждого (документально подтвержденные в ссылках выше). При использовании шифрования "клиент-узел" вы также захотите иметь хранилище доверия для клиентских сертификатов. Вы можете использовать то же хранилище доверия, а также выдавать сертификаты клиентам.
На клиент-узел бокового пример из Java-драйвер тесты, как настроить Возвращаетsslcontextэкземпляр, используя свой ключ и базы доверенных сертификатов:
/** * @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's 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); }
Как только вы создадите объект SSLOptions, вы можете просто передать его в свой конструктор кластеров, т. е.:
cluster = Cluster.builder() .addContactPoint(host) .withSSL(sslOptions)) .build();
CQLSH поддерживает SSL через файл cqlshrc. Вы можете найти пример того, как это сделать здесь.