Versions Compared

Key

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

Table of Contents


Status

Current state: VOTING ACCEPTED

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

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

JIRA:

Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyKAFKA-8890

PR: https://github.com/apache/kafka/pull/8338

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

...

However, Kafka configures the SSLEngine for Client and Server both modes. Hence according to existing code it would be useful to make SslEngineBuilder pluggable. That will provide us a way to configure SSLContext object in a flexible way and at the same time will allow creation of SSLEngine with Client/Server mode.

...

Default value will be as mentioned below.

Code Block
    public static final String SSL_ENGINE_FACTORY_CLASS_CONFIG = "ssl.engine.factory.class";
    public static final String DEFAULT_SSL_ENGINE_FACTORY_CLASS = "org.apache.kafka.common.security.ssl.DefaultSslEngineFactory.class.getCanonicalName();
    public static final String SSL_ENGINE_FACTORY_CLASS_DOC = "The class of type org.apache.kafka.common.security.auth.SslEngineFactory to provide SSLEngine objects. Default value is " + DEFAULT_SSL_ENGINE_FACTORY_CLASS;


Interface for SslEngineFactory

...

Code Block
package org.apache.kafka.common.security.sslauth;

import org.apache.kafka.common.network.ModeConfigurable;

import javax.net.ssl.SSLEngine;
import java.io.Closeable;
import java.security.KeyStore;
import java.util.Map;
import java.util.Set;

public/**
 * Plugin interface SslEngineFactory {

    /**
     * Create a new SSLEngine object.
     *
     * @param mode                   Whether to use client or server mode. for allowing creation of SSLEngine object in a custom way.
 * Example: You want to use custom way to load your key material and trust material needed for SSLContext.
 * However, keep in mind that this is complementary to the existing Java Security Provider's mechanism and not a competing
 * solution.
 */
public interface SslEngineFactory extends Configurable, Closeable {

    /**
     * Create a new SSLEngine object to be used by the client.
     *
     * @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 createSslEnginecreateClientSslEngine(Mode mode, String peerHost, int peerPort, String endpointIdentification);

    /**
     * ReturnsCreate truea ifnew SSLEngine needsobject to be rebuiltused by the server.
     *
     * @param nextConfigs peerHost               The configuration we want to usepeer 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.
     * @return The new SSLEngine.
     */
    SSLEngine createServerSslEngine(String peerHost, int peerPort);

 	/**
     * TrueReturns onlytrue if SSLEngine needs to be rebuilt. This method will be called when reconfiguration is triggered on
     * {@link org.apache.kafka.common.security.ssl.SslFactory}. Based on the <i>nextConfigs</i>, this method will
     * decide whether underlying SSLEngine object needs shouldto be rebuilt. If this method returns true, the
     * {@link org.apache.kafka.common.security.ssl.SslFactory} will re-create instance of this object and run other
     * checks before deciding to use the new object for the <i>new incoming connection</i> requests.The existing connections
     * are not impacted by this and will not see any changes done as part of reconfiguration.
     *
     * <pre>
     *     Example: If the implementation depends on the file based key material  boolean shouldBeRebuilt(Map<String, Object> nextConfigs);

    /**it can check if the file is updated
     *     compared to the previous/last-loaded timestamp and return true.
     * </pre>
     *
     * @param nextConfigs       The configuration we want to use.
     * Returns @return                  True only if the namesunderlying ofSSLEngine configsobject that mayshould be reconfiguredrebuilt.
     */
    Set<String>boolean reconfigurableConfigs(shouldBeRebuilt(Map<String, Object> nextConfigs);

    /**
     * Returns existing configurationthe names of configs that may be reconfigured.
     */
    Map<String, Object> configsSet<String> reconfigurableConfigs();

    /**
     * Returns keystore.
     * @return
     */
    KeyStore keystore();

    /**
     * Returns truststore.
     * @return
     */
    KeyStore truststore();
}

...

The configuration of Map will be passed to the implementation class via the constructorconfigure() method. See below example,


Code Block
public DefaultSslEngineFactory implements SslEngineFactory {
...
...
	/* Default empty argument constructor */

	/* implement configure() method */
    @Override
    public void configure(Map<String, ?> configs) {
    ...
    }
...
...
}


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

Code Block
public class SslFactory implement Reconfigurable {
...
...
     private SslEngineFactory instantiateSslEngineFactory(Map<String, Object> configs) {
        @SuppressWarnings("unchecked")
        Class<? extends SslEngineFactory> sslEngineFactoryClass.getDeclaredConstructor(Map.class).newInstance(configs); =
                (Class<? extends SslEngineFactory>) configs.get(SslConfigs.SSL_ENGINE_FACTORY_CLASS_CONFIG);
        SslEngineFactory sslEngineFactory = Utils.newInstance(sslEngineFactoryClass);
        sslEngineFactory.configure(configs);
        this.sslEngineFactoryConfig = configs;
        return sslEngineFactory;
    }
...
}


Support for reconfiguration of custom configs

...

This is because currently SslFactory does certain validations which we want to keep separate and mandate those checks across any possible implementation of pluggable ssl context class. Also, once we start writing the reconfigurable classes we realize that we need two classes - 1) SslEngineFactory implementation and 2) Container of the factory implementation. We believe that keeping SslFactory as Reconfigurable object and help reconfigure the underlying SslEngineFactory will simplify the implementations of SslEngineFactory.

...