You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 6 Next »


Status

Current state: DISCUSS

Discussion thread: https://www.mail-archive.com/dev@kafka.apache.org/msg101011.html

JIRA: Unable to render Jira issues macro, execution error.

Please keep the discussion on the mailing list rather than commenting on the wiki (wiki discussions get unwieldy fast).

Motivation

Kafka adoption is growing day-by-day and it is used by all sizes of organizations serving varied technical and business domains like banking, entertainment, food/transportation logistics, financial technology to name a few. These organizations depending upon their size and domain may have more internal and external InfoSec/AppSec/Compliance standards they have to meet while using Kafka. SSL/TLS communication is very critical part of those standards. While Kafka supports SSL communication sometimes it becomes challenging to use out-of-the-box solution provided by Kafka for SSL/TLS given the organization's needs.

Currently Kafka provides several SSL related configurations that typically starts with 'ssl.' prefix. Those configurations focuses on ability to specify Keystore and Truststores parameters, supply custom java security Providers etc. However as mentioned before there is still room to allow more flexibility/extensibility to allow organizations to fully comply to their requirement without one-off customizations of Kafka.

According to JSSE Documentation SSLContext and SSLEngine are the endpoint classes for the secure connection. Moreover, SSLEngine is created by SSLContext and can be further customized according to the needs. Hence if Kafka provides a way to customize SSLContext and/or SSLEngine it would be a great lever and provide the ultimate extensibility for Kafka users.

This work is influenced by past KIPs (mentioned below) and is a fresh attempt to provide a conclusive solution. It also got more energy from discussion on KIP-486: Support custom way to load KeyStore and TrustStore.

Past KIPs,

KIP-76 Enable getting password from executable rather than passing as plaintext in config files

KIP-383: Pluggable interface for SSL Factory

This KIP proposes the work on top of what has been done already for SSL configuration like KIP-226 - Dynamic Broker Configuration and KIP-492: Add java security providers in Kafka Security config.

Our primary goal is: Instead of keep adding various ssl configurations to customize smaller portions of SSLContext/Engine, we should have a single configurable/pluggable SSLContext/Engine functionality.

Public Interfaces

New configuration

ssl.engine.factory.class - This configuration will take class of the below interface's type and will be used to create javax.net.ssl.SSLEngine object.

Default value will be as mentioned below.

final static String SSL_ENGINEFACTORY_CLASS_CONFIG = "ssl.engine.factory.class";
final static String DEFAULT_SSL_ENGINEFACTORY_CLASS = "org.apache.kafka.common.security.ssl.DefaultSslEngineFactory";


Interface for SSLEngineFactory

Below is the interface suggested for this.

In the interface we provide a way to customize SSLContext and SSLEngine both because SSLContext ideally has all the data points to be customized (see JSSE reference diagram) but for Kafka SSLEngine needs to be further configured based on Client or Server Mode as it is done currently.


package org.apache.kafka.common.security.ssl;

import org.apache.kafka.common.network.Mode;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import java.util.Map;
import java.util.Set;

public interface SslEngineFactory {

	/**
     * Creates SSLContext by providing required key material and {@code java.security.SecureRandom}
     *
     * @return	The SSLContext.
     */
	SSLContext createSSLContext();

    /**
     * Creates a new SSLEngine object.
     *
     * @param mode      Whether to use client or server mode.
     * @param peerHost  The peer host to use. This is used in client mode if endpoint validation is enabled.
     * @param peerPort  The peer port to use. This is a hint and not used for validation.
     * @param endpointIdentification Endpoint identification algorithm for client mode.
     * @return          The new SSLEngine.
     */
    SSLEngine createSSLEngine(Mode mode, String peerHost, int peerPort, String endpointIdentification);

    /**
     * Returns the currently used configurations by this engine.
     * @return
     */
    Map<String, Object> currentConfigs();

    /**
     * Returns the reconfigurable configs used by this engine.
     * @return
     */
    Set<String> reconfigurableConfigs();

    /**
     * Returns true if this engine needs to be rebuilt.
     *
     * @param nextConfigs       The configuration we want to use.
     * @return                  True only if this builder should be rebuilt.
     */
    boolean shouldRebuiltFor(Map<String, Object> nextConfigs);
}


Why we allow SSLContext and SSLEngine creation in the interface?

This is because as we mentioned in the motivation - JSSE documentation makes it clear that SSLContext can be used to create all the other objects that are needed for SSL communication including SSLEngine. Also from the application security domain's perspective control over SSLContext was recommended to us in order to achieve customizations. However as we pointed out before Kafka needs to further configure SSLEngine for client or server Mode hence we want to leave that also overridable. 

Proposed Changes

Currently SslFactory.java uses SslEngineBuilder.java. Instead of that we will modify SslFactory.java to load a class configured via the new configuration 'ssl.engine.factory.class' and delegate the SSLEngine creation call to the implementation. 

We will also provide default implementation for the 'ssl.engine.factory.class' which will be used in absence of provided config.

Default implementation would be along the lines (but not necessarily the same) of - sample code which is copied from current SslEngineBuilder.java.

Which classes will be deleted?

  • SslEngineBuilder.java (functionality moved to DefaultSslEngineFactory.java)

Which classes will be added?

  • SslEngineFactory.java Interface
  • SslEngineFactoryInstantiator.java (as an inner class to SslFactory)
  • DefaultSslEngineFactory.java (mostly having code from existing SslEngineBuilder)

Which classes will be modified?

  • SslFactory.java 

How does configs get to the implementation class?

The configuration of Map will be passed to the implementation class via the constructor. See below example,

Detailed code link: My fork

public DefaultSslEngineFactory(Map<String, ?> configs) {
...
...
}


These configuration will be passed from SslFactory to the implementation of the SslEngineFactory interface via reflection like below

public class SslFactory implement Reconfigurable {
...
...
     sslEngineFactoryClass.getDeclaredConstructor(Map.class).newInstance(configs);
...
}


Support for reconfiguration of custom configs

By custom configs we mean the configs used by the SslEngineFactory's implementation. Those configs does not have to be part of definition of Kafka configs since only the implementation class knows what are those.

This need to be explored more. We don't have clarity on how this can be achieved.

Other challenge

Currently reconfigurations are pushed from Kafka code base to the reconfigurable classes. However, depending upon SslEngineFactory's implementation we could have some events/changes detected by the implementation first and we would need to trigger reconfiguration on SslFactory in order to get re-initialized!

Probably this could be achieved by passing listener to those implementation changes but this needs to be further explored.

Sequence Diagram of SslFactory instantiating the SslEngineFactory implementation

Sequence diagram for the Reconfiguration flow

Compatibility, Deprecation, and Migration Plan

  • What impact (if any) will there be on existing users?

There will be no impact on existing users who do not specify the new configuration.

  • If we are changing behavior how will we phase out the older behavior?

No impact

  • If we need special migration tools, describe them here.

None

  • When will we remove the existing behavior?

Not applicable since old code behavior will be kept with default implementation of DefaultSslEngineFactory.

Rejected Alternatives

As mentioned in the motivation there are/were several attempts to make various ssl configurations pluggable over time focusing on specific aspect of the SSL configuration. However, this KIP proposes to allow customization at SSLContext/SSLEgnine level hence there are no alternatives applicable in our opinion. However there are couple of implementation alternatives that we rejected and document as below.

Why is SslFactory not the pluggable interface directly

This is because currently SslFactory does certain validations which we want to keep separate and mandate those checks across any possible implementation of pluggable class. Also, once we start writing the reconfigurable classes we realize that we need two classes - 1) Engine factory implementation and 2) Container of the factory implementation. 



  • No labels