This is an automated email from the ASF dual-hosted git repository. mivanac pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push: new dddfce0 GEODE-7414_1: Define interface (#4505) dddfce0 is described below commit dddfce0a273a542744b6baab1d3ea535d11894c7 Author: Mario Ivanac <48509724+miva...@users.noreply.github.com> AuthorDate: Tue Jan 14 16:14:59 2020 +0100 GEODE-7414_1: Define interface (#4505) * GEODE-7414_1: Introduction of SSL Parameter Extension - Define interface - added config parameter - added SSLParameterExtension implementation --- .../integrationTest/resources/assembly_content.txt | 4 + ...SSLSocketParameterExtensionIntegrationTest.java | 242 +++++++++++++++++++++ .../geode/distributed/ConfigurationProperties.java | 16 ++ .../internal/AbstractDistributionConfig.java | 3 + .../distributed/internal/DistributionConfig.java | 30 +++ .../internal/DistributionConfigImpl.java | 20 +- .../org/apache/geode/internal/admin/SSLConfig.java | 42 +++- .../internal/net/SSLConfigurationFactory.java | 2 + .../apache/geode/internal/net/SocketCreator.java | 16 ++ .../apache/geode/net/SSLParameterExtension.java | 44 ++++ .../internal/DistributionConfigJUnitTest.java | 4 +- .../topics/gemfire_properties.html.md.erb | 7 + 12 files changed, 424 insertions(+), 6 deletions(-) diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt index 7fca5a5..1ea16d7 100644 --- a/geode-assembly/src/integrationTest/resources/assembly_content.txt +++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt @@ -887,6 +887,10 @@ javadoc/org/apache/geode/modules/util/TouchReplicatedRegionEntriesFunction.html javadoc/org/apache/geode/modules/util/package-frame.html javadoc/org/apache/geode/modules/util/package-summary.html javadoc/org/apache/geode/modules/util/package-tree.html +javadoc/org/apache/geode/net/SSLParameterExtension.html +javadoc/org/apache/geode/net/package-frame.html +javadoc/org/apache/geode/net/package-summary.html +javadoc/org/apache/geode/net/package-tree.html javadoc/org/apache/geode/package-frame.html javadoc/org/apache/geode/package-summary.html javadoc/org/apache/geode/package-tree.html diff --git a/geode-core/src/integrationTest/java/org/apache/geode/net/SSLSocketParameterExtensionIntegrationTest.java b/geode-core/src/integrationTest/java/org/apache/geode/net/SSLSocketParameterExtensionIntegrationTest.java new file mode 100644 index 0000000..18c67d4 --- /dev/null +++ b/geode-core/src/integrationTest/java/org/apache/geode/net/SSLSocketParameterExtensionIntegrationTest.java @@ -0,0 +1,242 @@ +/* + * 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.geode.net; + +import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_CIPHERS; +import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_ENABLED; +import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_PROTOCOLS; +import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_REQUIRE_AUTHENTICATION; +import static org.apache.geode.distributed.ConfigurationProperties.DISTRIBUTED_SYSTEM_ID; +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT; +import static org.apache.geode.distributed.ConfigurationProperties.SSL_PARAMETER_EXTENSION; +import static org.apache.geode.internal.security.SecurableCommunicationChannel.CLUSTER; +import static org.apache.geode.test.awaitility.GeodeAwaitility.await; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNull; + +import java.io.File; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicReference; + +import javax.net.ssl.SNIHostName; +import javax.net.ssl.SNIServerName; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; + +import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.RestoreSystemProperties; +import org.junit.experimental.categories.Category; +import org.junit.rules.ErrorCollector; +import org.junit.rules.TemporaryFolder; +import org.junit.rules.TestName; + +import org.apache.geode.cache.CacheFactory; +import org.apache.geode.distributed.internal.DistributionConfig; +import org.apache.geode.distributed.internal.DistributionConfigImpl; +import org.apache.geode.internal.cache.InternalCache; +import org.apache.geode.internal.net.SocketCreator; +import org.apache.geode.internal.net.SocketCreatorFactory; +import org.apache.geode.test.dunit.IgnoredException; +import org.apache.geode.test.junit.categories.MembershipTest; + +@Category({MembershipTest.class}) +public class SSLSocketParameterExtensionIntegrationTest { + + private static final String MESSAGE = + SSLSocketParameterExtensionIntegrationTest.class.getName() + " Message"; + + private AtomicReference<String> messageFromClient = new AtomicReference<>(); + + private DistributionConfig distributionConfig; + private SocketCreator socketCreator; + private InetAddress localHost; + private Thread serverThread; + private ServerSocket serverSocket; + private Socket clientSocket; + private InternalCache cache; + + @Rule + public ErrorCollector errorCollector = new ErrorCollector(); + + @Rule + public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties(); + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Rule + public TestName testName = new TestName(); + + + private Throwable serverException; + + @Before + public void setUp() throws Exception { + IgnoredException.addIgnoredException("javax.net.ssl.SSLException: Read timed out"); + + File keystore = findTestKeystore(); + System.setProperty("javax.net.ssl.trustStore", keystore.getCanonicalPath()); + System.setProperty("javax.net.ssl.trustStorePassword", "password"); + System.setProperty("javax.net.ssl.keyStore", keystore.getCanonicalPath()); + System.setProperty("javax.net.ssl.keyStorePassword", "password"); + + Properties properties = new Properties(); + properties.setProperty(MCAST_PORT, "0"); + properties.setProperty(CLUSTER_SSL_ENABLED, "true"); + properties.setProperty(CLUSTER_SSL_REQUIRE_AUTHENTICATION, "true"); + properties.setProperty(CLUSTER_SSL_CIPHERS, "any"); + properties.setProperty(CLUSTER_SSL_PROTOCOLS, "TLSv1.2"); + properties.setProperty(SSL_PARAMETER_EXTENSION, MySSLParameterExtension.class.getName()); + properties.setProperty(DISTRIBUTED_SYSTEM_ID, "11"); + + cache = (InternalCache) new CacheFactory(properties).create(); + + this.distributionConfig = new DistributionConfigImpl(properties); + + SocketCreatorFactory.setDistributionConfig(this.distributionConfig); + this.socketCreator = SocketCreatorFactory.getSocketCreatorForComponent(CLUSTER); + + this.localHost = InetAddress.getLocalHost(); + } + + @After + public void tearDown() throws Exception { + if (this.clientSocket != null) { + this.clientSocket.close(); + } + if (this.serverSocket != null) { + this.serverSocket.close(); + } + if (this.serverThread != null && this.serverThread.isAlive()) { + this.serverThread.interrupt(); + } + SocketCreatorFactory.close(); + cache.close(); + } + + @Test + public void securedSocketCheckExtensions() throws Exception { + this.serverSocket = this.socketCreator.createServerSocket(0, 0, this.localHost); + this.serverThread = startServer(this.serverSocket, 15000); + + int serverPort = this.serverSocket.getLocalPort(); + this.clientSocket = this.socketCreator.connectForServer(this.localHost, serverPort); + + SSLSocket sslSocket = (SSLSocket) this.clientSocket; + + List<SNIServerName> serverNames = new ArrayList<>(1); + SNIHostName serverName = new SNIHostName("11"); + serverNames.add(serverName); + + assertThat(sslSocket.getSSLParameters().getServerNames()).isEqualTo(serverNames); + + // transmit expected string from Client to Server + ObjectOutputStream output = new ObjectOutputStream(this.clientSocket.getOutputStream()); + output.writeObject(MESSAGE); + output.flush(); + + // this is the real assertion of this test + await().until(() -> { + return !serverThread.isAlive(); + }); + assertNull(serverException); + assertThat(this.messageFromClient.get()).isEqualTo(MESSAGE); + } + + private File findTestKeystore() throws IOException { + return copyKeystoreResourceToFile("/ssl/trusted.keystore"); + } + + public File copyKeystoreResourceToFile(final String name) throws IOException { + URL resource = getClass().getResource(name); + assertThat(resource).isNotNull(); + + File file = this.temporaryFolder.newFile(name.replaceFirst(".*/", "")); + FileUtils.copyURLToFile(resource, file); + return file; + } + + private Thread startServer(final ServerSocket serverSocket, int timeoutMillis) throws Exception { + Thread serverThread = new Thread(new MyThreadGroup(this.testName.getMethodName()), () -> { + try { + Socket socket = serverSocket.accept(); + SocketCreatorFactory.getSocketCreatorForComponent(CLUSTER).handshakeIfSocketIsSSL(socket, + timeoutMillis); + assertThat(socket.getSoTimeout()).isEqualTo(0); + + ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); + messageFromClient.set((String) ois.readObject()); + } catch (Throwable throwable) { + serverException = throwable; + } + }, this.testName.getMethodName() + "-server"); + + serverThread.start(); + return serverThread; + } + + private class MyThreadGroup extends ThreadGroup { + + public MyThreadGroup(final String name) { + super(name); + } + + @Override + public void uncaughtException(final Thread thread, final Throwable throwable) { + errorCollector.addError(throwable); + } + } + + public static class MySSLParameterExtension implements SSLParameterExtension { + DistributionConfig config; + + @Override + public void init(DistributionConfig config) { + this.config = config; + } + + @Override + public SSLParameters modifySSLClientSocketParameters(SSLParameters parameters) { + List<SNIServerName> serverNames = new ArrayList<>(1); + SNIHostName serverName = new SNIHostName(String.valueOf(config.getDistributedSystemId())); + serverNames.add(serverName); + parameters.setServerNames(serverNames); + return parameters; + } + + @Override + public SSLParameters modifySSLServerSocketParameters(SSLParameters parameters) { + List<SNIServerName> serverNames = new ArrayList<>(1); + SNIHostName serverName = new SNIHostName("server"); + serverNames.add(serverName); + parameters.setServerNames(serverNames); + return parameters; + } + + } +} diff --git a/geode-core/src/main/java/org/apache/geode/distributed/ConfigurationProperties.java b/geode-core/src/main/java/org/apache/geode/distributed/ConfigurationProperties.java index d06b962..f07988f 100644 --- a/geode-core/src/main/java/org/apache/geode/distributed/ConfigurationProperties.java +++ b/geode-core/src/main/java/org/apache/geode/distributed/ConfigurationProperties.java @@ -2155,6 +2155,22 @@ public interface ConfigurationProperties { * <U>Since</U>: Geode 1.0 */ String SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION = "ssl-web-require-authentication"; + + /** + * The static String definition of the <i>"ssl-parameter-extension"</i> property + * + * <U>Description</U>SSLParameterExtension module name for Clients that want to use SSL Parameter + * extensions. + * Module must implement SSLParameterExtension interface. + * </p> + * <U>Default</U>: "" + * </p> + * <U>Since</U>: Geode 1.12 + * </p> + * <U>Allowed values</U>: class name + */ + String SSL_PARAMETER_EXTENSION = "ssl-parameter-extension"; + /** * The static String definition of the <i>"validate-serializable-objects"</i> property * diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java index c21d330..f88e14d 100644 --- a/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java +++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java @@ -158,6 +158,7 @@ import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE; import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_PASSWORD; import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_TYPE; import static org.apache.geode.distributed.ConfigurationProperties.SSL_LOCATOR_ALIAS; +import static org.apache.geode.distributed.ConfigurationProperties.SSL_PARAMETER_EXTENSION; import static org.apache.geode.distributed.ConfigurationProperties.SSL_PROTOCOLS; import static org.apache.geode.distributed.ConfigurationProperties.SSL_REQUIRE_AUTHENTICATION; import static org.apache.geode.distributed.ConfigurationProperties.SSL_SERVER_ALIAS; @@ -1474,6 +1475,8 @@ public abstract class AbstractDistributionConfig extends AbstractConfig m.put(SSL_DEFAULT_ALIAS, "The default certificate alias to be used in a multi-key keystore"); m.put(SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION, "This property determines is the HTTP service with use mutual ssl authentication."); + m.put(SSL_PARAMETER_EXTENSION, + "User defined fully qualified class name implementing SSLParameterExtension interface for SSL parameter extensions. Defaults to \"{0}\". Legal values can be any \"class name\" implementing SSLParameterExtension that is present in the classpath."); m.put(VALIDATE_SERIALIZABLE_OBJECTS, "If true checks incoming java serializable objects against a filter"); m.put(SERIALIZABLE_OBJECT_FILTER, "The filter to check incoming java serializables against"); diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfig.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfig.java index d91bd6c..89a19a6 100644 --- a/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfig.java +++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfig.java @@ -158,6 +158,7 @@ import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE; import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_PASSWORD; import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_TYPE; import static org.apache.geode.distributed.ConfigurationProperties.SSL_LOCATOR_ALIAS; +import static org.apache.geode.distributed.ConfigurationProperties.SSL_PARAMETER_EXTENSION; import static org.apache.geode.distributed.ConfigurationProperties.SSL_PROTOCOLS; import static org.apache.geode.distributed.ConfigurationProperties.SSL_REQUIRE_AUTHENTICATION; import static org.apache.geode.distributed.ConfigurationProperties.SSL_SERVER_ALIAS; @@ -5257,6 +5258,35 @@ public interface DistributionConfig extends Config, LogConfig, StatisticsConfig */ boolean DEFAULT_SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION = false; + + /** + * Returns user defined class name SSL Parameter Extension in + * {@link ConfigurationProperties#SSL_PARAMETER_EXTENSION} + */ + @ConfigAttributeGetter(name = SSL_PARAMETER_EXTENSION) + String getSSLParameterExtension(); + + /** + * Sets the user defined class name in {@link ConfigurationProperties#SSL_PARAMETER_EXTENSION} + * property. + */ + @ConfigAttributeSetter(name = SSL_PARAMETER_EXTENSION) + void setSSLParameterExtension(String attValue); + + /** + * The name of class for {@link ConfigurationProperties#SSL_PARAMETER_EXTENSION} property + */ + @ConfigAttribute(type = String.class) + String SSL_PARAMETER_EXTENSION_NAME = SSL_PARAMETER_EXTENSION; + + /** + * The default {@link ConfigurationProperties#SSL_PARAMETER_EXTENSION} class name. + * <p> + * Actual value of this is fully qualified <code>"class name"</code>. + */ + String DEFAULT_SSL_PARAMETER_EXTENSION = ""; + + /** * Returns the value of the {@link ConfigurationProperties#VALIDATE_SERIALIZABLE_OBJECTS} property */ diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfigImpl.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfigImpl.java index 55d79b2..8a599ba 100644 --- a/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfigImpl.java +++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributionConfigImpl.java @@ -628,6 +628,11 @@ public class DistributionConfigImpl extends AbstractDistributionConfig implement private String sslDefaultAlias = DEFAULT_SSL_ALIAS; + /** + * The SSL Parameter Extension class name + */ + private String sslParameterExtension = DEFAULT_SSL_PARAMETER_EXTENSION; + private Map<String, ConfigSource> sourceMap = Collections.synchronizedMap(new HashMap<>()); @@ -867,6 +872,7 @@ public class DistributionConfigImpl extends AbstractDistributionConfig implement this.sslProperties = other.getSSLProperties(); this.sslDefaultAlias = other.getSSLDefaultAlias(); this.sslWebServiceRequireAuthentication = other.getSSLWebRequireAuthentication(); + this.sslParameterExtension = other.getSSLParameterExtension(); validateSerializableObjects = other.getValidateSerializableObjects(); serializableObjectFilter = other.getSerializableObjectFilter(); @@ -3112,6 +3118,16 @@ public class DistributionConfigImpl extends AbstractDistributionConfig implement } @Override + public String getSSLParameterExtension() { + return sslParameterExtension; + } + + @Override + public void setSSLParameterExtension(final String extension) { + sslParameterExtension = extension; + } + + @Override public boolean getValidateSerializableObjects() { return validateSerializableObjects; } @@ -3288,6 +3304,7 @@ public class DistributionConfigImpl extends AbstractDistributionConfig implement .append(sslKeyStorePassword, that.sslKeyStorePassword) .append(sslTrustStore, that.sslTrustStore) .append(sslTrustStorePassword, that.sslTrustStorePassword) + .append(sslParameterExtension, that.sslParameterExtension) .append(locatorSSLAlias, that.locatorSSLAlias).append(sslDefaultAlias, that.sslDefaultAlias) .append(sourceMap, that.sourceMap).append(userCommandPackages, that.userCommandPackages) .append(offHeapMemorySize, that.offHeapMemorySize).append(shiroInit, that.shiroInit) @@ -3360,7 +3377,8 @@ public class DistributionConfigImpl extends AbstractDistributionConfig implement .append(httpServiceSSLAlias).append(securableCommunicationChannels).append(sslProtocols) .append(sslCiphers).append(sslRequireAuthentication).append(sslKeyStore) .append(sslKeyStoreType).append(sslKeyStorePassword).append(sslTrustStore) - .append(sslTrustStorePassword).append(sslWebServiceRequireAuthentication) + .append(sslTrustStorePassword).append(sslParameterExtension) + .append(sslWebServiceRequireAuthentication) .append(locatorSSLAlias).append(sslDefaultAlias).append(sourceMap) .append(userCommandPackages).append(offHeapMemorySize).append(lockMemory).append(shiroInit) .append(modifiable).append(threadMonitorEnabled).append(threadMonitorInterval) diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/SSLConfig.java b/geode-core/src/main/java/org/apache/geode/internal/admin/SSLConfig.java index 79b0283..b1e3f07 100755 --- a/geode-core/src/main/java/org/apache/geode/internal/admin/SSLConfig.java +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/SSLConfig.java @@ -23,10 +23,15 @@ import java.security.KeyStore; import java.util.Iterator; import java.util.Properties; +import org.apache.commons.lang3.StringUtils; + import org.apache.geode.annotations.Immutable; import org.apache.geode.distributed.internal.DistributionConfig; +import org.apache.geode.distributed.internal.InternalDistributedSystem; +import org.apache.geode.internal.security.CallbackInstantiator; import org.apache.geode.internal.security.SecurableCommunicationChannel; import org.apache.geode.management.internal.SSLUtil; +import org.apache.geode.net.SSLParameterExtension; /** * The SSL configuration settings for a GemFire distributed system. @@ -60,6 +65,9 @@ public class SSLConfig { @Immutable private final Properties properties; + @Immutable + private final SSLParameterExtension sslParameterExtension; + private SSLConfig(boolean endpointIdentification, boolean useDefaultSSLContext, boolean enabled, @@ -74,7 +82,8 @@ public class SSLConfig { String truststoreType, String alias, SecurableCommunicationChannel securableCommunicationChannel, - Properties properties) { + Properties properties, + SSLParameterExtension sslParameterExtension) { this.endpointIdentification = endpointIdentification; this.useDefaultSSLContext = useDefaultSSLContext; this.enabled = enabled; @@ -90,6 +99,7 @@ public class SSLConfig { this.alias = alias; this.securableCommunicationChannel = securableCommunicationChannel; this.properties = properties; + this.sslParameterExtension = sslParameterExtension; } public String getAlias() { @@ -160,6 +170,10 @@ public class SSLConfig { return securableCommunicationChannel; } + public SSLParameterExtension getSSLParameterExtension() { + return sslParameterExtension; + } + @Override public String toString() { return "SSLConfig{" + "enabled=" + enabled + ", protocols='" + protocols + '\'' + ", ciphers='" @@ -168,7 +182,8 @@ public class SSLConfig { + '\'' + ", truststore='" + truststore + '\'' + ", truststorePassword='" + truststorePassword + '\'' + ", truststoreType='" + truststoreType + '\'' + ", alias='" + alias + '\'' + ", securableCommunicationChannel=" + securableCommunicationChannel - + ", properties=" + properties + '}'; + + ", properties=" + properties + '\'' + ", sslParameterExtension=" + sslParameterExtension + + '}'; } /** @@ -217,6 +232,7 @@ public class SSLConfig { private String alias = null; private SecurableCommunicationChannel securableCommunicationChannel = null; private Properties properties = new Properties(); + private SSLParameterExtension sslParameterExtension = null; public Builder() {} @@ -224,7 +240,7 @@ public class SSLConfig { return new SSLConfig(endpointIdentification, useDefaultSSLContext, enabled, protocols, ciphers, requireAuth, keystore, keystoreType, keystorePassword, truststore, truststorePassword, truststoreType, alias, securableCommunicationChannel, - properties); + properties, sslParameterExtension); } public Builder setAlias(final String alias) { @@ -307,6 +323,26 @@ public class SSLConfig { return this; } + public Builder setSSLParameterExtension( + final String sslParameterExtensionConfig) { + if (StringUtils.isBlank(sslParameterExtensionConfig)) { + this.sslParameterExtension = null; + return this; + } + SSLParameterExtension sslParameterExtension = + CallbackInstantiator.getObjectOfTypeFromClassName(sslParameterExtensionConfig, + SSLParameterExtension.class); + InternalDistributedSystem ids = InternalDistributedSystem.getAnyInstance(); + + if (ids == null) { + this.sslParameterExtension = null; + return this; + } + sslParameterExtension.init(ids.getConfig()); + this.sslParameterExtension = sslParameterExtension; + return this; + } + public String getKeystore() { return keystore; } diff --git a/geode-core/src/main/java/org/apache/geode/internal/net/SSLConfigurationFactory.java b/geode-core/src/main/java/org/apache/geode/internal/net/SSLConfigurationFactory.java index b6c12c0..259d578 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/net/SSLConfigurationFactory.java +++ b/geode-core/src/main/java/org/apache/geode/internal/net/SSLConfigurationFactory.java @@ -58,6 +58,7 @@ public class SSLConfigurationFactory { configureLegacyClusterSSL(distributionConfig, sslConfigBuilder); } sslConfigBuilder.setSecurableCommunicationChannel(sslEnabledComponent); + switch (sslEnabledComponent) { case ALL: { break; @@ -140,6 +141,7 @@ public class SSLConfigurationFactory { sslConfigBuilder.setRequireAuth(distributionConfig.getSSLRequireAuthentication()); sslConfigBuilder.setAlias(distributionConfig.getSSLDefaultAlias()); sslConfigBuilder.setUseDefaultSSLContext(distributionConfig.getSSLUseDefaultContext()); + sslConfigBuilder.setSSLParameterExtension(distributionConfig.getSSLParameterExtension()); return sslConfigBuilder; } diff --git a/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java b/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java index 807315c..439de6a 100755 --- a/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java +++ b/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java @@ -84,8 +84,10 @@ import org.apache.geode.internal.util.ArgumentRedactor; import org.apache.geode.internal.util.PasswordUtil; import org.apache.geode.logging.internal.log4j.api.LogService; import org.apache.geode.management.internal.SSLUtil; +import org.apache.geode.net.SSLParameterExtension; import org.apache.geode.util.internal.GeodeGlossary; + /** * Analyze configuration data (gemfire.properties) and configure sockets accordingly for SSL. * <p> @@ -967,6 +969,14 @@ public class SocketCreator { if (!"any".equalsIgnoreCase(ciphers[0])) { serverSocket.setEnabledCipherSuites(ciphers); } + + SSLParameterExtension sslParameterExtension = this.sslConfig.getSSLParameterExtension(); + if (sslParameterExtension != null) { + SSLParameters modifiedParams = + sslParameterExtension.modifySSLServerSocketParameters(serverSocket.getSSLParameters()); + serverSocket.setSSLParameters(modifiedParams); + } + } /** @@ -982,6 +992,12 @@ public class SocketCreator { SSLParameters modifiedParams = checkAndEnableHostnameValidation(sslSocket.getSSLParameters()); + + SSLParameterExtension sslParameterExtension = this.sslConfig.getSSLParameterExtension(); + if (sslParameterExtension != null) { + modifiedParams = + sslParameterExtension.modifySSLClientSocketParameters(modifiedParams); + } sslSocket.setSSLParameters(modifiedParams); String[] protocols = this.sslConfig.getProtocolsAsStringArray(); diff --git a/geode-core/src/main/java/org/apache/geode/net/SSLParameterExtension.java b/geode-core/src/main/java/org/apache/geode/net/SSLParameterExtension.java new file mode 100644 index 0000000..0ed4465 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/net/SSLParameterExtension.java @@ -0,0 +1,44 @@ +/* + * 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.geode.net; + +import javax.net.ssl.SSLParameters; + +import org.apache.geode.distributed.internal.DistributionConfig; + +/** + * User implementation of a SSLParameter extension logic. + * + * @since Geode 1.12 + */ + +public interface SSLParameterExtension { + /** + * Initialize the SSLParameterExtension. + * + * @param config the DistributionConfig + */ + default void init(DistributionConfig config) {} + + default SSLParameters modifySSLClientSocketParameters(SSLParameters parameters) { + return parameters; + } + + default SSLParameters modifySSLServerSocketParameters(SSLParameters parameters) { + return parameters; + } + +} diff --git a/geode-core/src/test/java/org/apache/geode/distributed/internal/DistributionConfigJUnitTest.java b/geode-core/src/test/java/org/apache/geode/distributed/internal/DistributionConfigJUnitTest.java index fd53247..64d0022 100644 --- a/geode-core/src/test/java/org/apache/geode/distributed/internal/DistributionConfigJUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/distributed/internal/DistributionConfigJUnitTest.java @@ -103,7 +103,7 @@ public class DistributionConfigJUnitTest { @Test public void testGetAttributeNames() { String[] attNames = AbstractDistributionConfig._getAttNames(); - assertThat(attNames.length).isEqualTo(167); + assertThat(attNames.length).isEqualTo(168); List boolList = new ArrayList(); List intList = new ArrayList(); @@ -139,7 +139,7 @@ public class DistributionConfigJUnitTest { // are. assertEquals(35, boolList.size()); assertEquals(35, intList.size()); - assertEquals(87, stringList.size()); + assertEquals(88, stringList.size()); assertEquals(5, fileList.size()); assertEquals(5, otherList.size()); } diff --git a/geode-docs/reference/topics/gemfire_properties.html.md.erb b/geode-docs/reference/topics/gemfire_properties.html.md.erb index afbfdea..8a23f6b 100644 --- a/geode-docs/reference/topics/gemfire_properties.html.md.erb +++ b/geode-docs/reference/topics/gemfire_properties.html.md.erb @@ -679,6 +679,13 @@ When enabled, also sets ssl-endpoint-identification-enabled to true.</td> </tr> <tr> +<td>ssl-parameter-extension</td> +<td>Specifies the implementation of the <code>SSLParameterExtension</code> interface that implements the SSL parameter extensions.</td> +<td>S, L</td> +<td><em>not set</em></td> +</tr> + +<tr> <td>ssl-protocols</td> <td>Comma-separated list of SSL protocols or "any"</td> <td>S, L</td>