You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by ap...@apache.org on 2022/01/28 00:31:30 UTC

[pinot] branch listener-tls-customization created (now 3633704)

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

apucher pushed a change to branch listener-tls-customization
in repository https://gitbox.apache.org/repos/asf/pinot.git.


      at 3633704  controller working

This branch includes the following new commits:

     new 7a18a16  prototype
     new 3633704  controller working

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org


[pinot] 01/02: prototype

Posted by ap...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

apucher pushed a commit to branch listener-tls-customization
in repository https://gitbox.apache.org/repos/asf/pinot.git

commit 7a18a16e9fe160130f9a72864dbb7938963e0d4f
Author: Alexander Pucher <ap...@apache.org>
AuthorDate: Thu Jan 27 15:32:11 2022 -0800

    prototype
---
 .../org/apache/pinot/core/transport/TlsConfig.java |  23 +-
 .../apache/pinot/core/util/ListenerConfigUtil.java |  59 +++-
 .../java/org/apache/pinot/core/util/TlsUtils.java  |  77 +++--
 .../tests/BasicAuthTlsRealtimeIntegrationTest.java |  83 ++---
 .../integration/tests/TlsIntegrationTest.java      | 354 +++++++++++++++++++++
 .../CertBasedTlsChannelAccessControlFactory.java   |   3 +-
 .../src/test/resources/empty.jks                   | Bin 0 -> 32 bytes
 .../src/test/resources/empty.p12                   | Bin 0 -> 103 bytes
 .../src/test/resources/tlstest.jks                 | Bin 2277 -> 2283 bytes
 .../src/test/resources/tlstest.p12                 | Bin 10155 -> 2645 bytes
 10 files changed, 487 insertions(+), 112 deletions(-)

diff --git a/pinot-core/src/main/java/org/apache/pinot/core/transport/TlsConfig.java b/pinot-core/src/main/java/org/apache/pinot/core/transport/TlsConfig.java
index c8de43b..9b86c34 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/transport/TlsConfig.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/transport/TlsConfig.java
@@ -18,6 +18,8 @@
  */
 package org.apache.pinot.core.transport;
 
+import io.netty.handler.ssl.SslProvider;
+import java.security.KeyStore;
 import org.apache.commons.lang3.StringUtils;
 
 
