This is an automated email from the ASF dual-hosted git repository. mridulm80 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/master by this push: new 83434af22284 [SPARK-46132][CORE] Support key password for JKS keys for RPC SSL 83434af22284 is described below commit 83434af22284482d4e805d8be625f733b074928b Author: Hasnain Lakhani <hasnain.lakh...@databricks.com> AuthorDate: Tue Dec 12 23:35:13 2023 -0600 [SPARK-46132][CORE] Support key password for JKS keys for RPC SSL ### What changes were proposed in this pull request? Add support for a separate key password in addition to the key store password for JKS keys. This is needed for keys which may have a key password in addition to a key store password. We already had this support for the UI SSL support, so for compatibility we should have it here. This wasn't done earlier as I wasn't sure how to implement it but the discussion in https://github.com/apache/spark/pull/43998#discussion_r1406993411 suggested the right way. ### Why are the changes needed? These are needed to support users who may have such keys configured. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Added some unit tests ``` build/sbt > project network-common > testOnly ``` ### Was this patch authored or co-authored using generative AI tooling? No Closes #44264 from hasnain-db/separate-pw. Authored-by: Hasnain Lakhani <hasnain.lakh...@databricks.com> Signed-off-by: Mridul Muralidharan <mridul<at>gmail.com> --- .../org/apache/spark/network/ssl/SSLFactory.java | 11 ++- .../apache/spark/network/ssl/SSLFactorySuite.java | 104 +++++++++++++++++++++ 2 files changed, 111 insertions(+), 4 deletions(-) diff --git a/common/network-common/src/main/java/org/apache/spark/network/ssl/SSLFactory.java b/common/network-common/src/main/java/org/apache/spark/network/ssl/SSLFactory.java index 0ae83eb5fd68..82951d213011 100644 --- a/common/network-common/src/main/java/org/apache/spark/network/ssl/SSLFactory.java +++ b/common/network-common/src/main/java/org/apache/spark/network/ssl/SSLFactory.java @@ -89,7 +89,7 @@ public class SSLFactory { private void initJdkSslContext(final Builder b) throws IOException, GeneralSecurityException { - this.keyManagers = keyManagers(b.keyStore, b.keyStorePassword); + this.keyManagers = keyManagers(b.keyStore, b.keyPassword, b.keyStorePassword); this.trustManagers = trustStoreManagers( b.trustStore, b.trustStorePassword, b.trustStoreReloadingEnabled, b.trustStoreReloadIntervalMs @@ -391,13 +391,16 @@ public class SSLFactory { } } - private static KeyManager[] keyManagers(File keyStore, String keyStorePassword) + private static KeyManager[] keyManagers( + File keyStore, String keyPassword, String keyStorePassword) throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, UnrecoverableKeyException { KeyManagerFactory factory = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm()); - char[] passwordCharacters = keyStorePassword != null? keyStorePassword.toCharArray() : null; - factory.init(loadKeyStore(keyStore, passwordCharacters), passwordCharacters); + char[] keyStorePasswordChars = keyStorePassword != null? keyStorePassword.toCharArray() : null; + char[] keyPasswordChars = keyPassword != null? + keyPassword.toCharArray() : keyStorePasswordChars; + factory.init(loadKeyStore(keyStore, keyStorePasswordChars), keyPasswordChars); return factory.getKeyManagers(); } diff --git a/common/network-common/src/test/java/org/apache/spark/network/ssl/SSLFactorySuite.java b/common/network-common/src/test/java/org/apache/spark/network/ssl/SSLFactorySuite.java new file mode 100644 index 000000000000..922d0f22c25c --- /dev/null +++ b/common/network-common/src/test/java/org/apache/spark/network/ssl/SSLFactorySuite.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.spark.network.ssl; + +import java.io.File; + +import io.netty.buffer.ByteBufAllocator; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +import static org.apache.spark.network.ssl.SslSampleConfigs.*; + +public class SSLFactorySuite { + + @Test + public void testBuildWithJKSAndPEMWithPasswords() throws Exception { + SSLFactory factory = new SSLFactory.Builder() + .openSslEnabled(true) + .requestedProtocol("TLSv1.3") + .keyStore(new File(SslSampleConfigs.keyStorePath), "password") + .privateKey(new File(SslSampleConfigs.privateKeyPath)) + .privateKeyPassword("password") + .keyPassword("password") + .certChain(new File(SslSampleConfigs.certChainPath)) + .trustStore( + new File(SslSampleConfigs.trustStorePath), + "password", + true, + 10000 + ) + .build(); + factory.createSSLEngine(true, ByteBufAllocator.DEFAULT); + } + + @Test + public void testBuildWithJKSAndPEMWithOnlyJKSPassword() throws Exception { + SSLFactory factory = new SSLFactory.Builder() + .openSslEnabled(true) + .requestedProtocol("TLSv1.3") + .keyStore(new File(SslSampleConfigs.keyStorePath), "password") + .privateKey(new File(SslSampleConfigs.unencryptedPrivateKeyPath)) + .keyPassword("password") + .certChain(new File(SslSampleConfigs.unencryptedCertChainPath)) + .trustStore( + new File(SslSampleConfigs.trustStorePath), + "password", + true, + 10000 + ) + .build(); + factory.createSSLEngine(true, ByteBufAllocator.DEFAULT); + } + + @Test + public void testBuildWithJKSKeyStorePassword() throws Exception { + // if key password is null, fall back to keystore password + SSLFactory factory = new SSLFactory.Builder() + .requestedProtocol("TLSv1.3") + .keyStore(new File(SslSampleConfigs.keyStorePath), "password") + .trustStore( + new File(SslSampleConfigs.trustStorePath), + "password", + true, + 10000 + ) + .build(); + factory.createSSLEngine(true, ByteBufAllocator.DEFAULT); + } + + @Test + public void testKeyAndKeystorePasswordsAreDistinct() throws Exception { + assertThrows(RuntimeException.class, () -> { + // Set the wrong password, validate we fail + SSLFactory factory = new SSLFactory.Builder() + .requestedProtocol("TLSv1.3") + .keyStore(new File(SslSampleConfigs.keyStorePath), "password") + .keyPassword("wrong") + .trustStore( + new File(SslSampleConfigs.trustStorePath), + "password", + true, + 10000 + ) + .build(); + factory.createSSLEngine(true, ByteBufAllocator.DEFAULT); + }); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@spark.apache.org For additional commands, e-mail: commits-h...@spark.apache.org