From a5b93cc70b867adca542d79d17126d30b2afbd27 Mon Sep 17 00:00:00 2001 From: Alex Rankin Date: Tue, 2 Oct 2018 16:52:12 +0100 Subject: [PATCH 1/4] Adding ability to specify custom SSLContext for client --- .../org/apache/zookeeper/common/X509Util.java | 101 ++++++++++-------- .../zookeeper/common/ZKClientSSLContext.java | 18 ++++ .../org/apache/zookeeper/common/ZKConfig.java | 1 + .../apache/zookeeper/common/X509UtilTest.java | 50 +++++++++ .../common/ZKTestClientSSLContext.java | 12 +++ 5 files changed, 138 insertions(+), 44 deletions(-) create mode 100644 src/java/main/org/apache/zookeeper/common/ZKClientSSLContext.java create mode 100644 src/java/test/org/apache/zookeeper/common/X509UtilTest.java create mode 100644 src/java/test/org/apache/zookeeper/common/ZKTestClientSSLContext.java diff --git a/src/java/main/org/apache/zookeeper/common/X509Util.java b/src/java/main/org/apache/zookeeper/common/X509Util.java index cc8662e7984..41a324528ea 100644 --- a/src/java/main/org/apache/zookeeper/common/X509Util.java +++ b/src/java/main/org/apache/zookeeper/common/X509Util.java @@ -85,60 +85,73 @@ public static SSLContext createSSLContext() throws SSLContextException { } public static SSLContext createSSLContext(ZKConfig config) throws SSLContextException { - KeyManager[] keyManagers = null; - TrustManager[] trustManagers = null; + if (config.getProperty(ZKConfig.SSL_CLIENT_CONTEXT) != null) { + LOG.debug("Loading SSLContext from property '" + ZKConfig.SSL_CLIENT_CONTEXT + "'"); + String sslClientContextClass = config.getProperty(ZKConfig.SSL_CLIENT_CONTEXT); + try { + Class sslContextClass = Class.forName(sslClientContextClass); + ZKClientSSLContext sslContext = (ZKClientSSLContext) sslContextClass.newInstance(); + return sslContext.getSSLContext(); + } catch (ClassNotFoundException | ClassCastException | InstantiationException | IllegalAccessException e) { + throw new SSLContextException("Could not retrieve the SSLContext from source '" + sslClientContextClass + + "' provided in the property '" + ZKConfig.SSL_CLIENT_CONTEXT + "'", e); + } + } else { + KeyManager[] keyManagers = null; + TrustManager[] trustManagers = null; - String keyStoreLocationProp = config.getProperty(ZKConfig.SSL_KEYSTORE_LOCATION); - String keyStorePasswordProp = config.getProperty(ZKConfig.SSL_KEYSTORE_PASSWD); + String keyStoreLocationProp = config.getProperty(ZKConfig.SSL_KEYSTORE_LOCATION); + String keyStorePasswordProp = config.getProperty(ZKConfig.SSL_KEYSTORE_PASSWD); - // There are legal states in some use cases for null KeyManager or TrustManager. - // But if a user wanna specify one, location and password are required. + // There are legal states in some use cases for null KeyManager or TrustManager. + // But if a user wanna specify one, location and password are required. - if (keyStoreLocationProp == null && keyStorePasswordProp == null) { - LOG.warn("keystore not specified for client connection"); - } else { - if (keyStoreLocationProp == null) { - throw new SSLContextException("keystore location not specified for client connection"); - } - if (keyStorePasswordProp == null) { - throw new SSLContextException("keystore password not specified for client connection"); - } - try { - keyManagers = new KeyManager[]{ - createKeyManager(keyStoreLocationProp, keyStorePasswordProp)}; - } catch (KeyManagerException e) { - throw new SSLContextException("Failed to create KeyManager", e); + if (keyStoreLocationProp == null && keyStorePasswordProp == null) { + LOG.warn("keystore not specified for client connection"); + } else { + if (keyStoreLocationProp == null) { + throw new SSLContextException("keystore location not specified for client connection"); + } + if (keyStorePasswordProp == null) { + throw new SSLContextException("keystore password not specified for client connection"); + } + try { + keyManagers = new KeyManager[]{ + createKeyManager(keyStoreLocationProp, keyStorePasswordProp)}; + } catch (KeyManagerException e) { + throw new SSLContextException("Failed to create KeyManager", e); + } } - } - String trustStoreLocationProp = config.getProperty(ZKConfig.SSL_TRUSTSTORE_LOCATION); - String trustStorePasswordProp = config.getProperty(ZKConfig.SSL_TRUSTSTORE_PASSWD); + String trustStoreLocationProp = config.getProperty(ZKConfig.SSL_TRUSTSTORE_LOCATION); + String trustStorePasswordProp = config.getProperty(ZKConfig.SSL_TRUSTSTORE_PASSWD); - if (trustStoreLocationProp == null && trustStorePasswordProp == null) { - LOG.warn("Truststore not specified for client connection"); - } else { - if (trustStoreLocationProp == null) { - throw new SSLContextException("Truststore location not specified for client connection"); - } - if (trustStorePasswordProp == null) { - throw new SSLContextException("Truststore password not specified for client connection"); + if (trustStoreLocationProp == null && trustStorePasswordProp == null) { + LOG.warn("Truststore not specified for client connection"); + } else { + if (trustStoreLocationProp == null) { + throw new SSLContextException("Truststore location not specified for client connection"); + } + if (trustStorePasswordProp == null) { + throw new SSLContextException("Truststore password not specified for client connection"); + } + try { + trustManagers = new TrustManager[]{ + createTrustManager(trustStoreLocationProp, trustStorePasswordProp)}; + } catch (TrustManagerException e) { + throw new SSLContextException("Failed to create TrustManager", e); + } } + + SSLContext sslContext = null; try { - trustManagers = new TrustManager[]{ - createTrustManager(trustStoreLocationProp, trustStorePasswordProp)}; - } catch (TrustManagerException e) { - throw new SSLContextException("Failed to create TrustManager", e); + sslContext = SSLContext.getInstance("TLSv1"); + sslContext.init(keyManagers, trustManagers, null); + } catch (Exception e) { + throw new SSLContextException(e); } + return sslContext; } - - SSLContext sslContext = null; - try { - sslContext = SSLContext.getInstance("TLSv1"); - sslContext.init(keyManagers, trustManagers, null); - } catch (Exception e) { - throw new SSLContextException(e); - } - return sslContext; } public static X509KeyManager createKeyManager(String keyStoreLocation, String keyStorePassword) diff --git a/src/java/main/org/apache/zookeeper/common/ZKClientSSLContext.java b/src/java/main/org/apache/zookeeper/common/ZKClientSSLContext.java new file mode 100644 index 00000000000..6ca5c5491ae --- /dev/null +++ b/src/java/main/org/apache/zookeeper/common/ZKClientSSLContext.java @@ -0,0 +1,18 @@ +package org.apache.zookeeper.common; + +import javax.net.ssl.SSLContext; + +/** + * An interface for providing a custom {@link SSLContext} object to {@link X509Util} using {@link ZKConfig#SSL_CLIENT_CONTEXT} + */ +public interface ZKClientSSLContext { + + /** + * Returns an {@link SSLContext} for use within the {@link X509Util} + * + * @return {@link SSLContext} for use within {@link X509Util} + * @throws X509Exception.SSLContextException if {@link SSLContext} cannot be created + */ + SSLContext getSSLContext() throws X509Exception.SSLContextException; + +} diff --git a/src/java/main/org/apache/zookeeper/common/ZKConfig.java b/src/java/main/org/apache/zookeeper/common/ZKConfig.java index 8d9c001328d..4abe4410e45 100644 --- a/src/java/main/org/apache/zookeeper/common/ZKConfig.java +++ b/src/java/main/org/apache/zookeeper/common/ZKConfig.java @@ -50,6 +50,7 @@ public class ZKConfig { public static final String SSL_TRUSTSTORE_LOCATION = X509Util.SSL_TRUSTSTORE_LOCATION; @SuppressWarnings("deprecation") public static final String SSL_TRUSTSTORE_PASSWD = X509Util.SSL_TRUSTSTORE_PASSWD; + public static final String SSL_CLIENT_CONTEXT = "zookeeper.ssl.client.context"; @SuppressWarnings("deprecation") public static final String SSL_AUTHPROVIDER = X509Util.SSL_AUTHPROVIDER; public static final String JUTE_MAXBUFFER = "jute.maxbuffer"; diff --git a/src/java/test/org/apache/zookeeper/common/X509UtilTest.java b/src/java/test/org/apache/zookeeper/common/X509UtilTest.java new file mode 100644 index 00000000000..0d5ef7d5dd7 --- /dev/null +++ b/src/java/test/org/apache/zookeeper/common/X509UtilTest.java @@ -0,0 +1,50 @@ +/** + * 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.zookeeper.common; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Test; + +import javax.net.ssl.SSLContext; + +public class X509UtilTest { + + @Test + public void testCreateSSLContext_invalidCustomSSLContextClass() { + ZKConfig zkConfig = new ZKConfig(); + zkConfig.setProperty(ZKConfig.SSL_CLIENT_CONTEXT, String.class.getCanonicalName()); + try { + X509Util.createSSLContext(zkConfig); + fail("SSLContextException expected."); + } catch (X509Exception.SSLContextException e) { + assertTrue(e.getMessage().contains(ZKConfig.SSL_CLIENT_CONTEXT)); + } + } + + @Test + public void testCreateSSLContext_validCustomSSLContextClass() throws X509Exception.SSLContextException { + ZKConfig zkConfig = new ZKConfig(); + zkConfig.setProperty(ZKConfig.SSL_CLIENT_CONTEXT, ZKTestClientSSLContext.class.getCanonicalName()); + final SSLContext sslContext = X509Util.createSSLContext(zkConfig); + assertNull(sslContext); + } + +} \ No newline at end of file diff --git a/src/java/test/org/apache/zookeeper/common/ZKTestClientSSLContext.java b/src/java/test/org/apache/zookeeper/common/ZKTestClientSSLContext.java new file mode 100644 index 00000000000..5699ac2dd72 --- /dev/null +++ b/src/java/test/org/apache/zookeeper/common/ZKTestClientSSLContext.java @@ -0,0 +1,12 @@ +package org.apache.zookeeper.common; + +import javax.net.ssl.SSLContext; + +public class ZKTestClientSSLContext implements ZKClientSSLContext { + + @Override + public SSLContext getSSLContext() { + return null; + } + +} From e7746dff52464016d57fa976e7384669bde3efe4 Mon Sep 17 00:00:00 2001 From: Alex Rankin Date: Tue, 2 Oct 2018 17:46:37 +0100 Subject: [PATCH 2/4] Updating to use getConstructor().newInstance() instead of just newInstance(); --- src/java/main/org/apache/zookeeper/common/X509Util.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/java/main/org/apache/zookeeper/common/X509Util.java b/src/java/main/org/apache/zookeeper/common/X509Util.java index 41a324528ea..b58cd6e751f 100644 --- a/src/java/main/org/apache/zookeeper/common/X509Util.java +++ b/src/java/main/org/apache/zookeeper/common/X509Util.java @@ -28,6 +28,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.security.KeyStore; import org.slf4j.Logger; @@ -90,9 +91,10 @@ public static SSLContext createSSLContext(ZKConfig config) throws SSLContextExce String sslClientContextClass = config.getProperty(ZKConfig.SSL_CLIENT_CONTEXT); try { Class sslContextClass = Class.forName(sslClientContextClass); - ZKClientSSLContext sslContext = (ZKClientSSLContext) sslContextClass.newInstance(); + ZKClientSSLContext sslContext = (ZKClientSSLContext) sslContextClass.getConstructor().newInstance(); return sslContext.getSSLContext(); - } catch (ClassNotFoundException | ClassCastException | InstantiationException | IllegalAccessException e) { + } catch (ClassNotFoundException | ClassCastException | NoSuchMethodException | InvocationTargetException | + InstantiationException | IllegalAccessException e) { throw new SSLContextException("Could not retrieve the SSLContext from source '" + sslClientContextClass + "' provided in the property '" + ZKConfig.SSL_CLIENT_CONTEXT + "'", e); } From 92a58e16ab2dd7efe7fc78fe2ba152891004dcc0 Mon Sep 17 00:00:00 2001 From: Alex Rankin Date: Thu, 18 Oct 2018 14:29:07 +0100 Subject: [PATCH 3/4] Accidentally overwrote previous test cases --- .../apache/zookeeper/common/X509UtilTest.java | 244 +++++++++++++++++- 1 file changed, 241 insertions(+), 3 deletions(-) diff --git a/zookeeper-common/src/test/java/org/apache/zookeeper/common/X509UtilTest.java b/zookeeper-common/src/test/java/org/apache/zookeeper/common/X509UtilTest.java index 5f6826c157c..2b55d98249d 100644 --- a/zookeeper-common/src/test/java/org/apache/zookeeper/common/X509UtilTest.java +++ b/zookeeper-common/src/test/java/org/apache/zookeeper/common/X509UtilTest.java @@ -21,11 +21,250 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import org.apache.zookeeper.PortAssignment; +import org.apache.zookeeper.ZKTestCase; +import org.apache.zookeeper.client.ZKClientConfig; +import org.apache.zookeeper.server.ServerCnxnFactory; +import org.bouncycastle.asn1.x500.X500NameBuilder; +import org.bouncycastle.asn1.x500.style.BCStyle; +import org.bouncycastle.asn1.x509.BasicConstraints; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.KeyUsage; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLSocket; +import java.io.FileOutputStream; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Calendar; +import java.util.Date; +import java.util.Random; -public class X509UtilTest { +import static org.apache.zookeeper.test.ClientBase.createTmpDir; + +public class X509UtilTest extends ZKTestCase { + + private static final char[] PASSWORD = "password".toCharArray(); + private X509Certificate rootCertificate; + + private String truststorePath; + private String keystorePath; + private static KeyPair rootKeyPair; + + private X509Util x509Util; + private String[] customCipherSuites = new String[]{"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"}; + + @BeforeClass + public static void createKeyPair() throws Exception { + Security.addProvider(new BouncyCastleProvider()); + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME); + keyPairGenerator.initialize(4096); + rootKeyPair = keyPairGenerator.genKeyPair(); + } + + @AfterClass + public static void removeBouncyCastleProvider() throws Exception { + Security.removeProvider("BC"); + } + + @Before + public void setUp() throws Exception { + rootCertificate = createSelfSignedCertifcate(rootKeyPair); + + String tmpDir = createTmpDir().getAbsolutePath(); + truststorePath = tmpDir + "/truststore.jks"; + keystorePath = tmpDir + "/keystore.jks"; + + x509Util = new ClientX509Util(); + + writeKeystore(rootCertificate, rootKeyPair, keystorePath); + + System.setProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY, "org.apache.zookeeper.server.NettyServerCnxnFactory"); + System.setProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET, "org.apache.zookeeper.ClientCnxnSocketNetty"); + System.setProperty(x509Util.getSslKeystoreLocationProperty(), keystorePath); + System.setProperty(x509Util.getSslKeystorePasswdProperty(), new String(PASSWORD)); + System.setProperty(x509Util.getSslTruststoreLocationProperty(), truststorePath); + System.setProperty(x509Util.getSslTruststorePasswdProperty(), new String(PASSWORD)); + System.setProperty(x509Util.getSslHostnameVerificationEnabledProperty(), "false"); + + writeTrustStore(PASSWORD); + } + + private void writeKeystore(X509Certificate certificate, KeyPair keyPair, String path) throws Exception { + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(null, PASSWORD); + keyStore.setKeyEntry("alias", keyPair.getPrivate(), PASSWORD, new Certificate[] { certificate }); + FileOutputStream outputStream = new FileOutputStream(path); + keyStore.store(outputStream, PASSWORD); + outputStream.flush(); + outputStream.close(); + } + + private void writeTrustStore(char[] password) throws Exception { + KeyStore trustStore = KeyStore.getInstance("JKS"); + trustStore.load(null, password); + trustStore.setCertificateEntry(rootCertificate.getSubjectDN().toString(), rootCertificate); + FileOutputStream outputStream = new FileOutputStream(truststorePath); + if (password == null) { + trustStore.store(outputStream, new char[0]); + } else { + trustStore.store(outputStream, password); + } + outputStream.flush(); + outputStream.close(); + } + + private X509Certificate createSelfSignedCertifcate(KeyPair keyPair) throws Exception { + X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE); + nameBuilder.addRDN(BCStyle.CN, "localhost"); + Date notBefore = new Date(); + Calendar cal = Calendar.getInstance(); + cal.setTime(notBefore); + cal.add(Calendar.YEAR, 1); + Date notAfter = cal.getTime(); + BigInteger serialNumber = new BigInteger(128, new Random()); + + X509v3CertificateBuilder certificateBuilder = + new JcaX509v3CertificateBuilder(nameBuilder.build(), serialNumber, notBefore, notAfter, nameBuilder.build(), keyPair.getPublic()) + .addExtension(Extension.basicConstraints, true, new BasicConstraints(0)) + .addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign)); + + ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(keyPair.getPrivate()); + + return new JcaX509CertificateConverter().getCertificate(certificateBuilder.build(contentSigner)); + } + + @After + public void cleanUp() throws Exception { + System.clearProperty(x509Util.getSslKeystoreLocationProperty()); + System.clearProperty(x509Util.getSslKeystorePasswdProperty()); + System.clearProperty(x509Util.getSslTruststoreLocationProperty()); + System.clearProperty(x509Util.getSslTruststorePasswdProperty()); + System.clearProperty(x509Util.getSslHostnameVerificationEnabledProperty()); + System.clearProperty(x509Util.getSslOcspEnabledProperty()); + System.clearProperty(x509Util.getSslCrlEnabledProperty()); + System.clearProperty(x509Util.getCipherSuitesProperty()); + System.clearProperty("com.sun.net.ssl.checkRevocation"); + System.clearProperty("com.sun.security.enableCRLDP"); + Security.setProperty("com.sun.security.enableCRLDP", "false"); + } + + @Test(timeout = 5000) + public void testCreateSSLContextWithoutCustomProtocol() throws Exception { + SSLContext sslContext = x509Util.getDefaultSSLContext(); + Assert.assertEquals(X509Util.DEFAULT_PROTOCOL, sslContext.getProtocol()); + } + + @Test(timeout = 5000) + public void testCreateSSLContextWithCustomProtocol() throws Exception { + final String protocol = "TLSv1.1"; + System.setProperty(x509Util.getSslProtocolProperty(), protocol); + SSLContext sslContext = x509Util.getDefaultSSLContext(); + Assert.assertEquals(protocol, sslContext.getProtocol()); + } + + @Test(timeout = 5000) + public void testCreateSSLContextWithoutTrustStorePassword() throws Exception { + writeTrustStore(null); + System.clearProperty(x509Util.getSslTruststorePasswdProperty()); + x509Util.getDefaultSSLContext(); + } + + @Test(timeout = 5000, expected = X509Exception.SSLContextException.class) + public void testCreateSSLContextWithoutKeyStoreLocation() throws Exception { + System.clearProperty(x509Util.getSslKeystoreLocationProperty()); + x509Util.getDefaultSSLContext(); + } + + @Test(timeout = 5000, expected = X509Exception.SSLContextException.class) + public void testCreateSSLContextWithoutKeyStorePassword() throws Exception { + System.clearProperty(x509Util.getSslKeystorePasswdProperty()); + x509Util.getDefaultSSLContext(); + } + + @Test(timeout = 5000) + public void testCreateSSLContextWithCustomCipherSuites() throws Exception { + setCustomCipherSuites(); + SSLSocket sslSocket = x509Util.createSSLSocket(); + Assert.assertArrayEquals(customCipherSuites, sslSocket.getEnabledCipherSuites()); + } + + // It would be great to test the value of PKIXBuilderParameters#setRevocationEnabled but it does not appear to be + // possible + @Test(timeout = 5000) + public void testCRLEnabled() throws Exception { + System.setProperty(x509Util.getSslCrlEnabledProperty(), "true"); + x509Util.getDefaultSSLContext(); + Assert.assertTrue(Boolean.valueOf(System.getProperty("com.sun.net.ssl.checkRevocation"))); + Assert.assertTrue(Boolean.valueOf(System.getProperty("com.sun.security.enableCRLDP"))); + Assert.assertFalse(Boolean.valueOf(Security.getProperty("ocsp.enable"))); + } + + @Test(timeout = 5000) + public void testCRLDisabled() throws Exception { + x509Util.getDefaultSSLContext(); + Assert.assertFalse(Boolean.valueOf(System.getProperty("com.sun.net.ssl.checkRevocation"))); + Assert.assertFalse(Boolean.valueOf(System.getProperty("com.sun.security.enableCRLDP"))); + Assert.assertFalse(Boolean.valueOf(Security.getProperty("ocsp.enable"))); + } + + @Test(timeout = 5000) + public void testOCSPEnabled() throws Exception { + System.setProperty(x509Util.getSslOcspEnabledProperty(), "true"); + x509Util.getDefaultSSLContext(); + Assert.assertTrue(Boolean.valueOf(System.getProperty("com.sun.net.ssl.checkRevocation"))); + Assert.assertTrue(Boolean.valueOf(System.getProperty("com.sun.security.enableCRLDP"))); + Assert.assertTrue(Boolean.valueOf(Security.getProperty("ocsp.enable"))); + } + + @Test(timeout = 5000) + public void testCreateSSLSocket() throws Exception { + setCustomCipherSuites(); + SSLSocket sslSocket = x509Util.createSSLSocket(); + Assert.assertArrayEquals(customCipherSuites, sslSocket.getEnabledCipherSuites()); + } + + @Test(timeout = 5000) + public void testCreateSSLServerSocketWithoutPort() throws Exception { + setCustomCipherSuites(); + SSLServerSocket sslServerSocket = x509Util.createSSLServerSocket(); + Assert.assertArrayEquals(customCipherSuites, sslServerSocket.getEnabledCipherSuites()); + Assert.assertTrue(sslServerSocket.getNeedClientAuth()); + } + + @Test(timeout = 5000) + public void testCreateSSLServerSocketWithPort() throws Exception { + int port = PortAssignment.unique(); + setCustomCipherSuites(); + SSLServerSocket sslServerSocket = x509Util.createSSLServerSocket(port); + Assert.assertEquals(sslServerSocket.getLocalPort(), port); + Assert.assertArrayEquals(customCipherSuites, sslServerSocket.getEnabledCipherSuites()); + Assert.assertTrue(sslServerSocket.getNeedClientAuth()); + } + + // Warning: this will reset the x509Util + private void setCustomCipherSuites() { + System.setProperty(x509Util.getCipherSuitesProperty(), customCipherSuites[0] + "," + customCipherSuites[1]); + x509Util = new ClientX509Util(); + } @Test public void testCreateSSLContext_invalidCustomSSLContextClass() { @@ -48,5 +287,4 @@ public void testCreateSSLContext_validCustomSSLContextClass() throws X509Excepti final SSLContext sslContext = clientX509Util.createSSLContext(zkConfig); assertNull(sslContext); } - -} \ No newline at end of file +} From e46cc3ebe15600a9adf8e523053fd18e8084717a Mon Sep 17 00:00:00 2001 From: Alex Rankin Date: Thu, 15 Nov 2018 16:36:56 +0000 Subject: [PATCH 4/4] Adding Apache license header to new files. --- .../zookeeper/common/ZKClientSSLContext.java | 17 +++++++++++++++++ .../common/ZKTestClientSSLContext.java | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKClientSSLContext.java b/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKClientSSLContext.java index 755b9641fc4..55cb8a6ebeb 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKClientSSLContext.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKClientSSLContext.java @@ -1,3 +1,20 @@ +/** + * 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.zookeeper.common; import javax.net.ssl.SSLContext; diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/common/ZKTestClientSSLContext.java b/zookeeper-server/src/test/java/org/apache/zookeeper/common/ZKTestClientSSLContext.java index 5699ac2dd72..b7b66e54053 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/common/ZKTestClientSSLContext.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/common/ZKTestClientSSLContext.java @@ -1,3 +1,20 @@ +/** + * 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.zookeeper.common; import javax.net.ssl.SSLContext;