@@ -26,13 +28,28 @@ import org.apache.commons.lang3.StringUtils;
  */
 public class TlsConfig {
   private boolean _clientAuthEnabled;
-  private String _keyStoreType;
+  private String _keyStoreType = KeyStore.getDefaultType();
   private String _keyStorePath;
   private String _keyStorePassword;
-  private String _trustStoreType;
+  private String _trustStoreType = KeyStore.getDefaultType();
   private String _trustStorePath;
   private String _trustStorePassword;
-  private String _sslProvider;
+  private String _sslProvider = SslProvider.JDK.toString();
+
+  public TlsConfig() {
+    // left blank
+  }
+
+  public TlsConfig(TlsConfig tlsConfig) {
+    _clientAuthEnabled = tlsConfig._clientAuthEnabled;
+    _keyStoreType = tlsConfig._keyStoreType;
+    _keyStorePath = tlsConfig._keyStorePath;
+    _keyStorePassword = tlsConfig._keyStorePassword;
+    _trustStoreType = tlsConfig._trustStoreType;
+    _trustStorePath = tlsConfig._trustStorePath;
+    _trustStorePassword = tlsConfig._trustStorePassword;
+    _sslProvider = tlsConfig._sslProvider;
+  }
 
   public boolean isClientAuthEnabled() {
     return _clientAuthEnabled;
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/util/ListenerConfigUtil.java b/pinot-core/src/main/java/org/apache/pinot/core/util/ListenerConfigUtil.java
index 0211c29..0fd1143 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/util/ListenerConfigUtil.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/util/ListenerConfigUtil.java
@@ -19,7 +19,14 @@
 package org.apache.pinot.core.util;
 
 import com.google.common.base.Preconditions;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.URI;
+import java.net.URL;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -28,6 +35,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.pinot.core.transport.ListenerConfig;
 import org.apache.pinot.core.transport.TlsConfig;
@@ -76,9 +84,7 @@ public final class ListenerConfigUtil {
 
     String[] protocols = config.getProperty(namespace + DOT_ACCESS_PROTOCOLS).split(",");
 
-    return Arrays.stream(protocols).peek(protocol -> Preconditions
-        .checkArgument(SUPPORTED_PROTOCOLS.contains(protocol), "Unsupported protocol '%s' in config namespace '%s'",
-            protocol, namespace)).map(protocol -> buildListenerConfig(config, namespace, protocol, tlsDefaults))
+    return Arrays.stream(protocols).map(protocol -> buildListenerConfig(config, namespace, protocol, tlsDefaults))
         .collect(Collectors.toList());
   }
 
@@ -167,24 +173,35 @@ public final class ListenerConfigUtil {
     return listeners;
   }
 
-  private static ListenerConfig buildListenerConfig(PinotConfiguration config, String namespace, String protocol,
+  private static ListenerConfig buildListenerConfig(PinotConfiguration config, String namespace, String name,
       TlsConfig tlsConfig) {
-    String protocolNamespace = namespace + DOT_ACCESS_PROTOCOLS + "." + protocol;
+    String protocolNamespace = namespace + DOT_ACCESS_PROTOCOLS + "." + name;
 
-    return new ListenerConfig(protocol, getHost(config.getProperty(protocolNamespace + ".host", DEFAULT_HOST)),
-        getPort(config.getProperty(protocolNamespace + ".port")), protocol, tlsConfig);
+    return new ListenerConfig(name, getHost(config.getProperty(protocolNamespace + ".host", DEFAULT_HOST)),
+        getPort(config.getProperty(protocolNamespace + ".port")), getProtocol(config.getProperty(protocolNamespace + ".protocol"), name),
+        TlsUtils.extractTlsConfig(config, namespace + ".tls", tlsConfig));
   }
 
   private static String getHost(String configuredHost) {
-    return Optional.ofNullable(configuredHost).filter(host -> !host.trim().isEmpty())
+    return Optional.ofNullable(configuredHost).map(String::trim).filter(host -> !host.isEmpty())
         .orElseThrow(() -> new IllegalArgumentException(configuredHost + " is not a valid host"));
   }
 
   private static int getPort(String configuredPort) {
-    return Optional.ofNullable(configuredPort).filter(port -> !port.trim().isEmpty()).<Integer>map(Integer::valueOf)
+    return Optional.ofNullable(configuredPort).map(String::trim).filter(port -> !port.isEmpty()).map(Integer::valueOf)
         .orElseThrow(() -> new IllegalArgumentException(configuredPort + " is not a valid port"));
   }
 
+  private static String getProtocol(String configuredProtocol, String listenerName) {
+    Optional<String> optProtocol = Optional.ofNullable(configuredProtocol).map(String::trim).filter(protocol -> !protocol.isEmpty());
+    if (optProtocol.isEmpty()) {
+      return Optional.of(listenerName).filter(SUPPORTED_PROTOCOLS::contains)
+          .orElseThrow(() -> new IllegalArgumentException("No protocol set for listener" + listenerName + " and '" + listenerName + "' is not a valid protocol either"));
+    }
+    return optProtocol.filter(SUPPORTED_PROTOCOLS::contains)
+        .orElseThrow(() -> new IllegalArgumentException(configuredProtocol + " is not a valid protocol"));
+  }
+
   public static HttpServer buildHttpServer(ResourceConfig resConfig, List<ListenerConfig> listenerConfigs) {
     Preconditions.checkNotNull(listenerConfigs);
 
@@ -213,23 +230,24 @@ public final class ListenerConfigUtil {
 
     if (CommonConstants.HTTPS_PROTOCOL.equals(listenerConfig.getProtocol())) {
       listener.setSecure(true);
-      listener.setSSLEngineConfig(buildSSLConfig(listenerConfig.getTlsConfig()));
+      listener.setSSLEngineConfig(buildSSLEngineConfigurator(listenerConfig.getTlsConfig()));
     }
 
     httpServer.addListener(listener);
   }
 
-  private static SSLEngineConfigurator buildSSLConfig(TlsConfig tlsConfig) {
+  private static SSLEngineConfigurator buildSSLEngineConfigurator(TlsConfig tlsConfig) {
     SSLContextConfigurator sslContextConfigurator = new SSLContextConfigurator();
 
     if (tlsConfig.getKeyStorePath() != null) {
       Preconditions.checkNotNull(tlsConfig.getKeyStorePassword(), "key store password required");
-      sslContextConfigurator.setKeyStoreFile(tlsConfig.getKeyStorePath());
+      sslContextConfigurator.setKeyStoreFile(cacheInTempFile(tlsConfig.getKeyStorePath()).getAbsolutePath());
       sslContextConfigurator.setKeyStorePass(tlsConfig.getKeyStorePassword());
     }
+
     if (tlsConfig.getTrustStorePath() != null) {
       Preconditions.checkNotNull(tlsConfig.getKeyStorePassword(), "trust store password required");
-      sslContextConfigurator.setTrustStoreFile(tlsConfig.getTrustStorePath());
+      sslContextConfigurator.setTrustStoreFile(cacheInTempFile(tlsConfig.getTrustStorePath()).getAbsolutePath());
       sslContextConfigurator.setTrustStorePass(tlsConfig.getTrustStorePassword());
     }
 
@@ -242,4 +260,19 @@ public final class ListenerConfigUtil {
         .map(listener -> String.format("%s://%s:%d", listener.getProtocol(), listener.getHost(), listener.getPort()))
         .toArray(), ", ");
   }
+
+  private static File cacheInTempFile(String sourceUrl) {
+    try {
+      File tempFile = Files.createTempFile("keystore", "cache").toFile();
+      tempFile.deleteOnExit();
+
+      try (InputStream is = TlsUtils.makeKeyStoreUrl(sourceUrl).openStream(); OutputStream os = new FileOutputStream(tempFile)) {
+        IOUtils.copy(is, os);
+      }
+
+      return tempFile;
+    } catch (Exception e) {
+      throw new IllegalStateException(String.format("Could not retrieve and cache keystore from '%s'", sourceUrl), e);
+    }
+  }
 }
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/util/TlsUtils.java b/pinot-core/src/main/java/org/apache/pinot/core/util/TlsUtils.java
index a004404..5bf3395 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/util/TlsUtils.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/util/TlsUtils.java
@@ -19,14 +19,16 @@
 package org.apache.pinot.core.util;
 
 import com.google.common.base.Preconditions;
-import io.netty.handler.ssl.SslProvider;
-import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
 import java.net.Socket;
 import java.net.SocketAddress;
-import java.net.UnknownHostException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
 import java.security.GeneralSecurityException;
 import java.security.KeyStore;
 import javax.net.ssl.HttpsURLConnection;
@@ -36,10 +38,10 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
-import org.apache.commons.httpclient.ConnectTimeoutException;
 import org.apache.commons.httpclient.params.HttpConnectionParams;
 import org.apache.commons.httpclient.protocol.Protocol;
 import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.commons.lang.StringUtils;
 import org.apache.pinot.common.utils.FileUploadDownloadClient;
 import org.apache.pinot.core.transport.TlsConfig;
 import org.apache.pinot.spi.env.PinotConfiguration;
@@ -72,31 +74,28 @@ public final class TlsUtils {
    * @return TlsConfig instance
    */
   public static TlsConfig extractTlsConfig(PinotConfiguration pinotConfig, String namespace) {
-    TlsConfig tlsConfig = new TlsConfig();
-
-    tlsConfig.setClientAuthEnabled(pinotConfig.getProperty(key(namespace, CLIENT_AUTH_ENABLED), false));
-
-    tlsConfig.setKeyStoreType(pinotConfig.getProperty(key(namespace, KEYSTORE_TYPE), KeyStore.getDefaultType()));
-
-    if (pinotConfig.containsKey(key(namespace, KEYSTORE_PATH))) {
-      tlsConfig.setKeyStorePath(pinotConfig.getProperty(key(namespace, KEYSTORE_PATH)));
-    }
-
-    if (pinotConfig.containsKey(key(namespace, KEYSTORE_PASSWORD))) {
-      tlsConfig.setKeyStorePassword(pinotConfig.getProperty(key(namespace, KEYSTORE_PASSWORD)));
-    }
-
-    tlsConfig.setTrustStoreType(pinotConfig.getProperty(key(namespace, TRUSTSTORE_TYPE), KeyStore.getDefaultType()));
-
-    if (pinotConfig.containsKey(key(namespace, TRUSTSTORE_PATH))) {
-      tlsConfig.setTrustStorePath(pinotConfig.getProperty(key(namespace, TRUSTSTORE_PATH)));
-    }
-
-    if (pinotConfig.containsKey(key(namespace, TRUSTSTORE_PASSWORD))) {
-      tlsConfig.setTrustStorePassword(pinotConfig.getProperty(key(namespace, TRUSTSTORE_PASSWORD)));
-    }
+    return extractTlsConfig(pinotConfig, namespace, new TlsConfig());
+  }
 
-    tlsConfig.setSslProvider(pinotConfig.getProperty(key(namespace, SSL_PROVIDER), SslProvider.JDK.toString()));
+  /**
+   * Extract a TlsConfig instance from a namespaced set of configuration keys, based on a default config
+   *
+   * @param pinotConfig pinot configuration
+   * @param namespace namespace prefix
+   * @param defaultConfig TLS config defaults
+   *
+   * @return TlsConfig instance
+   */
+  public static TlsConfig extractTlsConfig(PinotConfiguration pinotConfig, String namespace, TlsConfig defaultConfig) {
+    TlsConfig tlsConfig = new TlsConfig(defaultConfig);
+    tlsConfig.setClientAuthEnabled(pinotConfig.getProperty(key(namespace, CLIENT_AUTH_ENABLED), defaultConfig.isClientAuthEnabled()));
+    tlsConfig.setKeyStoreType(pinotConfig.getProperty(key(namespace, KEYSTORE_TYPE), defaultConfig.getKeyStoreType()));
+    tlsConfig.setKeyStorePath(pinotConfig.getProperty(key(namespace, KEYSTORE_PATH), defaultConfig.getKeyStorePath()));
+    tlsConfig.setKeyStorePassword(pinotConfig.getProperty(key(namespace, KEYSTORE_PASSWORD), defaultConfig.getKeyStorePassword()));
+    tlsConfig.setTrustStoreType(pinotConfig.getProperty(key(namespace, TRUSTSTORE_TYPE), defaultConfig.getTrustStoreType()));
+    tlsConfig.setTrustStorePath(pinotConfig.getProperty(key(namespace, TRUSTSTORE_PATH), defaultConfig.getTrustStorePath()));
+    tlsConfig.setTrustStorePassword(pinotConfig.getProperty(key(namespace, TRUSTSTORE_PASSWORD), defaultConfig.getTrustStorePassword()));
+    tlsConfig.setSslProvider(pinotConfig.getProperty(key(namespace, SSL_PROVIDER), defaultConfig.getSslProvider()));
 
     return tlsConfig;
   }
@@ -128,7 +127,7 @@ public final class TlsUtils {
 
     try {
       KeyStore keyStore = KeyStore.getInstance(keyStoreType);
-      try (FileInputStream is = new FileInputStream(keyStorePath)) {
+      try (InputStream is = makeKeyStoreUrl(keyStorePath).openStream()) {
         keyStore.load(is, keyStorePassword.toCharArray());
       }
 
@@ -168,7 +167,7 @@ public final class TlsUtils {
 
     try {
       KeyStore keyStore = KeyStore.getInstance(trustStoreType);
-      try (FileInputStream is = new FileInputStream(trustStorePath)) {
+      try (InputStream is = makeKeyStoreUrl(trustStorePath).openStream()) {
         keyStore.load(is, trustStorePassword.toCharArray());
       }
 
@@ -237,6 +236,18 @@ public final class TlsUtils {
     return namespace + "." + suffix;
   }
 
+  public static URL makeKeyStoreUrl(String storePath)
+      throws URISyntaxException, MalformedURLException {
+    URI inputUri = new URI(storePath);
+    if (StringUtils.isBlank(inputUri.getScheme())) {
+      if (storePath.startsWith("/")) {
+        return new URL("file://" + storePath);
+      }
+      return new URL("file://./" + storePath);
+    }
+    return inputUri.toURL();
+  }
+
   /**
    * Adapted from: https://svn.apache.org/viewvc/httpcomponents/oac
    * .hc3x/trunk/src/contrib/org/apache/commons/httpclient/contrib/ssl/AuthSSLProtocolSocketFactory.java?view=markup
@@ -250,14 +261,14 @@ public final class TlsUtils {
 
     @Override
     public Socket createSocket(String host, int port, InetAddress localAddress, int localPort)
-        throws IOException, UnknownHostException {
+        throws IOException {
       return _sslSocketFactory.createSocket(host, port, localAddress, localPort);
     }
 
     @Override
     public Socket createSocket(String host, int port, InetAddress localAddress, int localPort,
         HttpConnectionParams params)
-        throws IOException, UnknownHostException, ConnectTimeoutException {
+        throws IOException {
       Preconditions.checkNotNull(params);
 
       int timeout = params.getConnectionTimeout();
@@ -275,7 +286,7 @@ public final class TlsUtils {
 
     @Override
     public Socket createSocket(String host, int port)
-        throws IOException, UnknownHostException {
+        throws IOException {
       return _sslSocketFactory.createSocket(host, port);
     }
   }
diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BasicAuthTlsRealtimeIntegrationTest.java b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BasicAuthTlsRealtimeIntegrationTest.java
index 003a1d2..354c55a 100644
--- a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BasicAuthTlsRealtimeIntegrationTest.java
+++ b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BasicAuthTlsRealtimeIntegrationTest.java
@@ -19,20 +19,16 @@
 package org.apache.pinot.integration.tests;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.google.common.base.Preconditions;
 import groovy.lang.IntRange;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
+import java.net.URL;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import org.apache.commons.httpclient.methods.PostMethod;
 import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
 import org.apache.pinot.client.Connection;
 import org.apache.pinot.client.ConnectionFactory;
 import org.apache.pinot.client.JsonAsyncHttpPinotClientTransportFactory;
@@ -62,17 +58,12 @@ import static org.apache.pinot.integration.tests.BasicAuthTestUtils.AUTH_HEADER;
  * to go, you can manually run BasicAuthRealtimeIntegrationTest which tests the auth aspect only.
  */
 public class BasicAuthTlsRealtimeIntegrationTest extends BaseClusterIntegrationTest {
-  private final File _tempDirTls = new File(FileUtils.getTempDirectory(), getClass().getSimpleName() + "-cert");
-  private final File _tlsStore = _tempDirTls.toPath().resolve("tlsstore.p12").toFile();
-  private final File _tlsStoreJKS = _tempDirTls.toPath().resolve("tlsstore.jks").toFile();
+  private final URL _tlsStorePKCS12 = TlsIntegrationTest.class.getResource("/tlstest.p12");
 
   @BeforeClass
   public void setUp()
       throws Exception {
     TestUtils.ensureDirectoriesExistAndEmpty(_tempDir);
-    TestUtils.ensureDirectoriesExistAndEmpty(_tempDirTls);
-
-    prepareTlsStore();
 
     // Start Zookeeper
     startZk();
@@ -107,34 +98,38 @@ public class BasicAuthTlsRealtimeIntegrationTest extends BaseClusterIntegrationT
     stopKafka();
     stopZk();
     FileUtils.deleteDirectory(_tempDir);
-    FileUtils.deleteDirectory(_tempDirTls);
   }
 
   @Override
   public Map<String, Object> getDefaultControllerConfiguration() {
     Map<String, Object> prop = super.getDefaultControllerConfiguration();
-    prop.put("controller.tls.keystore.path", _tlsStore.getAbsolutePath());
+    prop.put("controller.tls.keystore.path", _tlsStorePKCS12);
     prop.put("controller.tls.keystore.password", "changeit");
-    prop.put("controller.tls.truststore.path", _tlsStore.getAbsolutePath());
+    prop.put("controller.tls.keystore.type", "PKCS12");
+    prop.put("controller.tls.truststore.path", _tlsStorePKCS12);
     prop.put("controller.tls.truststore.password", "changeit");
+    prop.put("controller.tls.truststore.type", "PKCS12");
 
-    prop.remove("controller.port");
     prop.put("controller.access.protocols", "https");
     prop.put("controller.access.protocols.https.port", DEFAULT_CONTROLLER_PORT);
     prop.put("controller.broker.protocol", "https");
     prop.put("controller.vip.protocol", "https");
     prop.put("controller.vip.port", DEFAULT_CONTROLLER_PORT);
 
+    prop.remove("controller.port");
+
     return BasicAuthTestUtils.addControllerConfiguration(prop);
   }
 
   @Override
   protected PinotConfiguration getDefaultBrokerConfiguration() {
     Map<String, Object> prop = super.getDefaultBrokerConfiguration().toMap();
-    prop.put("pinot.broker.tls.keystore.path", _tlsStore.getAbsolutePath());
+    prop.put("pinot.broker.tls.keystore.path", _tlsStorePKCS12);
     prop.put("pinot.broker.tls.keystore.password", "changeit");
-    prop.put("pinot.broker.tls.truststore.path", _tlsStore.getAbsolutePath());
+    prop.put("pinot.server.tls.keystore.type", "PKCS12");
+    prop.put("pinot.broker.tls.truststore.path", _tlsStorePKCS12);
     prop.put("pinot.broker.tls.truststore.password", "changeit");
+    prop.put("pinot.broker.tls.truststore.type", "PKCS12");
 
     prop.put("pinot.broker.client.access.protocols", "https");
     prop.put("pinot.broker.client.access.protocols.https.port", DEFAULT_BROKER_PORT);
@@ -146,15 +141,16 @@ public class BasicAuthTlsRealtimeIntegrationTest extends BaseClusterIntegrationT
   @Override
   protected PinotConfiguration getDefaultServerConfiguration() {
     Map<String, Object> prop = super.getDefaultServerConfiguration().toMap();
-    prop.put("pinot.server.tls.keystore.path", _tlsStoreJKS.getAbsolutePath());
+    prop.put("pinot.server.tls.keystore.path", _tlsStorePKCS12);
     prop.put("pinot.server.tls.keystore.password", "changeit");
     prop.put("pinot.server.tls.keystore.type", "PKCS12");
-    prop.put("pinot.server.tls.truststore.path", _tlsStore.getAbsolutePath());
+    prop.put("pinot.server.tls.truststore.path", _tlsStorePKCS12);
     prop.put("pinot.server.tls.truststore.password", "changeit");
-    prop.put("pinot.server.admin.access.control.factory.class",
-        CertBasedTlsChannelAccessControlFactory.class.getName());
+    prop.put("pinot.server.tls.truststore.type", "PKCS12");
     prop.put("pinot.server.tls.client.auth.enabled", "true");
 
+    prop.put("pinot.server.admin.access.control.factory.class",
+        CertBasedTlsChannelAccessControlFactory.class.getName());
     prop.put("pinot.server.adminapi.access.protocols", "https");
     prop.put("pinot.server.adminapi.access.protocols.https.port", "7443");
     prop.put("pinot.server.netty.enabled", "false");
@@ -168,10 +164,12 @@ public class BasicAuthTlsRealtimeIntegrationTest extends BaseClusterIntegrationT
   @Override
   protected PinotConfiguration getDefaultMinionConfiguration() {
     Map<String, Object> prop = super.getDefaultMinionConfiguration().toMap();
-    prop.put("pinot.minion.tls.keystore.path", _tlsStore.getAbsolutePath());
+    prop.put("pinot.minion.tls.keystore.path", _tlsStorePKCS12);
     prop.put("pinot.minion.tls.keystore.password", "changeit");
-    prop.put("pinot.minion.tls.truststore.path", _tlsStore.getAbsolutePath());
+    prop.put("pinot.server.tls.keystore.type", "PKCS12");
+    prop.put("pinot.minion.tls.truststore.path", _tlsStorePKCS12);
     prop.put("pinot.minion.tls.truststore.password", "changeit");
+    prop.put("pinot.server.tls.truststore.type", "PKCS12");
 
     return BasicAuthTestUtils.addMinionConfiguration(prop);
   }
@@ -260,43 +258,4 @@ public class BasicAuthTlsRealtimeIntegrationTest extends BaseClusterIntegrationT
               > 200000); // download segment
     }
   }
-
-  void prepareTlsStore()
-      throws Exception {
-    try (OutputStream os = new FileOutputStream(_tlsStore);
-        /*
-         * Command to generate the tlstest.jks file (generate key pairs for both IPV4 and IPV6 addresses):
-         * ```
-         *  keytool -genkeypair -keystore tlstest.jks -dname "CN=test, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, \
-         *  C=Unknown" -keypass changeit -storepass changeit -keyalg RSA -alias localhost-ipv4 -ext \
-         *  SAN=dns:localhost,ip:127.0.0.1
-         *
-         *  keytool -genkeypair -keystore tlstest.jks -dname "CN=test, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, \
-         *  C=Unknown" -keypass changeit -storepass changeit -keyalg RSA -alias localhost-ipv6 -ext \
-         *  SAN=dns:localhost,ip:0:0:0:0:0:0:0:1
-         * ```
-         */
-        InputStream is = getClass().getResourceAsStream("/tlstest.p12")) {
-      Preconditions.checkNotNull(is, "tlstest.p12 must be on the classpath");
-      IOUtils.copy(is, os);
-    }
-
-    try (OutputStream osJKS = new FileOutputStream(_tlsStoreJKS);
-        /*
-         * Command to generate the tlstest.pkcs file (generate key pairs for both IPV4 and IPV6 addresses):
-         * ```
-         *  keytool -genkeypair -storetype JKS -keystore tlstest.p12 -dname "CN=test, OU=Unknown, O=Unknown, \
-         *  L=Unknown, ST=Unknown, C=Unknown" -keypass changeit -storepass changeit -keyalg RSA \
-         *  -alias localhost-ipv4 -ext SAN=dns:localhost,ip:127.0.0.1
-         *
-         *  keytool -genkeypair -storetype JKS -keystore tlstest.p12 -dname "CN=test, OU=Unknown, O=Unknown, \
-         *  L=Unknown, ST=Unknown, C=Unknown" -keypass changeit -storepass changeit -keyalg RSA \
-         *  -alias localhost-ipv6 -ext SAN=dns:localhost,ip:0:0:0:0:0:0:0:1
-         * ```
-         */
-        InputStream isJKS = getClass().getResourceAsStream("/tlstest.jks")) {
-      Preconditions.checkNotNull(isJKS, "tlstest.jks must be on the classpath");
-      IOUtils.copy(isJKS, osJKS);
-    }
-  }
 }
diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/TlsIntegrationTest.java b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/TlsIntegrationTest.java
new file mode 100644
index 0000000..a6e3c5c
--- /dev/null
+++ b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/TlsIntegrationTest.java
@@ -0,0 +1,354 @@
+/**
+ * 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.pinot.integration.tests;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.Header;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.pinot.client.Connection;
+import org.apache.pinot.client.ConnectionFactory;
+import org.apache.pinot.client.JsonAsyncHttpPinotClientTransportFactory;
+import org.apache.pinot.common.utils.FileUploadDownloadClient;
+import org.apache.pinot.integration.tests.access.CertBasedTlsChannelAccessControlFactory;
+import org.apache.pinot.spi.config.table.TableConfig;
+import org.apache.pinot.spi.data.Schema;
+import org.apache.pinot.spi.env.PinotConfiguration;
+import org.apache.pinot.spi.utils.CommonConstants;
+import org.apache.pinot.spi.utils.builder.TableNameBuilder;
+import org.apache.pinot.util.TestUtils;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static org.apache.pinot.integration.tests.BasicAuthTestUtils.AUTH_HEADER;
+import static org.apache.pinot.integration.tests.BasicAuthTestUtils.AUTH_TOKEN;
+
+
+public class TlsIntegrationTest extends BaseClusterIntegrationTest {
+  private static final String PASSWORD = "changeit";
+  private static final char[] PASSWORD_CHAR = PASSWORD.toCharArray();
+  private static final Header CLIENT_HEADER = new BasicHeader("Authorization", AUTH_TOKEN);
+
+  private static final int INTERNAL_CONTROLLER_PORT = DEFAULT_CONTROLLER_PORT + 1;
+  private static final int INTERNAL_BROKER_PORT = DEFAULT_BROKER_PORT + 1;
+  private static final String PKCS_12 = "PKCS12";
+  private static final String JKS = "JKS";
+
+  private final URL _tlsStoreEmptyPKCS12 = TlsIntegrationTest.class.getResource("/empty.p12");
+  private final URL _tlsStoreEmptyJKS = TlsIntegrationTest.class.getResource("/empty.jks");
+  private final URL _tlsStorePKCS12 = TlsIntegrationTest.class.getResource("/tlstest.p12");
+  private final URL _tlsStoreJKS = TlsIntegrationTest.class.getResource("/tlstest.jks");
+
+  @BeforeClass
+  public void setUp()
+      throws Exception {
+    TestUtils.ensureDirectoriesExistAndEmpty(_tempDir);
+
+    // Start Zookeeper
+    startZk();
+    // Start Pinot cluster
+    startKafka();
+    startController();
+    startBrokerHttps();
+    startServerHttps();
+
+    // Unpack the Avro files
+    List<File> avroFiles = unpackAvroData(_tempDir);
+
+    // Create and upload the schema and table config
+    addSchema(createSchema());
+    addTableConfig(createRealtimeTableConfig(avroFiles.get(0)));
+    addTableConfig(createOfflineTableConfig());
+
+    // Push data into Kafka
+    pushAvroIntoKafka(avroFiles);
+    waitForAllDocsLoaded(600_000L);
+
+    System.out.println("hello world!");
+
+    Thread.sleep(600000);
+  }
+
+  @AfterClass(alwaysRun = true)
+  public void tearDown()
+      throws Exception {
+    dropRealtimeTable(getTableName());
+    stopServer();
+    stopBroker();
+    stopController();
+    stopKafka();
+    stopZk();
+    FileUtils.deleteDirectory(_tempDir);
+  }
+
+  @Override
+  public Map<String, Object> getDefaultControllerConfiguration() {
+    Map<String, Object> prop = super.getDefaultControllerConfiguration();
+    prop.put("controller.tls.keystore.path", _tlsStorePKCS12);
+    prop.put("controller.tls.keystore.password", PASSWORD);
+    prop.put("controller.tls.keystore.type", PKCS_12);
+    prop.put("controller.tls.truststore.path", _tlsStorePKCS12);
+    prop.put("controller.tls.truststore.password", PASSWORD);
+    prop.put("controller.tls.truststore.type", PKCS_12);
+
+//    prop.put("controller.access.protocols", "https");
+//    prop.put("controller.access.protocols.https.port", DEFAULT_CONTROLLER_PORT);
+    prop.put("controller.access.protocols", "https,internal");
+    prop.put("controller.access.protocols.https.port", DEFAULT_CONTROLLER_PORT);
+    prop.put("controller.access.protocols.https.tls.keystore.path", _tlsStoreJKS);
+    prop.put("controller.access.protocols.https.tls.keystore.type", JKS);
+    prop.put("controller.access.protocols.https.tls.truststore.path", _tlsStoreJKS);
+    prop.put("controller.access.protocols.https.tls.truststore.type", JKS);
+    prop.put("controller.access.protocols.internal.protocol", "https");
+    prop.put("controller.access.protocols.internal.port", INTERNAL_CONTROLLER_PORT);
+    prop.put("controller.access.protocols.internal.tls.client.auth.enabled", "true");
+
+    prop.put("controller.broker.protocol", "https");
+    prop.put("controller.broker.port.override", INTERNAL_BROKER_PORT);
+
+    // announce external only
+    prop.put("controller.vip.protocol", "https");
+    prop.put("controller.vip.port", DEFAULT_CONTROLLER_PORT);
+
+    prop.remove("controller.port");
+
+    return BasicAuthTestUtils.addControllerConfiguration(prop);
+  }
+
+  @Override
+  protected PinotConfiguration getDefaultBrokerConfiguration() {
+    Map<String, Object> prop = super.getDefaultBrokerConfiguration().toMap();
+    prop.put("pinot.broker.tls.keystore.path", _tlsStorePKCS12);
+    prop.put("pinot.broker.tls.keystore.password", PASSWORD);
+    prop.put("pinot.broker.tls.keystore.type", PKCS_12);
+    prop.put("pinot.broker.tls.truststore.path", _tlsStorePKCS12);
+    prop.put("pinot.broker.tls.truststore.password", PASSWORD);
+    prop.put("pinot.broker.tls.truststore.type", PKCS_12);
+
+//    prop.put("pinot.broker.client.access.protocols", "https");
+//    prop.put("pinot.broker.client.access.protocols.https.port", DEFAULT_BROKER_PORT);
+    prop.put("pinot.broker.client.access.protocols", "https,internal");
+    prop.put("pinot.broker.client.access.protocols.https.port", DEFAULT_BROKER_PORT);
+    prop.put("pinot.broker.client.access.protocols.https.tls.keystore.path", _tlsStoreJKS);
+    prop.put("pinot.broker.client.access.protocols.https.tls.keystore.type", JKS);
+    prop.put("pinot.broker.client.access.protocols.https.tls.truststore.path", _tlsStoreJKS);
+    prop.put("pinot.broker.client.access.protocols.https.tls.truststore.type", JKS);
+    prop.put("pinot.broker.client.access.protocols.internal.protocol", "https");
+    prop.put("pinot.broker.client.access.protocols.internal.port", INTERNAL_BROKER_PORT);
+    prop.put("pinot.broker.client.access.protocols.internal.tls.client.auth.enabled", "true");
+
+    prop.put("pinot.broker.nettytls.enabled", "true");
+
+    return BasicAuthTestUtils.addBrokerConfiguration(prop);
+  }
+
+  @Override
+  protected PinotConfiguration getDefaultServerConfiguration() {
+    Map<String, Object> prop = super.getDefaultServerConfiguration().toMap();
+    prop.put("pinot.server.tls.keystore.path", _tlsStorePKCS12);
+    prop.put("pinot.server.tls.keystore.password", PASSWORD);
+    prop.put("pinot.server.tls.keystore.type", PKCS_12);
+    prop.put("pinot.server.tls.truststore.path", _tlsStorePKCS12);
+    prop.put("pinot.server.tls.truststore.password", PASSWORD);
+    prop.put("pinot.server.tls.truststore.type", PKCS_12);
+    prop.put("pinot.server.tls.client.auth.enabled", "true");
+
+    prop.put("pinot.server.admin.access.control.factory.class",
+        CertBasedTlsChannelAccessControlFactory.class.getName());
+//    prop.put("pinot.server.adminapi.access.protocols", "https");
+//    prop.put("pinot.server.adminapi.access.protocols.https.port", "7443");
+    prop.put("pinot.server.adminapi.access.protocols", "internal");
+    prop.put("pinot.server.adminapi.access.protocols.internal.protocol", "https");
+    prop.put("pinot.server.adminapi.access.protocols.internal.port", "7443");
+    prop.put("pinot.server.netty.enabled", "false");
+    prop.put("pinot.server.nettytls.enabled", "true");
+    prop.put("pinot.server.nettytls.port", "8089");
+    prop.put("pinot.server.segment.uploader.protocol", "https");
+
+    return BasicAuthTestUtils.addServerConfiguration(prop);
+  }
+
+  @Override
+  protected boolean useLlc() {
+    return true;
+  }
+
+  @Override
+  protected void addSchema(Schema schema)
+      throws IOException {
+    PostMethod response =
+        sendMultipartPostRequest(_controllerRequestURLBuilder.forSchemaCreate(), schema.toSingleLineJsonString(),
+            AUTH_HEADER);
+    Assert.assertEquals(response.getStatusCode(), 200);
+  }
+
+  @Override
+  protected void addTableConfig(TableConfig tableConfig)
+      throws IOException {
+    sendPostRequest(_controllerRequestURLBuilder.forTableCreate(), tableConfig.toJsonString(), AUTH_HEADER);
+  }
+
+  @Override
+  protected Connection getPinotConnection() {
+    if (_pinotConnection == null) {
+      JsonAsyncHttpPinotClientTransportFactory factory = new JsonAsyncHttpPinotClientTransportFactory();
+      factory.setHeaders(AUTH_HEADER);
+      factory.setScheme(CommonConstants.HTTPS_PROTOCOL);
+      factory.setSslContext(FileUploadDownloadClient._defaultSSLContext);
+
+      _pinotConnection =
+          ConnectionFactory.fromZookeeper(getZkUrl() + "/" + getHelixClusterName(), factory.buildTransport());
+    }
+    return _pinotConnection;
+  }
+
+  @Override
+  protected void dropRealtimeTable(String tableName)
+      throws IOException {
+    sendDeleteRequest(
+        _controllerRequestURLBuilder.forTableDelete(TableNameBuilder.REALTIME.tableNameWithType(tableName)),
+        AUTH_HEADER);
+  }
+
+  @Test
+  public void testQueryControllerExternalTrustedServer()
+      throws Exception {
+    try (CloseableHttpClient client = makeClient(JKS, _tlsStoreJKS, _tlsStoreJKS)) {
+      HttpUriRequest request = new HttpGet("https://localhost:" + DEFAULT_CONTROLLER_PORT + "/tables");
+      request.addHeader(CLIENT_HEADER);
+
+      try (CloseableHttpResponse response = client.execute(request)) {
+        Assert.assertEquals(response.getStatusLine().getStatusCode(), 200);
+        String output = IOUtils.toString(response.getEntity().getContent());
+        System.out.println(output);
+      }
+    }
+  }
+
+  @Test
+  public void testQueryControllerExternalUntrustedServer()
+      throws Exception {
+    try (CloseableHttpClient client = makeClient(JKS, _tlsStoreJKS, _tlsStoreEmptyJKS)) {
+      HttpUriRequest request = new HttpGet("https://localhost:" + DEFAULT_CONTROLLER_PORT + "/tables");
+      request.addHeader(CLIENT_HEADER);
+
+      try {
+        client.execute(request);
+        Assert.fail("Must not allow connection to untrusted server");
+      } catch (IOException ignore) {
+        // this should fail
+      }
+    }
+  }
+
+  @Test
+  public void testQueryControllerInternalTrustedClient()
+      throws Exception {
+    try (CloseableHttpClient client = makeClient(PKCS_12, _tlsStorePKCS12, _tlsStorePKCS12)) {
+      HttpUriRequest request = new HttpGet("https://localhost:" + INTERNAL_CONTROLLER_PORT + "/tables");
+      request.addHeader(CLIENT_HEADER);
+
+      try (CloseableHttpResponse response = client.execute(request)) {
+        Assert.assertEquals(response.getStatusLine().getStatusCode(), 200);
+        String output = IOUtils.toString(response.getEntity().getContent());
+        System.out.println(output);
+      }
+    }
+  }
+
+  @Test
+  public void testQueryControllerInternalUntrustedClient()
+      throws Exception {
+    try (CloseableHttpClient client = makeClient(PKCS_12, _tlsStoreEmptyPKCS12, _tlsStorePKCS12)) {
+      HttpUriRequest request = new HttpGet("https://localhost:" + INTERNAL_CONTROLLER_PORT + "/tables");
+      request.addHeader(CLIENT_HEADER);
+
+      try {
+        client.execute(request);
+        Assert.fail("Must not allow connection from untrusted client");
+      } catch (IOException ignore) {
+        // this should fail
+      }
+    }
+  }
+
+  @Test
+  public void testQueryBrokerExternal()
+      throws Exception {
+    Assert.fail("not implemented yet");
+  }
+
+  @Test
+  public void testQueryBrokerInternal()
+      throws Exception {
+    Assert.fail("not implemented yet");
+  }
+
+  private static CloseableHttpClient makeClient(String keyStoreType, URL keyStoreUrl, URL trustStoreUrl) {
+    try {
+      SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
+      sslContextBuilder.setKeyStoreType(keyStoreType);
+      sslContextBuilder.loadKeyMaterial(keyStoreUrl, PASSWORD_CHAR, PASSWORD_CHAR);
+      sslContextBuilder.loadTrustMaterial(trustStoreUrl, PASSWORD_CHAR);
+      return HttpClientBuilder.create().setSSLContext(sslContextBuilder.build()).build();
+    } catch (Exception e) {
+      throw new IllegalStateException("Could not create HTTPS client");
+    }
+  }
+
+  /*
+   * Command to generate the tlstest.jks file (generate key pairs for both IPV4 and IPV6 addresses):
+   * ```
+   *  keytool -genkeypair -keystore tlstest.jks -dname "CN=test, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, \
+   *  C=Unknown" -keypass changeit -storepass changeit -keyalg RSA -alias localhost-ipv4 -ext \
+   *  SAN=dns:localhost,ip:127.0.0.1
+   *
+   *  keytool -genkeypair -keystore tlstest.jks -dname "CN=test, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, \
+   *  C=Unknown" -keypass changeit -storepass changeit -keyalg RSA -alias localhost-ipv6 -ext \
+   *  SAN=dns:localhost,ip:0:0:0:0:0:0:0:1
+   * ```
+   */
+
+  /*
+   * Command to generate the tlstest.pkcs file (generate key pairs for both IPV4 and IPV6 addresses):
+   * ```
+   *  keytool -genkeypair -storetype JKS -keystore tlstest.p12 -dname "CN=test, OU=Unknown, O=Unknown, \
+   *  L=Unknown, ST=Unknown, C=Unknown" -keypass changeit -storepass changeit -keyalg RSA \
+   *  -alias localhost-ipv4 -ext SAN=dns:localhost,ip:127.0.0.1
+   *
+   *  keytool -genkeypair -storetype JKS -keystore tlstest.p12 -dname "CN=test, OU=Unknown, O=Unknown, \
+   *  L=Unknown, ST=Unknown, C=Unknown" -keypass changeit -storepass changeit -keyalg RSA \
+   *  -alias localhost-ipv6 -ext SAN=dns:localhost,ip:0:0:0:0:0:0:0:1
+   * ```
+   */
+}
diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/access/CertBasedTlsChannelAccessControlFactory.java b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/access/CertBasedTlsChannelAccessControlFactory.java
index 99f9501..dd65e77 100644
--- a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/access/CertBasedTlsChannelAccessControlFactory.java
+++ b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/access/CertBasedTlsChannelAccessControlFactory.java
@@ -46,7 +46,8 @@ public class CertBasedTlsChannelAccessControlFactory implements AccessControlFac
     private final Logger _logger = LoggerFactory.getLogger(CertBasedTlsChannelAccessControl.class);
 
     private final Set<String> _aclPrincipalAllowlist = new HashSet<String>() {{
-      add("CN=test, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown");
+      add("CN=test-jks, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown");
+      add("CN=test-p12, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown");
     }};
 
     @Override
diff --git a/pinot-integration-tests/src/test/resources/empty.jks b/pinot-integration-tests/src/test/resources/empty.jks
new file mode 100644
index 0000000..c408465
Binary files /dev/null and b/pinot-integration-tests/src/test/resources/empty.jks differ
diff --git a/pinot-integration-tests/src/test/resources/empty.p12 b/pinot-integration-tests/src/test/resources/empty.p12
new file mode 100644
index 0000000..4f5baf1
Binary files /dev/null and b/pinot-integration-tests/src/test/resources/empty.p12 differ
diff --git a/pinot-integration-tests/src/test/resources/tlstest.jks b/pinot-integration-tests/src/test/resources/tlstest.jks
index 12f28e2..a43845f 100644
Binary files a/pinot-integration-tests/src/test/resources/tlstest.jks and b/pinot-integration-tests/src/test/resources/tlstest.jks differ
diff --git a/pinot-integration-tests/src/test/resources/tlstest.p12 b/pinot-integration-tests/src/test/resources/tlstest.p12
index 7750790..23c49e4 100644
Binary files a/pinot-integration-tests/src/test/resources/tlstest.p12 and b/pinot-integration-tests/src/test/resources/tlstest.p12 differ

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org


[pinot] 02/02: controller working

Posted by ap...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

apucher pushed a commit to branch listener-tls-customization
in repository https://gitbox.apache.org/repos/asf/pinot.git

commit 363370412f6f477a3a85a432596c90fd0e796308
Author: Alexander Pucher <ap...@apache.org>
AuthorDate: Thu Jan 27 16:29:45 2022 -0800

    controller working
---
 .../apache/pinot/core/util/ListenerConfigUtil.java |  4 +-
 .../integration/tests/TlsIntegrationTest.java      | 89 +++++++++-------------
 2 files changed, 39 insertions(+), 54 deletions(-)

diff --git a/pinot-core/src/main/java/org/apache/pinot/core/util/ListenerConfigUtil.java b/pinot-core/src/main/java/org/apache/pinot/core/util/ListenerConfigUtil.java
index 0fd1143..018072a 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/util/ListenerConfigUtil.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/util/ListenerConfigUtil.java
@@ -179,7 +179,7 @@ public final class ListenerConfigUtil {
 
     return new ListenerConfig(name, getHost(config.getProperty(protocolNamespace + ".host", DEFAULT_HOST)),
         getPort(config.getProperty(protocolNamespace + ".port")), getProtocol(config.getProperty(protocolNamespace + ".protocol"), name),
-        TlsUtils.extractTlsConfig(config, namespace + ".tls", tlsConfig));
+        TlsUtils.extractTlsConfig(config, protocolNamespace + ".tls", tlsConfig));
   }
 
   private static String getHost(String configuredHost) {
@@ -263,7 +263,7 @@ public final class ListenerConfigUtil {
 
   private static File cacheInTempFile(String sourceUrl) {
     try {
-      File tempFile = Files.createTempFile("keystore", "cache").toFile();
+      File tempFile = Files.createTempFile("pinot-keystore-", null).toFile();
       tempFile.deleteOnExit();
 
       try (InputStream is = TlsUtils.makeKeyStoreUrl(sourceUrl).openStream(); OutputStream os = new FileOutputStream(tempFile)) {
diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/TlsIntegrationTest.java b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/TlsIntegrationTest.java
index a6e3c5c..edc8dd2 100644
--- a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/TlsIntegrationTest.java
+++ b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/TlsIntegrationTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.pinot.integration.tests;
 
+import com.fasterxml.jackson.databind.JsonNode;
 import java.io.File;
 import java.io.IOException;
 import java.net.URL;
@@ -43,6 +44,7 @@ import org.apache.pinot.spi.config.table.TableConfig;
 import org.apache.pinot.spi.data.Schema;
 import org.apache.pinot.spi.env.PinotConfiguration;
 import org.apache.pinot.spi.utils.CommonConstants;
+import org.apache.pinot.spi.utils.JsonUtils;
 import org.apache.pinot.spi.utils.builder.TableNameBuilder;
 import org.apache.pinot.util.TestUtils;
 import org.testng.Assert;
@@ -59,8 +61,8 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
   private static final char[] PASSWORD_CHAR = PASSWORD.toCharArray();
   private static final Header CLIENT_HEADER = new BasicHeader("Authorization", AUTH_TOKEN);
 
-  private static final int INTERNAL_CONTROLLER_PORT = DEFAULT_CONTROLLER_PORT + 1;
-  private static final int INTERNAL_BROKER_PORT = DEFAULT_BROKER_PORT + 1;
+  private static final int EXTERNAL_CONTROLLER_PORT = DEFAULT_CONTROLLER_PORT + 1;
+  private static final int EXTERNAL_BROKER_PORT = DEFAULT_BROKER_PORT + 1;
   private static final String PKCS_12 = "PKCS12";
   private static final String JKS = "JKS";
 
@@ -93,10 +95,6 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
     // Push data into Kafka
     pushAvroIntoKafka(avroFiles);
     waitForAllDocsLoaded(600_000L);
-
-    System.out.println("hello world!");
-
-    Thread.sleep(600000);
   }
 
   @AfterClass(alwaysRun = true)
@@ -121,20 +119,19 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
     prop.put("controller.tls.truststore.password", PASSWORD);
     prop.put("controller.tls.truststore.type", PKCS_12);
 
-//    prop.put("controller.access.protocols", "https");
-//    prop.put("controller.access.protocols.https.port", DEFAULT_CONTROLLER_PORT);
-    prop.put("controller.access.protocols", "https,internal");
-    prop.put("controller.access.protocols.https.port", DEFAULT_CONTROLLER_PORT);
-    prop.put("controller.access.protocols.https.tls.keystore.path", _tlsStoreJKS);
-    prop.put("controller.access.protocols.https.tls.keystore.type", JKS);
-    prop.put("controller.access.protocols.https.tls.truststore.path", _tlsStoreJKS);
-    prop.put("controller.access.protocols.https.tls.truststore.type", JKS);
+    // CAUTION: order matters. first listener becomes registered as internal address in zookeeper
+    prop.put("controller.access.protocols", "internal,external");
     prop.put("controller.access.protocols.internal.protocol", "https");
-    prop.put("controller.access.protocols.internal.port", INTERNAL_CONTROLLER_PORT);
+    prop.put("controller.access.protocols.internal.port", DEFAULT_CONTROLLER_PORT);
     prop.put("controller.access.protocols.internal.tls.client.auth.enabled", "true");
+    prop.put("controller.access.protocols.external.protocol", "https");
+    prop.put("controller.access.protocols.external.port", EXTERNAL_CONTROLLER_PORT);
+    prop.put("controller.access.protocols.external.tls.keystore.path", _tlsStoreJKS);
+    prop.put("controller.access.protocols.external.tls.keystore.type", JKS);
+    prop.put("controller.access.protocols.external.tls.truststore.path", _tlsStoreJKS);
+    prop.put("controller.access.protocols.external.tls.truststore.type", JKS);
 
     prop.put("controller.broker.protocol", "https");
-    prop.put("controller.broker.port.override", INTERNAL_BROKER_PORT);
 
     // announce external only
     prop.put("controller.vip.protocol", "https");
@@ -155,17 +152,17 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
     prop.put("pinot.broker.tls.truststore.password", PASSWORD);
     prop.put("pinot.broker.tls.truststore.type", PKCS_12);
 
-//    prop.put("pinot.broker.client.access.protocols", "https");
-//    prop.put("pinot.broker.client.access.protocols.https.port", DEFAULT_BROKER_PORT);
-    prop.put("pinot.broker.client.access.protocols", "https,internal");
-    prop.put("pinot.broker.client.access.protocols.https.port", DEFAULT_BROKER_PORT);
-    prop.put("pinot.broker.client.access.protocols.https.tls.keystore.path", _tlsStoreJKS);
-    prop.put("pinot.broker.client.access.protocols.https.tls.keystore.type", JKS);
-    prop.put("pinot.broker.client.access.protocols.https.tls.truststore.path", _tlsStoreJKS);
-    prop.put("pinot.broker.client.access.protocols.https.tls.truststore.type", JKS);
+    // CAUTION: order matters. first listener becomes registered as internal address in zookeeper
+    prop.put("pinot.broker.client.access.protocols", "internal,external");
     prop.put("pinot.broker.client.access.protocols.internal.protocol", "https");
-    prop.put("pinot.broker.client.access.protocols.internal.port", INTERNAL_BROKER_PORT);
+    prop.put("pinot.broker.client.access.protocols.internal.port", DEFAULT_BROKER_PORT);
     prop.put("pinot.broker.client.access.protocols.internal.tls.client.auth.enabled", "true");
+    prop.put("pinot.broker.client.access.protocols.external.protocol", "https");
+    prop.put("pinot.broker.client.access.protocols.external.port", EXTERNAL_BROKER_PORT);
+    prop.put("pinot.broker.client.access.protocols.external.tls.keystore.path", _tlsStoreJKS);
+    prop.put("pinot.broker.client.access.protocols.external.tls.keystore.type", JKS);
+    prop.put("pinot.broker.client.access.protocols.external.tls.truststore.path", _tlsStoreJKS);
+    prop.put("pinot.broker.client.access.protocols.external.tls.truststore.type", JKS);
 
     prop.put("pinot.broker.nettytls.enabled", "true");
 
@@ -185,8 +182,6 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
 
     prop.put("pinot.server.admin.access.control.factory.class",
         CertBasedTlsChannelAccessControlFactory.class.getName());
-//    prop.put("pinot.server.adminapi.access.protocols", "https");
-//    prop.put("pinot.server.adminapi.access.protocols.https.port", "7443");
     prop.put("pinot.server.adminapi.access.protocols", "internal");
     prop.put("pinot.server.adminapi.access.protocols.internal.protocol", "https");
     prop.put("pinot.server.adminapi.access.protocols.internal.port", "7443");
@@ -244,13 +239,14 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
   public void testQueryControllerExternalTrustedServer()
       throws Exception {
     try (CloseableHttpClient client = makeClient(JKS, _tlsStoreJKS, _tlsStoreJKS)) {
-      HttpUriRequest request = new HttpGet("https://localhost:" + DEFAULT_CONTROLLER_PORT + "/tables");
+      HttpUriRequest request = new HttpGet("https://localhost:" + EXTERNAL_CONTROLLER_PORT + "/tables");
       request.addHeader(CLIENT_HEADER);
 
       try (CloseableHttpResponse response = client.execute(request)) {
         Assert.assertEquals(response.getStatusLine().getStatusCode(), 200);
-        String output = IOUtils.toString(response.getEntity().getContent());
-        System.out.println(output);
+        JsonNode tables = JsonUtils.inputStreamToJsonNode(response.getEntity().getContent()).get("tables");
+        Assert.assertEquals(tables.size(), 1);
+        Assert.assertEquals(tables.get(0).textValue(), "mytable");
       }
     }
   }
@@ -259,7 +255,7 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
   public void testQueryControllerExternalUntrustedServer()
       throws Exception {
     try (CloseableHttpClient client = makeClient(JKS, _tlsStoreJKS, _tlsStoreEmptyJKS)) {
-      HttpUriRequest request = new HttpGet("https://localhost:" + DEFAULT_CONTROLLER_PORT + "/tables");
+      HttpUriRequest request = new HttpGet("https://localhost:" + EXTERNAL_CONTROLLER_PORT + "/tables");
       request.addHeader(CLIENT_HEADER);
 
       try {
@@ -275,13 +271,14 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
   public void testQueryControllerInternalTrustedClient()
       throws Exception {
     try (CloseableHttpClient client = makeClient(PKCS_12, _tlsStorePKCS12, _tlsStorePKCS12)) {
-      HttpUriRequest request = new HttpGet("https://localhost:" + INTERNAL_CONTROLLER_PORT + "/tables");
+      HttpUriRequest request = new HttpGet("https://localhost:" + DEFAULT_CONTROLLER_PORT + "/tables");
       request.addHeader(CLIENT_HEADER);
 
       try (CloseableHttpResponse response = client.execute(request)) {
         Assert.assertEquals(response.getStatusLine().getStatusCode(), 200);
-        String output = IOUtils.toString(response.getEntity().getContent());
-        System.out.println(output);
+        JsonNode tables = JsonUtils.inputStreamToJsonNode(response.getEntity().getContent()).get("tables");
+        Assert.assertEquals(tables.size(), 1);
+        Assert.assertEquals(tables.get(0).textValue(), "mytable");
       }
     }
   }
@@ -290,7 +287,7 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
   public void testQueryControllerInternalUntrustedClient()
       throws Exception {
     try (CloseableHttpClient client = makeClient(PKCS_12, _tlsStoreEmptyPKCS12, _tlsStorePKCS12)) {
-      HttpUriRequest request = new HttpGet("https://localhost:" + INTERNAL_CONTROLLER_PORT + "/tables");
+      HttpUriRequest request = new HttpGet("https://localhost:" + DEFAULT_CONTROLLER_PORT + "/tables");
       request.addHeader(CLIENT_HEADER);
 
       try {
@@ -302,18 +299,6 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
     }
   }
 
-  @Test
-  public void testQueryBrokerExternal()
-      throws Exception {
-    Assert.fail("not implemented yet");
-  }
-
-  @Test
-  public void testQueryBrokerInternal()
-      throws Exception {
-    Assert.fail("not implemented yet");
-  }
-
   private static CloseableHttpClient makeClient(String keyStoreType, URL keyStoreUrl, URL trustStoreUrl) {
     try {
       SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
@@ -322,18 +307,18 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
       sslContextBuilder.loadTrustMaterial(trustStoreUrl, PASSWORD_CHAR);
       return HttpClientBuilder.create().setSSLContext(sslContextBuilder.build()).build();
     } catch (Exception e) {
-      throw new IllegalStateException("Could not create HTTPS client");
+      throw new IllegalStateException("Could not create HTTPS client", e);
     }
   }
 
   /*
    * Command to generate the tlstest.jks file (generate key pairs for both IPV4 and IPV6 addresses):
    * ```
-   *  keytool -genkeypair -keystore tlstest.jks -dname "CN=test, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, \
+   *  keytool -genkeypair -keystore tlstest.jks -dname "CN=test-jks, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, \
    *  C=Unknown" -keypass changeit -storepass changeit -keyalg RSA -alias localhost-ipv4 -ext \
    *  SAN=dns:localhost,ip:127.0.0.1
    *
-   *  keytool -genkeypair -keystore tlstest.jks -dname "CN=test, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, \
+   *  keytool -genkeypair -keystore tlstest.jks -dname "CN=test-jks, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, \
    *  C=Unknown" -keypass changeit -storepass changeit -keyalg RSA -alias localhost-ipv6 -ext \
    *  SAN=dns:localhost,ip:0:0:0:0:0:0:0:1
    * ```
@@ -342,11 +327,11 @@ public class TlsIntegrationTest extends BaseClusterIntegrationTest {
   /*
    * Command to generate the tlstest.pkcs file (generate key pairs for both IPV4 and IPV6 addresses):
    * ```
-   *  keytool -genkeypair -storetype JKS -keystore tlstest.p12 -dname "CN=test, OU=Unknown, O=Unknown, \
+   *  keytool -genkeypair -storetype JKS -keystore tlstest.p12 -dname "CN=test-p12, OU=Unknown, O=Unknown, \
    *  L=Unknown, ST=Unknown, C=Unknown" -keypass changeit -storepass changeit -keyalg RSA \
    *  -alias localhost-ipv4 -ext SAN=dns:localhost,ip:127.0.0.1
    *
-   *  keytool -genkeypair -storetype JKS -keystore tlstest.p12 -dname "CN=test, OU=Unknown, O=Unknown, \
+   *  keytool -genkeypair -storetype JKS -keystore tlstest.p12 -dname "CN=test-p12, OU=Unknown, O=Unknown, \
    *  L=Unknown, ST=Unknown, C=Unknown" -keypass changeit -storepass changeit -keyalg RSA \
    *  -alias localhost-ipv6 -ext SAN=dns:localhost,ip:0:0:0:0:0:0:0:1
    * ```

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org