GEODE-8800: Slower receiver is not allowed with cluster TLS/SSL (#5879)


    Co-authored-by: Xiaojian Zhou <zhouxh@vmware.com>
    Co-authored-by: Bill Burcham <bill.burcham@gmail.com>
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/internal/SSLConfigJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/internal/SSLConfigJUnitTest.java
index 2a3ded9..1a1b7a3 100755
--- a/geode-core/src/integrationTest/java/org/apache/geode/internal/SSLConfigJUnitTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/internal/SSLConfigJUnitTest.java
@@ -14,6 +14,7 @@
  */
 package org.apache.geode.internal;
 
+import static org.apache.geode.distributed.ConfigurationProperties.ASYNC_DISTRIBUTION_TIMEOUT;
 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_KEYSTORE;
@@ -51,9 +52,11 @@
 import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_REQUIRE_AUTHENTICATION;
 import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_TRUSTSTORE;
 import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_TRUSTSTORE_PASSWORD;
+import static org.apache.geode.distributed.ConfigurationProperties.SSL_ENABLED_COMPONENTS;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_ENDPOINT_IDENTIFICATION_ENABLED;
 import static org.apache.geode.internal.security.SecurableCommunicationChannel.ALL;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
@@ -154,6 +157,48 @@
   public void tearDownTest() {}
 
   @Test
+  public void slowReceiverShouldThrowExceptionWhenEnabledClusterTLS() throws Exception {
+    Properties props = new Properties();
+    props.setProperty(SSL_ENABLED_COMPONENTS, "cluster");
+    props.setProperty(ASYNC_DISTRIBUTION_TIMEOUT, "1");
+
+    Throwable thrown = catchThrowable(() -> new DistributionConfigImpl(props));
+    assertThat(thrown).isInstanceOf(IllegalArgumentException.class).hasMessageContaining(
+        "async-distribution-timeout greater than 0 is not allowed with cluster TLS/SSL.");
+  }
+
+  @Test
+  public void slowReceiverShouldThrowExceptionWhenEnabledAllTLS() throws Exception {
+    Properties props = new Properties();
+    props.setProperty(SSL_ENABLED_COMPONENTS, "all");
+    props.setProperty(ASYNC_DISTRIBUTION_TIMEOUT, "1");
+
+    Throwable thrown = catchThrowable(() -> new DistributionConfigImpl(props));
+    assertThat(thrown).isInstanceOf(IllegalArgumentException.class).hasMessageContaining(
+        "async-distribution-timeout greater than 0 is not allowed with cluster TLS/SSL.");
+  }
+
+  @Test
+  public void slowReceiverShouldNotThrowExceptionWhenEnabledLocatorTLS() throws Exception {
+    Properties props = new Properties();
+    props.setProperty(SSL_ENABLED_COMPONENTS, "locator");
+    props.setProperty(ASYNC_DISTRIBUTION_TIMEOUT, "1");
+
+    new DistributionConfigImpl(props);
+  }
+
+  @Test
+  public void slowReceiverShouldThrowExceptionWhenLegacyClusterTLS() throws Exception {
+    Properties props = new Properties();
+    props.setProperty(CLUSTER_SSL_ENABLED, "true");
+    props.setProperty(ASYNC_DISTRIBUTION_TIMEOUT, "1");
+
+    Throwable thrown = catchThrowable(() -> new DistributionConfigImpl(props));
+    assertThat(thrown).isInstanceOf(IllegalArgumentException.class).hasMessageContaining(
+        "async-distribution-timeout greater than 0 is not allowed with cluster TLS/SSL.");
+  }
+
+  @Test
   public void testMCastPortWithClusterSSL() throws Exception {
     Properties props = new Properties();
     // default mcast-port is not 0.
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 1b01dee..35ac545 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
@@ -63,6 +63,8 @@
 import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_TRUSTSTORE;
 import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_TRUSTSTORE_PASSWORD;
 import static org.apache.geode.distributed.ConfigurationProperties.SSL_ENABLED_COMPONENTS;
+import static org.apache.geode.internal.security.SecurableCommunicationChannel.ALL;
+import static org.apache.geode.internal.security.SecurableCommunicationChannel.CLUSTER;
 
 import java.io.File;
 import java.io.IOException;
@@ -1030,6 +1032,20 @@
     modifiable = false;
   }
 
+  /*
+   * When ssl-enabled-components specified CLUSTER or ALL, the slower receiver is not allowed.
+   * In legacy code, if cluster-ssl-enabled is true, the slower receiver is not allowed.
+   */
+  void validateSlowReceiversIncompatibleWithSSL(
+      SecurableCommunicationChannel[] sslEnabledComponents) {
+    if (getAsyncDistributionTimeout() > 0
+        && (getClusterSSLEnabled() || Arrays.stream(sslEnabledComponents)
+            .anyMatch(component -> component == ALL || component == CLUSTER))) {
+      throw new IllegalArgumentException(
+          "async-distribution-timeout greater than 0 is not allowed with cluster TLS/SSL.");
+    }
+  }
+
   private void validateSSLEnabledComponentsConfiguration() {
     Object value = null;
     try {
@@ -1049,6 +1065,9 @@
       }
     }
     SecurableCommunicationChannel[] sslEnabledComponents = (SecurableCommunicationChannel[]) value;
+
+    validateSlowReceiversIncompatibleWithSSL(sslEnabledComponents);
+
     for (SecurableCommunicationChannel securableCommunicationChannel : sslEnabledComponents) {
       if (!isAliasCorrectlyConfiguredForComponents(securableCommunicationChannel)) {
         throw new IllegalArgumentException(
@@ -1072,7 +1091,7 @@
         if (StringUtils.isEmpty(getSSLDefaultAlias())) {
           boolean correctAlias = true;
           correctAlias &=
-              isAliasCorrectlyConfiguredForComponents(SecurableCommunicationChannel.CLUSTER);
+              isAliasCorrectlyConfiguredForComponents(CLUSTER);
           correctAlias &=
               isAliasCorrectlyConfiguredForComponents(SecurableCommunicationChannel.GATEWAY);
           correctAlias &=