From e8a1c06ad2511127ee78b118867af6e4440af2cb Mon Sep 17 00:00:00 2001 From: Elbin Pallimalil Date: Fri, 23 May 2025 04:22:08 +0530 Subject: [PATCH] Add support for mTLS authentication in Arrow Flight client --- .../facebook/plugin/arrow/ArrowErrorCode.java | 4 +- .../plugin/arrow/ArrowFlightConfig.java | 29 ++++ .../arrow/BaseArrowFlightClientHandler.java | 56 ++++++- .../plugin/arrow/TestArrowFlightMtls.java | 146 ++++++++++++++++++ .../src/test/resources/mtls/ca.crt | 33 ++++ .../src/test/resources/mtls/client.crt | 27 ++++ .../src/test/resources/mtls/client.key | 28 ++++ .../src/test/resources/mtls/invalid_cert.crt | 0 .../src/test/resources/mtls/server.crt | 27 ++++ .../src/test/resources/mtls/server.key | 28 ++++ .../sphinx/connector/base-arrow-flight.rst | 4 +- 11 files changed, 373 insertions(+), 9 deletions(-) create mode 100644 presto-base-arrow-flight/src/test/java/com/facebook/plugin/arrow/TestArrowFlightMtls.java create mode 100644 presto-base-arrow-flight/src/test/resources/mtls/ca.crt create mode 100644 presto-base-arrow-flight/src/test/resources/mtls/client.crt create mode 100644 presto-base-arrow-flight/src/test/resources/mtls/client.key create mode 100644 presto-base-arrow-flight/src/test/resources/mtls/invalid_cert.crt create mode 100644 presto-base-arrow-flight/src/test/resources/mtls/server.crt create mode 100644 presto-base-arrow-flight/src/test/resources/mtls/server.key diff --git a/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowErrorCode.java b/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowErrorCode.java index 6b217e4f56cdf..2da078e05e870 100644 --- a/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowErrorCode.java +++ b/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowErrorCode.java @@ -27,7 +27,9 @@ public enum ArrowErrorCode ARROW_INTERNAL_ERROR(1, INTERNAL_ERROR), ARROW_FLIGHT_CLIENT_ERROR(2, EXTERNAL), ARROW_FLIGHT_METADATA_ERROR(3, EXTERNAL), - ARROW_FLIGHT_TYPE_ERROR(4, EXTERNAL); + ARROW_FLIGHT_TYPE_ERROR(4, EXTERNAL), + ARROW_FLIGHT_INVALID_KEY_ERROR(5, INTERNAL_ERROR), + ARROW_FLIGHT_INVALID_CERT_ERROR(6, INTERNAL_ERROR); private final ErrorCode errorCode; diff --git a/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowFlightConfig.java b/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowFlightConfig.java index d01333860e878..cf1829cb0d263 100644 --- a/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowFlightConfig.java +++ b/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowFlightConfig.java @@ -14,12 +14,15 @@ package com.facebook.plugin.arrow; import com.facebook.airlift.configuration.Config; +import com.facebook.airlift.configuration.ConfigDescription; public class ArrowFlightConfig { private String server; private boolean verifyServer = true; private String flightServerSSLCertificate; + private String flightClientSSLCertificate; + private String flightClientSSLKey; private boolean arrowFlightServerSslEnabled; private Integer arrowFlightPort; @@ -82,4 +85,30 @@ public ArrowFlightConfig setArrowFlightServerSslEnabled(boolean arrowFlightServe this.arrowFlightServerSslEnabled = arrowFlightServerSslEnabled; return this; } + + public String getFlightClientSSLCertificate() + { + return flightClientSSLCertificate; + } + + @ConfigDescription("Path to the client SSL certificate used for mTLS authentication with Flight server") + @Config("arrow-flight.client-ssl-certificate") + public ArrowFlightConfig setFlightClientSSLCertificate(String flightClientSSLCertificate) + { + this.flightClientSSLCertificate = flightClientSSLCertificate; + return this; + } + + public String getFlightClientSSLKey() + { + return flightClientSSLKey; + } + + @ConfigDescription("Path to the client SSL key used for mTLS authentication with Flight server") + @Config("arrow-flight.client-ssl-key") + public ArrowFlightConfig setFlightClientSSLKey(String flightClientSSLKey) + { + this.flightClientSSLKey = flightClientSSLKey; + return this; + } } diff --git a/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/BaseArrowFlightClientHandler.java b/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/BaseArrowFlightClientHandler.java index 304bf4c953ff7..d559768fcd6c8 100644 --- a/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/BaseArrowFlightClientHandler.java +++ b/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/BaseArrowFlightClientHandler.java @@ -13,6 +13,7 @@ */ package com.facebook.plugin.arrow; +import com.facebook.airlift.log.Logger; import com.facebook.presto.spi.ConnectorSession; import com.facebook.presto.spi.SchemaTableName; import org.apache.arrow.flight.CallOption; @@ -30,11 +31,15 @@ import java.net.URISyntaxException; import java.nio.ByteBuffer; import java.nio.file.Paths; +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; import java.util.List; import java.util.Optional; import static com.facebook.plugin.arrow.ArrowErrorCode.ARROW_FLIGHT_CLIENT_ERROR; import static com.facebook.plugin.arrow.ArrowErrorCode.ARROW_FLIGHT_INFO_ERROR; +import static com.facebook.plugin.arrow.ArrowErrorCode.ARROW_FLIGHT_INVALID_CERT_ERROR; +import static com.facebook.plugin.arrow.ArrowErrorCode.ARROW_FLIGHT_INVALID_KEY_ERROR; import static com.facebook.plugin.arrow.ArrowErrorCode.ARROW_FLIGHT_METADATA_ERROR; import static java.nio.file.Files.newInputStream; import static java.util.Objects.requireNonNull; @@ -43,6 +48,7 @@ public abstract class BaseArrowFlightClientHandler { private final ArrowFlightConfig config; private final BufferAllocator allocator; + private static final Logger logger = Logger.get(BaseArrowFlightClientHandler.class); public BaseArrowFlightClientHandler(BufferAllocator allocator, ArrowFlightConfig config) { @@ -64,24 +70,60 @@ protected FlightClient createFlightClient() protected FlightClient createFlightClient(Location location) { + Optional trustedCertificate = Optional.empty(); + Optional clientCertificate = Optional.empty(); + Optional clientKey = Optional.empty(); try { - Optional trustedCertificate = Optional.empty(); FlightClient.Builder flightClientBuilder = FlightClient.builder(allocator, location); flightClientBuilder.verifyServer(config.getVerifyServer()); if (config.getFlightServerSSLCertificate() != null) { trustedCertificate = Optional.of(newInputStream(Paths.get(config.getFlightServerSSLCertificate()))); flightClientBuilder.trustedCertificates(trustedCertificate.get()).useTls(); } - - FlightClient flightClient = flightClientBuilder.build(); - if (trustedCertificate.isPresent()) { - trustedCertificate.get().close(); + if (config.getFlightClientSSLCertificate() != null && config.getFlightClientSSLKey() != null) { + clientCertificate = Optional.of(newInputStream(Paths.get(config.getFlightClientSSLCertificate()))); + clientKey = Optional.of(newInputStream(Paths.get(config.getFlightClientSSLKey()))); + flightClientBuilder.clientCertificate(clientCertificate.get(), clientKey.get()).useTls(); } - return flightClient; + return flightClientBuilder.build(); } catch (Exception e) { - throw new ArrowException(ARROW_FLIGHT_CLIENT_ERROR, "Error creating flight client: " + e.getMessage(), e); + if (e.getCause() instanceof InvalidKeyException) { + throw new ArrowException(ARROW_FLIGHT_INVALID_KEY_ERROR, "Error creating flight client, invalid key file: " + e.getMessage(), e); + } + else if (e.getCause() instanceof CertificateException) { + throw new ArrowException(ARROW_FLIGHT_INVALID_CERT_ERROR, "Error creating flight client, invalid certificate file: " + e.getMessage(), e); + } + else { + throw new ArrowException(ARROW_FLIGHT_CLIENT_ERROR, "Error creating flight client: " + e.getMessage(), e); + } + } + finally { + if (trustedCertificate.isPresent()) { + try { + trustedCertificate.get().close(); + } + catch (IOException e) { + logger.error("Error closing input stream for server certificate", e); + } + } + if (clientCertificate.isPresent()) { + try { + clientCertificate.get().close(); + } + catch (IOException e) { + logger.error("Error closing input stream for client certificate", e); + } + } + if (clientKey.isPresent()) { + try { + clientKey.get().close(); + } + catch (IOException e) { + logger.error("Error closing input stream for client key", e); + } + } } } diff --git a/presto-base-arrow-flight/src/test/java/com/facebook/plugin/arrow/TestArrowFlightMtls.java b/presto-base-arrow-flight/src/test/java/com/facebook/plugin/arrow/TestArrowFlightMtls.java new file mode 100644 index 0000000000000..169f08db4ddb6 --- /dev/null +++ b/presto-base-arrow-flight/src/test/java/com/facebook/plugin/arrow/TestArrowFlightMtls.java @@ -0,0 +1,146 @@ +/* + * Licensed 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 com.facebook.plugin.arrow; + +import com.facebook.airlift.log.Logger; +import com.facebook.plugin.arrow.testingServer.TestingArrowProducer; +import com.facebook.presto.testing.QueryRunner; +import com.facebook.presto.tests.AbstractTestQueryFramework; +import com.facebook.presto.tests.DistributedQueryRunner; +import com.google.common.collect.ImmutableMap; +import org.apache.arrow.flight.FlightServer; +import org.apache.arrow.flight.Location; +import org.apache.arrow.memory.RootAllocator; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.util.Map; +import java.util.Optional; + +import static com.facebook.plugin.arrow.testingConnector.TestingArrowFlightPlugin.ARROW_FLIGHT_CONNECTOR; + +public class TestArrowFlightMtls + extends AbstractTestQueryFramework +{ + private static final Logger logger = Logger.get(TestArrowFlightMtls.class); + private final int serverPort; + private RootAllocator allocator; + private FlightServer server; + private DistributedQueryRunner arrowFlightQueryRunner; + private static final String ARROW_FLIGHT_CATALOG_WITH_INVALID_CERT = "arrow_catalog_with_invalid_cert"; + private static final String ARROW_FLIGHT_CATALOG_WITH_NO_MTLS_CERTS = "arrow_catalog_with_no_mtls_certs"; + private static final String ARROW_FLIGHT_CATALOG_WITH_MTLS_CERTS = "arrow_catalog_with_mtls_certs"; + + public TestArrowFlightMtls() + throws IOException + { + this.serverPort = ArrowFlightQueryRunner.findUnusedPort(); + } + + @BeforeClass + private void setup() + throws Exception + { + arrowFlightQueryRunner = getDistributedQueryRunner(); + arrowFlightQueryRunner.createCatalog(ARROW_FLIGHT_CATALOG_WITH_INVALID_CERT, ARROW_FLIGHT_CONNECTOR, getInvalidCertCatalogProperties()); + arrowFlightQueryRunner.createCatalog(ARROW_FLIGHT_CATALOG_WITH_NO_MTLS_CERTS, ARROW_FLIGHT_CONNECTOR, getNoMtlsCatalogProperties()); + arrowFlightQueryRunner.createCatalog(ARROW_FLIGHT_CATALOG_WITH_MTLS_CERTS, ARROW_FLIGHT_CONNECTOR, getMtlsCatalogProperties()); + + File certChainFile = new File("src/test/resources/mtls/server.crt"); + File privateKeyFile = new File("src/test/resources/mtls/server.key"); + File caCertFile = new File("src/test/resources/mtls/ca.crt"); + + allocator = new RootAllocator(Long.MAX_VALUE); + + Location location = Location.forGrpcTls("localhost", serverPort); + server = FlightServer.builder(allocator, location, new TestingArrowProducer(allocator)) + .useTls(certChainFile, privateKeyFile) + .useMTlsClientVerification(caCertFile) + .build(); + + server.start(); + logger.info("Server listening on port %s", server.getPort()); + } + + @AfterClass(alwaysRun = true) + private void tearDown() + throws InterruptedException + { + arrowFlightQueryRunner.close(); + server.close(); + allocator.close(); + } + + @Override + protected QueryRunner createQueryRunner() + throws Exception + { + return ArrowFlightQueryRunner.createQueryRunner(serverPort, ImmutableMap.of(), ImmutableMap.of(), Optional.empty()); + } + + private Map getInvalidCertCatalogProperties() + { + ImmutableMap.Builder catalogProperties = ImmutableMap.builder() + .put("arrow-flight.server.port", String.valueOf(serverPort)) + .put("arrow-flight.server", "localhost") + .put("arrow-flight.server-ssl-enabled", "true") + .put("arrow-flight.server-ssl-certificate", "src/test/resources/mtls/server.crt") + .put("arrow-flight.client-ssl-certificate", "src/test/resources/mtls/invalid_cert.crt") + .put("arrow-flight.client-ssl-key", "src/test/resources/mtls/client.key"); + return catalogProperties.build(); + } + + private Map getNoMtlsCatalogProperties() + { + ImmutableMap.Builder catalogProperties = ImmutableMap.builder() + .put("arrow-flight.server.port", String.valueOf(serverPort)) + .put("arrow-flight.server", "localhost") + .put("arrow-flight.server-ssl-enabled", "true") + .put("arrow-flight.server-ssl-certificate", "src/test/resources/mtls/server.crt"); + return catalogProperties.build(); + } + + private Map getMtlsCatalogProperties() + { + ImmutableMap.Builder catalogProperties = ImmutableMap.builder() + .put("arrow-flight.server.port", String.valueOf(serverPort)) + .put("arrow-flight.server", "localhost") + .put("arrow-flight.server-ssl-enabled", "true") + .put("arrow-flight.server-ssl-certificate", "src/test/resources/mtls/server.crt") + .put("arrow-flight.client-ssl-certificate", "src/test/resources/mtls/client.crt") + .put("arrow-flight.client-ssl-key", "src/test/resources/mtls/client.key"); + return catalogProperties.build(); + } + + @Test + public void testMtlsInvalidCert() + { + assertQueryFails("SELECT COUNT(*) FROM " + ARROW_FLIGHT_CATALOG_WITH_INVALID_CERT + ".tpch.orders", ".*invalid certificate file.*"); + } + + @Test + public void testMtlsFailure() + { + assertQueryFails("SELECT COUNT(*) FROM " + ARROW_FLIGHT_CATALOG_WITH_NO_MTLS_CERTS + ".tpch.orders", "ssl exception"); + } + + @Test + public void testMtls() + { + assertQuery("SELECT COUNT(*) FROM " + ARROW_FLIGHT_CATALOG_WITH_MTLS_CERTS + ".tpch.orders", "SELECT COUNT(*) FROM orders"); + } +} diff --git a/presto-base-arrow-flight/src/test/resources/mtls/ca.crt b/presto-base-arrow-flight/src/test/resources/mtls/ca.crt new file mode 100644 index 0000000000000..3d3f516aa0148 --- /dev/null +++ b/presto-base-arrow-flight/src/test/resources/mtls/ca.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFozCCA4ugAwIBAgIUTnZhzGzxAzaTJ5DDQnmBp8jvBUMwDQYJKoZIhvcNAQEL +BQAwYDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5 +MQ4wDAYDVQQKDAVNeU9yZzEPMA0GA1UECwwGTXlVbml0MREwDwYDVQQDDAhNeVJv +b3RDQTAgFw0yNTA1MjIxNjA2MDNaGA8yMTI1MDQyODE2MDYwM1owYDELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5MQ4wDAYDVQQKDAVN +eU9yZzEPMA0GA1UECwwGTXlVbml0MREwDwYDVQQDDAhNeVJvb3RDQTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBALmNRxPZt9vvFvIQcdCM3xcAOiTepahR +zsK86AwzXbwcWwOw+rQP0iXiMGjP9wJy0C1hU+j7F+gu5+d5j3DK9/iTlIqByjN+ +gffsZDSBBZBozJxARBWKaEFKRKbhCmr+v92ZN1KMYhhwc5W3SRp6y3kvsWYM4/JE +pRzYUy0505g3p7PnpQzZZSSzV33+9fn5ggafVB9FSJqOuBKUBTITt+Rf1pNV2ZGC +f2X39KOIIRz2Hz1L6hdqeMQN9V5KQ7C6oPfl+ho97JHaZirtHr1XZJ6YQRy7Mldp +jOPj4MMKqi8m+HhyCSznIDNiMp0OACX3CZ5RmKRYfnunOuw+fvI28HyOXMgfWKa2 +o/2/YlAzNrD50hJPwQMTlKWJm2gY2n5x2FWT6/8aXeCnsJALK6Dj6Ax0wxkAFfIo +76REHlXX2fIiz0cciYwYtvwhjp5efqX22B7LDkhu7fJ42yUd6g3crbmGM8OOoXgL +w3MWx30FatTyDT8un2ZvVDJEADW3+WWtyrZWHFMVFrVnN7Di4MAuWsRIVtuO6PEV +6pPS55NBmvKzWAoYBmpH103GlIxvZ6CCTeKqFbcrI77smrIO5CLmzl5yjb/urmy4 +GLYHM+EPB5pJKQO8g6fyM369mhEjBxt/RJGv9E0Jw7KmnHn5V2qSn4Yi41dUp7Cp +pQVIaYlJGn65AgMBAAGjUzBRMB0GA1UdDgQWBBRjt9KoJO8CO/Cy/xTJztrbdUlv +9DAfBgNVHSMEGDAWgBRjt9KoJO8CO/Cy/xTJztrbdUlv9DAPBgNVHRMBAf8EBTAD +AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQApizBpSaZDYjBhOxD6+B5em18OIf5ZIjHk +iAhuppR+HaqyAHJgCO707dZVmFz9ECUZI9mvKcmj+h0Wh/mK4cSiDunFB9yUr67U +wV5F2/u/JAAq6VsbdrDiZPUwET8U9ai14LMEgPPF+Zif+wnopRav5lbiPoJVUjqr +wVoP2AHijIP46YCWwXqOTJMC79ccUMBZeDwF4bOquIADLmEnANp6fiMI+eE6OLFs +fDtjFqybRUZqzewv2lpzH2ZYEYk4bIk76TGkOYtrwJ+iQj77ZZFSBW5zkry/zaG3 +/5Ufjv65T9Zr1jmIMigcmCHwNsCLOYzIKjRaiuLGs4B9s8SGEauTRhP0dG5ndWPw +50NeSNJr37MHdKky44WAFlAk9BAKlghOaC5m2RyMof8DwYKPEe5epe1wBotiPqSX +doaZvch6wkuo8xvFKqH6rBTWJLMwuFt7m3XrGqGYlE+1gvuEfn7ZGzG00sl218mZ +MfsLqJfft92ARC1/qJvUFr5mM6SV4eQeTl1tAtv6Xfczr+3/iqc5gbeG25dXQclO +y1qIKthAoXFq6rAZ+bvfASiVV1OQS76nWSiYYS1dDPQJ/g4aawOkUYr9OjS5HNQ+ +rNAcLB+I0oaZQzZ85098qAVAJ76eFATb4ieDK6m0j6Fq5ddwrlYzxEEr7TscfHW2 +zPCtinUe0w== +-----END CERTIFICATE----- diff --git a/presto-base-arrow-flight/src/test/resources/mtls/client.crt b/presto-base-arrow-flight/src/test/resources/mtls/client.crt new file mode 100644 index 0000000000000..0e2bc9ff7f662 --- /dev/null +++ b/presto-base-arrow-flight/src/test/resources/mtls/client.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEkDCCAnigAwIBAgIUUIByH9V7DhUf5n3Qd7tPxpPixQYwDQYJKoZIhvcNAQEL +BQAwYDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5 +MQ4wDAYDVQQKDAVNeU9yZzEPMA0GA1UECwwGTXlVbml0MREwDwYDVQQDDAhNeVJv +b3RDQTAgFw0yNTA1MjIxNjA4MzFaGA8yMTI1MDQyODE2MDgzMVowXjELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5MQ4wDAYDVQQKDAVN +eU9yZzEPMA0GA1UECwwGTXlVbml0MQ8wDQYDVQQDDAZjbGllbnQwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8DK/RdBF6I+k+DMGrjhMMBCnpPNwJtzJU +uXYcHFYEdBnHY/rpjk/fi+7jD8bppynCZPakrDX+5VIMzS4HBU/CHY26eR2ItiWq +DoDkPAlCdgeKIGNYYEvVSuUW5YQX6fuD8PfCpCP5zK7DJC2xTTsyEjBzD+MnIB7T +ja9/22Djo2Ib2l9BEBOD+k79caPFtSqDQVdS5JLJ/P7BeqGuFS8bEgtLwwCzRxPK +kG64rXb9F0IErGwjXi/70BA24EW0uGAzzeY5Pnlx5MulEIjuxII/dTuoo+/uirN0 +wxURKSzTMyzzoJqGX9Ng9+Z+VqWFrnqckcmFcD4T0sPoHpWZsYIHAgMBAAGjQjBA +MB0GA1UdDgQWBBRW/6j5rNwnwTBAXY5igXm3ETzv/DAfBgNVHSMEGDAWgBRjt9Ko +JO8CO/Cy/xTJztrbdUlv9DANBgkqhkiG9w0BAQsFAAOCAgEAVLpfZDgkL1Dz/+Fq +vSl2IoxOFNd2DTa6yM8/1wpvMVTA024lp0ttyoz0o1621hTRexcXTimZqUNAtPV6 +Gwmb2ACLN4XtLk9QT9XjDtWKzPxCJ+ze7rrhj1jYqv9yUebdkJoMKfcbwYi0gtpt +HlaJqNoKgzZxOCGhTtdS3ypb9nDCyx3fmFk5mIYfzEszoMmqNL006ANlJ0IKkFZj +vUkkFyMGLerInmTDRjDLkUCkNKaJUYjZhf/FNwVtc1A9a/bDJMEYVog+CY0dpXKb +1IGaXzB4ewhuQKuhb/LCZT1pNm/cGCY2cRGFy9EVAuZ5FV0ajh1HYwdpGDzucoUD +UaTHIK40E2/kZorJa37Xyn7Lekgun6YpfOudBkKg5mlV6qoL9W/lTZPjMHs2ufvW +/A5S4okR4JmhC44TMgAv90MU9yEP90OkzW6egatBShWySJ3Bn5W+ebQSwJ38wgTy +e6j5jWh7xiiPC4TJbSXVMGEfJw/c2hx4R/83MqBhVLPfoapaUCDUWniv6n7zl5ML +k7WIZzXSK212/H+eVXFJ1Gq6zztOPkN9QGgr+dbsCzdLWPJzZDmI7+lgT2EKxIV/ +VMtHVOe2bLkePTNA2+vXQhs0p7JDtzyATAyMdhJwPljt8X+HJxEoAP4Dk6PcK3Bd +E92yOuW2jl6FzgqKqtVQvxIiBgc= +-----END CERTIFICATE----- diff --git a/presto-base-arrow-flight/src/test/resources/mtls/client.key b/presto-base-arrow-flight/src/test/resources/mtls/client.key new file mode 100644 index 0000000000000..72434bc294aff --- /dev/null +++ b/presto-base-arrow-flight/src/test/resources/mtls/client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC8DK/RdBF6I+k+ +DMGrjhMMBCnpPNwJtzJUuXYcHFYEdBnHY/rpjk/fi+7jD8bppynCZPakrDX+5VIM +zS4HBU/CHY26eR2ItiWqDoDkPAlCdgeKIGNYYEvVSuUW5YQX6fuD8PfCpCP5zK7D +JC2xTTsyEjBzD+MnIB7Tja9/22Djo2Ib2l9BEBOD+k79caPFtSqDQVdS5JLJ/P7B +eqGuFS8bEgtLwwCzRxPKkG64rXb9F0IErGwjXi/70BA24EW0uGAzzeY5Pnlx5Mul +EIjuxII/dTuoo+/uirN0wxURKSzTMyzzoJqGX9Ng9+Z+VqWFrnqckcmFcD4T0sPo +HpWZsYIHAgMBAAECggEAViw6JXFa0O3D5HtUBJmGgOsniYoqCwm4NrsGNLuHb2ME +rSpTwNNGJtqpDcQdEtVXfY1muO9xjuznPJaJkQ4ODpYcbGcz8YIGoHck+XHJjHsp +2VIeNFFsbsFzWZqzfYHrj/rMjpVJJx90tlfN2IHbroZHTXLqVPOTLL6wvZZ6P9XF +zqpWABKOaEDbenhSFFZeF5KR3NG9HSTm4YLuekumkH+QgrveDfDwXG4hAHqg836o +OF3NPaij6VlSR18nuyW0wMs/Ceu13P+GALqHmz98pFyVgHWQFryL9IccvJQDyEnt +saeG4IAVlJbZDGTnRgANLhpwBr7XhMG1aK+wmOMRgQKBgQDkcatiATlr9L8gfnHb +6pmX//AZLdXuQLXfuTvu638Brhm770noLgfIC+HIp5kCHxT2Xj5Vn+MSnYD6R6Wh +chApRKJUdsuz1iOq23YJjvsSLWCGpl9IxR7WY27uGOPIjQcOd1PRbkCq9AgUJwyn +ryca3sbYh/XQOWGLbJNIQs/S/QKBgQDSu6PVeMaS3276KblvGIvvaSAQDQWxXcC+ +sA4CBmvjzx3xx5GAox/w7tcKmK/KQxNhaYy6N7xLc1YUJ9FbnT2PZQJhtP2d2Gat +Zre/+Qa+u84cR5hj9EI+B8FjW7D/psEj16KjHCds/SET6ngPM+RdB4N9daVFCurt +p0f717yiUwKBgBTJDun06I+dDkLbnmp/FwiQff0cgYmTE7lOdliPzteNSsQhypy4 +i3a1Ng72yOI7h8G+43cQ/C02bYTYPgbJhRTsLMT4piIvysECBORrwQZvYIf/3U2W +ue6Rz4cUdq1Jv6meS98TZAjp+U40G1+qfSlhub/75u7SOcDg2SnLAnPVAoGBAIOO +EmRE5qpwA+b2P0Ykq89E8Hg0uPYWEiq427XV7mqkNQxoSuRkcZ9Ga0a5NRzurN2m +N+1UuB7eHMGubdtkmTa4lzkJ9T4iB09/DX0x6E0QD0bGR1M2/FefHdJ6PlAK+Q34 +Ixbyj4ZRq+G0AUl0Wr7c3vBmjktA2pKMWLrW3nLzAoGBAKTl7qX6CD42gAJuT5Hp +rrXqlppVIyRvuXzXtX/Xq81IUHlBgS/t9HPyqDzmTKfxD8540kI+15bWPDHSJxiQ +ccqPaKyXhBXstDwGmlPKVzJUxk0dz5NHs+8gItUDOg78pM3siXN7vW9XBCH7mCDA +4zet/C0YCAiFVT+ipMoXy8Nc +-----END PRIVATE KEY----- diff --git a/presto-base-arrow-flight/src/test/resources/mtls/invalid_cert.crt b/presto-base-arrow-flight/src/test/resources/mtls/invalid_cert.crt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/presto-base-arrow-flight/src/test/resources/mtls/server.crt b/presto-base-arrow-flight/src/test/resources/mtls/server.crt new file mode 100644 index 0000000000000..8fb80c1bba51d --- /dev/null +++ b/presto-base-arrow-flight/src/test/resources/mtls/server.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEkzCCAnugAwIBAgIUUIByH9V7DhUf5n3Qd7tPxpPixQgwDQYJKoZIhvcNAQEL +BQAwYDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5 +MQ4wDAYDVQQKDAVNeU9yZzEPMA0GA1UECwwGTXlVbml0MREwDwYDVQQDDAhNeVJv +b3RDQTAgFw0yNTA1MjMwMTQzNTBaGA8yMTI1MDQyOTAxNDM1MFowYTELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5MQ4wDAYDVQQKDAVN +eU9yZzEPMA0GA1UECwwGTXlVbml0MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtkJ+r1F8+YOVuwWLxbGVsJKw3BESh +tCsU+IXHJeaNJdBr59B/4h5WM37wOnnecmyEZTh47FXXkb5h0xVlHES7eTAD+NPl +WHufGJ9PR1kvQyZ0fyNRFXLzUID/dl7atHBtlrqE5Bhg7xqAyPZjUjhkAZPgrT1/ +8+gYmbWPbw3Ba3+XRupq3Kn+EVVJi7wk4cj8jf6g1aex6sMOkSYNsanb+JdEryev +goju+EtHgCHL6cB0eJs8PfMWiibgWLE2pkI0bdbGjTNVDDygZoO8Qr/YrGvXXYqt +0D7IKSUiO8bnrvZh6ITPEcQ3ePQRGEpqh8ggKaVq3RVkC3t3QMRWGpsvAgMBAAGj +QjBAMB0GA1UdDgQWBBRf0XdDhjNSIZQsvSFbe+hdsydllzAfBgNVHSMEGDAWgBRj +t9KoJO8CO/Cy/xTJztrbdUlv9DANBgkqhkiG9w0BAQsFAAOCAgEAec7y1Odyg3x/ +Uj0jfZWYNE0BuR114UVwEYhxFi9tRAGxjTlsl6ATCSYBWU+fwUkC29C2r3bu59fp +/KvYPRrwGPyOtXwHR2cmwJ7QrUhlIwPipWO4Kal3/EKWvrV9rzdnOd2QYqEMS6f0 +UixGLcT5p5KmEsH3W8Y9Uk94g/z12ZgdGeKKyY7hWnu1d47b2TS4oiRx+d6AacAD +1BzJRUhDjS2Vfe2cnpOqBHJWyCT1BxsfxKAc3rLa6JznbulHQPCE5WWBolHb8Tob +Yf32sIJydOcWU+zJ9VsGuglQ8dQInMemW8k5y48ACqHb00lAoucGJ3Izy9tJiBeU +C8TcmRxQSjoMGhFGNIjBAvXak0UzobUKE3YyABBbUdWLofs0N325K1aSga4vXmlO +OPzP4FWMLZyDicVMUGLP9jcyeb/gFMzjoU2En59gRNVDNNo01Lyj9MhGHF/jvV7p +Zf782GvXMT/NSPtXqmABSV/Svy70vXogeQxTii9YOZePKWQnFhcEwin/7d9bf4d/ +nUqtzDFb5FiDeFA+H9FyeNaeub3OtvsZUacAVDCT1t9/8uShjJo34v8WbJegepcY +Tpdkm4x0DWvv/QT3JBqC0wprsmBVzuqTJ/jBxYye02bds1bM7xePAuVOwuSb6Azg +gLrweiDMakgmZSkGgUonnjblYbHGTHw= +-----END CERTIFICATE----- diff --git a/presto-base-arrow-flight/src/test/resources/mtls/server.key b/presto-base-arrow-flight/src/test/resources/mtls/server.key new file mode 100644 index 0000000000000..0e49bebd60beb --- /dev/null +++ b/presto-base-arrow-flight/src/test/resources/mtls/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCtkJ+r1F8+YOVu +wWLxbGVsJKw3BEShtCsU+IXHJeaNJdBr59B/4h5WM37wOnnecmyEZTh47FXXkb5h +0xVlHES7eTAD+NPlWHufGJ9PR1kvQyZ0fyNRFXLzUID/dl7atHBtlrqE5Bhg7xqA +yPZjUjhkAZPgrT1/8+gYmbWPbw3Ba3+XRupq3Kn+EVVJi7wk4cj8jf6g1aex6sMO +kSYNsanb+JdEryevgoju+EtHgCHL6cB0eJs8PfMWiibgWLE2pkI0bdbGjTNVDDyg +ZoO8Qr/YrGvXXYqt0D7IKSUiO8bnrvZh6ITPEcQ3ePQRGEpqh8ggKaVq3RVkC3t3 +QMRWGpsvAgMBAAECggEAIK9C+lNAallJ62z8inU8tjxDuAqUOBVbJZRVcPbIr1zn +HmLlpyd4Sghhh7CjYYoPuHDtTQxIcBNwlDBxb3x+zwUXzy+tC5v5j7DN01qex2Ew +XTDSAEN3Ra2r1S+/1hSztVd0oXDozFxKk+UETRjfKKoJZH6LPcy7MOLFR5EEuJ8L +0kvGdEtuNCmZ1vPBwqR3IKQS9NsB1IdTtK0g2LdtVzM3U6F173CrAx51qNeAL30j +Np+I0rfm7vYVco6nDQXJB86hzwwBnLMzmZR2E0z+JStQCjQtEJN9wp+NBnViMb8C +mZl0K/PH3ZKNEs1Aw/TsRpPu6Fc+sN6iIs2oOGiKfQKBgQDa0Wpfj+SHflLfmrRU +PplGNjWdJiyuXROqX18iNE8nAD0eRqAFdzj9yU1IW49KCzuHInEl2pP9yrDZTWXB +Bht4C+Vk13mrBE3Sc1LDrks5EhDLaaolLgx1B+JN1X2DpfuzO8WHrXR11PCzFTAp +yDSVd451CFFXMseS1V9UxCy3lQKBgQDLDrLX/0hGhG+a5RUaAE+hZk+tU9RyjYm6 +/5lIoDjDwA9Yst69JCTHDApkdZ6IrjPDZrxkAQR6QwsGo+zRGkHV2wCoqR/RxcT5 +RBcbe/8xL86ZKwnhAheP6ssgZeK5zOG1iLol319kXXuo6NueN+YlocmsppRvAOq7 +/qMnhzXGswKBgQCpke2wHo9HnNJWK8ohGt2mtm232ZR4jvKlbgEIPac1Hw89/hcW +BT0qFqyILUQOakP4Re2PGyLiYwfHbh4zhisVTYq4Ke9EYzJ3qxzxPYlXsbNIHxtW +cqf+rVxnWtFIiwFR9TjvGrEMezcIYJwRVO/DAIJqGUcHnvdfx3B3/Qp2PQKBgQCk +y7UR37kEog8BotHRXFdEIgigHtzYa05QWYhJjN8E3yaVUfW7g03lzTvR9DNJsjeI +aiSS9NBxeV/Fb9yOh8TOjwKl3zxXvy3xLvWh9KxTev0tCeTmnBALWP6puIadTE4S +Snjoq7R7e/MUToeOjMdX20oVuMvWmuPm1u4K8o0OSQKBgQCec+QLllYXk22A8/e/ +f5HhSYr161lEFFmuzKhuuy+esyCQU/KZmxQH0UqnsL3Ww4ofq42lteqyUJnriHsx +QP5FTIMKH8W+Xels1i6jCC+MVXAXraAF27dOlmKxWMN7mnElZ/7lQKmBq64wil35 +sfcJA4FDxVM2Amv4KRo/w1C/zQ== +-----END PRIVATE KEY----- diff --git a/presto-docs/src/main/sphinx/connector/base-arrow-flight.rst b/presto-docs/src/main/sphinx/connector/base-arrow-flight.rst index ba5d4bce9ebfd..e1676d3e05249 100644 --- a/presto-docs/src/main/sphinx/connector/base-arrow-flight.rst +++ b/presto-docs/src/main/sphinx/connector/base-arrow-flight.rst @@ -52,7 +52,9 @@ Property Name Description ========================================== ============================================================== ``arrow-flight.server`` Endpoint of the Flight server ``arrow-flight.server.port`` Flight server port -``arrow-flight.server-ssl-certificate`` Pass ssl certificate +``arrow-flight.server-ssl-certificate`` Path to SSL certificate of Flight server +``arrow-flight.client-ssl-certificate`` Path to SSL certificate that Flight clients will use for mTLS authentication with the Flight server +``arrow-flight.client-ssl-key`` Path to SSL key that Flight clients will use for mTLS authentication with the Flight server ``arrow-flight.server.verify`` To verify server ``arrow-flight.server-ssl-enabled`` Port is ssl enabled ========================================== ==============================================================