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 6

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. Вы можете найти пример того, как это сделать здесь.