This is an automated email from the ASF dual-hosted git repository.

dajac pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 1c02a764eca KAFKA-12703; Allow unencrypted private keys when using PEM 
files (#11916)
1c02a764eca is described below

commit 1c02a764eca19d2606259a4efa58f6cfdfc8e70a
Author: Dejan Maric <[email protected]>
AuthorDate: Mon May 16 09:25:05 2022 +0200

    KAFKA-12703; Allow unencrypted private keys when using PEM files (#11916)
    
    Reviewers: David Jacot <[email protected]>
---
 .../org/apache/kafka/common/config/SslConfigs.java     |  2 +-
 .../common/security/ssl/DefaultSslEngineFactory.java   |  2 --
 .../kafka/common/network/SslTransportLayerTest.java    | 18 ++++--------------
 .../security/ssl/DefaultSslEngineFactoryTest.java      | 11 ++++++++---
 docs/security.html                                     |  2 +-
 5 files changed, 14 insertions(+), 21 deletions(-)

diff --git 
a/clients/src/main/java/org/apache/kafka/common/config/SslConfigs.java 
b/clients/src/main/java/org/apache/kafka/common/config/SslConfigs.java
index 5061ed5cfca..62343a23b57 100644
--- a/clients/src/main/java/org/apache/kafka/common/config/SslConfigs.java
+++ b/clients/src/main/java/org/apache/kafka/common/config/SslConfigs.java
@@ -96,7 +96,7 @@ public class SslConfigs {
 
     public static final String SSL_KEY_PASSWORD_CONFIG = "ssl.key.password";
     public static final String SSL_KEY_PASSWORD_DOC = "The password of the 
private key in the key store file or "
-        + "the PEM key specified in `ssl.keystore.key'. This is required for 
clients only if two-way authentication is configured.";
+        + "the PEM key specified in `ssl.keystore.key'.";
 
     public static final String SSL_TRUSTSTORE_TYPE_CONFIG = 
"ssl.truststore.type";
     public static final String SSL_TRUSTSTORE_TYPE_DOC = "The file format of 
the trust store file.";
diff --git 
a/clients/src/main/java/org/apache/kafka/common/security/ssl/DefaultSslEngineFactory.java
 
b/clients/src/main/java/org/apache/kafka/common/security/ssl/DefaultSslEngineFactory.java
index a46626e7d79..ac16c21bfc8 100644
--- 
a/clients/src/main/java/org/apache/kafka/common/security/ssl/DefaultSslEngineFactory.java
+++ 
b/clients/src/main/java/org/apache/kafka/common/security/ssl/DefaultSslEngineFactory.java
@@ -287,8 +287,6 @@ public final class DefaultSslEngineFactory implements 
SslEngineFactory {
         } else if (PEM_TYPE.equals(type) && path != null) {
             if (password != null)
                 throw new InvalidConfigurationException("SSL key store 
password cannot be specified with PEM format, only key password may be 
specified");
-            else if (keyPassword == null)
-                throw new InvalidConfigurationException("SSL PEM key store is 
specified, but key password is not specified.");
             else
                 return new FileBasedPemStore(path, keyPassword, true);
         } else if (path == null && password != null) {
diff --git 
a/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java
 
b/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java
index 5b0d4172d8c..d78e5f44b27 100644
--- 
a/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java
+++ 
b/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java
@@ -490,9 +490,7 @@ public class SslTransportLayerTest {
     }
 
     /**
-     * Test with PEM key store files without key password for client key 
store. We don't allow this
-     * with PEM files since unprotected private key on disk is not safe. We do 
allow with inline
-     * PEM config since key config can be encrypted or externalized similar to 
other password configs.
+     * Test with PEM key store files without key password for client key store.
      */
     @ParameterizedTest
     @ArgumentsSource(SslTransportLayerArgumentsProvider.class)
@@ -502,27 +500,19 @@ public class SslTransportLayerTest {
         TestSslUtils.convertToPem(args.sslClientConfigs, !useInlinePem, false);
         
args.sslServerConfigs.put(BrokerSecurityConfigs.SSL_CLIENT_AUTH_CONFIG, 
"required");
         server = createEchoServer(args, SecurityProtocol.SSL);
-        if (useInlinePem)
-            verifySslConfigs(args);
-        else
-            assertThrows(KafkaException.class, () -> 
createSelector(args.sslClientConfigs));
+        verifySslConfigs(args);
     }
 
     /**
      * Test with PEM key store files without key password for server key 
store.We don't allow this
-     * with PEM files since unprotected private key on disk is not safe. We do 
allow with inline
-     * PEM config since key config can be encrypted or externalized similar to 
other password configs.
+     * with PEM files since unprotected private key on disk is not safe.
      */
     @ParameterizedTest
     @ArgumentsSource(SslTransportLayerArgumentsProvider.class)
     public void testPemFilesWithoutServerKeyPassword(Args args) throws 
Exception {
         TestSslUtils.convertToPem(args.sslServerConfigs, !args.useInlinePem, 
false);
         TestSslUtils.convertToPem(args.sslClientConfigs, !args.useInlinePem, 
true);
-
-        if (args.useInlinePem)
-            verifySslConfigs(args);
-        else
-            assertThrows(KafkaException.class, () -> createEchoServer(args, 
SecurityProtocol.SSL));
+        verifySslConfigs(args);
     }
 
     /**
diff --git 
a/clients/src/test/java/org/apache/kafka/common/security/ssl/DefaultSslEngineFactoryTest.java
 
b/clients/src/test/java/org/apache/kafka/common/security/ssl/DefaultSslEngineFactoryTest.java
index 0e494cc529d..fc3726ac59a 100644
--- 
a/clients/src/test/java/org/apache/kafka/common/security/ssl/DefaultSslEngineFactoryTest.java
+++ 
b/clients/src/test/java/org/apache/kafka/common/security/ssl/DefaultSslEngineFactoryTest.java
@@ -18,7 +18,6 @@ package org.apache.kafka.common.security.ssl;
 
 import org.apache.kafka.common.config.SslConfigs;
 import org.apache.kafka.common.config.types.Password;
-import org.apache.kafka.common.errors.InvalidConfigurationException;
 import org.apache.kafka.test.TestUtils;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -33,7 +32,6 @@ import java.util.Map;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
 
 public class DefaultSslEngineFactoryTest {
 
@@ -291,7 +289,14 @@ public class DefaultSslEngineFactoryTest {
         configs.put(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG,
                 pemFilePath(pemAsConfigValue(KEY, CERTCHAIN).value()));
         configs.put(SslConfigs.SSL_KEYSTORE_TYPE_CONFIG, 
DefaultSslEngineFactory.PEM_TYPE);
-        assertThrows(InvalidConfigurationException.class, () -> 
factory.configure(configs));
+        configs.put(SslConfigs.SSL_KEY_PASSWORD_CONFIG, null);
+        factory.configure(configs);
+
+        KeyStore keyStore = factory.keystore();
+        List<String> aliases = Collections.list(keyStore.aliases());
+        assertEquals(Collections.singletonList("kafka"), aliases);
+        assertNotNull(keyStore.getCertificate("kafka"), "Certificate not 
loaded");
+        assertNotNull(keyStore.getKey("kafka", null), "Private key not 
loaded");
     }
 
     @Test
diff --git a/docs/security.html b/docs/security.html
index 846ce5f20bc..21ec72cec50 100644
--- a/docs/security.html
+++ b/docs/security.html
@@ -271,7 +271,7 @@ keyUsage               = digitalSignature, 
keyEncipherment</code></pre>
 
             <p>Store password configs <code>ssl.keystore.password</code> and 
<code>ssl.truststore.password</code> are not used for PEM.
             If private key is encrypted using a password, the key password 
must be provided in <code>ssl.key.password</code>. Private keys may be provided
-            in unencrypted form without a password when PEM is specified 
directly in the config value. In production deployments, configs should be 
encrypted or
+            in unencrypted form without a password. In production deployments, 
configs should be encrypted or
             externalized using password protection feature in Kafka in this 
case. Note that the default SSL engine factory has limited capabilities for 
decryption
             of encrypted private keys when external tools like OpenSSL are 
used for encryption. Third party libraries like BouncyCastle may be integrated 
witn a
             custom <code>SslEngineFactory</code> to support a wider range of 
encrypted private keys.</p>

Reply via email to