Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • To allow plugging in custom JSSE Provider. The requirement to plugin a custom JSSE Provider is out of scope for this CIP. 
  • Not sure if we need to To make SSLFactory#tlsInstanceProtocolSubstituion() pluggable (Will seek guidance in the Discussion thread)because regardless of pluggability requirements it is just fetching the list of TLS protocol list

Proposed Changes

I propose following changes,

  1. Create a new Java interface 'SslContextFactoryISslContextFactory'
  2. Adding a new configuration like 'ssl._context._factory.class' with default value provided by newly created DefaultSslContextFactoryImpl.java
    1. Make necessary changes in Config.java and DatabaseDescriptor.java to load the new config if provided
  3. Create a new DefaultSslContextFactoryImpl.java implementing the new SslContextFactory ISslContextFactory interface
    1. This will be a 'final' class and will be considered internal without expectations of being extensible by any other public implementation
    2. This will be the only default implementation class for the SslContextFactory interface
  4. Make changes in the existing SSLFactory and other classes to use the dependency on the newly created SslContextFactory
  5. Make necessary changes to the existing code to allow triggering Hotreloading on the pluggable SslContextFactory
  6. Make changes in the existing EncryptionOptions.java that uses 'keystore' to determine if it needs to enable encrypted connection

New or Changed Public Interfaces

New configuration (optional)

The new configuration key introduced is optional to be configured ONLY in the case you need to use your own implementation for SSL Context creation.

Code Block
languagetext
titleNew Configuration
 ssl.context.factory.class

...

_context_factory:
        class_name: org.apache.cassandra.security.YourSslContextFactoryImpl
        parameters:
          key1: "value1"
          key2: "value2"
          key3: "value3"


New ISslContextFactory interface

Code Block
languagejava
titleSslContextFactoryISslContextFactory
package org.apache.cassandra.security;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;

import io.netty.handler.ssl.CipherSuiteFilter;
import io.netty.handler.ssl.SslContext;
import org.apache.cassandra.config.EncryptionOptions;

/**
 * The purpose of this interface is to provide pluggable mechanism for creating custom JSSE and Netty SSLContext
* objects.
 * Please use the Cassandra configuration key {@code ssl._context._factory.class} and provide a custom class-name
 * implementing this interface with parameters to be used to plugin a your own way to load the SSLContext.
*
* Implementation of this interface must have a constructor with argument of type {@code Map<String,String>} to allow
*
  custom parameters to be passed from the Cassandra yaml configuration.
*
* Since on top of Netty, Cassandra is internally using JSSE SSLContext also for certain use-cases- this interface
 * has methods for both.
 */
public interface SslContextFactory
{
    /**

* Below is an example of how to configure a custom implementation with parameters
* <pre>
* ssl_context_factory:
*   class_name: org.apache.cassandra.security.YourSslContextFactoryImpl
*   parameters:
*     key1: "value1"
*    Creates JSSE SSLContext.
key2: "value2"
*     key3: "value3"
* </pre>
*/
public interface ISslContextFactory
{
/**
* Creates JSSE SSLContext.
*
* @param options EncryptionOptions that could be used for the SSL context creation
     * @param buildTruststore {@code true} if the caller requires Truststore; {@code false} otherwise
* @return
* @throws SSLException in case *the @return
Ssl Context creation fails for some reason
*/
    SSLContext createJSSESslContext(EncryptionOptions options, boolean buildTruststore) throws SSLException;

    /**
     * Creates Netty's SslContext object.
     *
     * @param options EncryptionOptions that could be used for the SSL context creation
     * @param buildTruststore {@code true} if the caller requires Truststore; {@code false} otherwise
     * @param socketType {@link SocketType} for Netty's Inbound or Outbound channels
* @param useOpenSsl {@code true} if openSsl is enabled;{@code false} otherwise
* @param cipherFilter to allow Netty's cipher suite filtering, e.g.
     * {@link io.netty.handler.ssl.SslContextBuilder#ciphers(Iterable, CipherSuiteFilter)}
* @return
* @throws SSLException in case the *Ssl @return
Context creation fails for some reason
*/
    SslContext createNettySslContext(EncryptionOptions options, boolean buildTruststore, SocketType socketType,
 boolean useOpenSsl, CipherSuiteFilter cipherFilter) throws SSLException;

/**
* Initializes hot reloading of the security keys/certs. The implementation must guarantee this to be thread safe.
* @param serverOpts Server encryption options (Internode)
* @param clientOpts Client encryption options (Native Protocol)
* @throws CipherSuiteFilter cipherFilter);

    SSLException
*/
void initHotReloading(EncryptionOptions.ServerEncryptionOptions serverOpts, EncryptionOptions clientOpts) throws SSLException;
/**
     * Returns if any changes require the reloading of the SSL context returned by this factory.
     * This will be called by Cassandra's periodic polling for any potential changes that will reload the SSL context
     * . However only newer connections established after the reload will use the reloaded SSL context.
     * @return
     */
    boolean shouldReload();

    /**
* Indicates if the process *holds SocketTypethe toinbound/listening differentiateend Serverof andthe Client. This is primarily used for Netty's Inbound and Outbound channels.
     */
    socket ({@link SSLFactory.SocketType#SERVER})), or the
* outbound side ({@link SSLFactory.SocketType#CLIENT}).
*/
enum SocketType {
        SERVER, CLIENT;
    }
}

Compatibility, Deprecation, and Migration Plan

...