diff --git a/presto-docs/src/main/sphinx/connector/druid.rst b/presto-docs/src/main/sphinx/connector/druid.rst index c57927907d898..79d527e1edf4d 100644 --- a/presto-docs/src/main/sphinx/connector/druid.rst +++ b/presto-docs/src/main/sphinx/connector/druid.rst @@ -32,9 +32,9 @@ Configuration Properties The following configuration properties are available: -================================== =================================================== +================================== ============================================================ Property Name Description -================================== =================================================== +================================== ============================================================ ``druid.coordinator-url`` Druid coordinator url. ``druid.broker-url`` Druid broker url. ``druid.schema-name`` Druid schema name. @@ -43,7 +43,10 @@ Property Name Description table, and column names for the connector. When disabled, names are matched case-insensitively using lowercase normalization. Default is ``false``. -================================== =================================================== +``druid.tls.enabled`` Enable TLS when connecting to Druid. +``druid.tls.truststore-path`` Path to the trust certificate file. +``druid.tls.truststore-password`` Password for the trust certificate file. +================================== ============================================================ ``druid.coordinator-url`` ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,6 +72,23 @@ Whether to pushdown all query processing to Druid. the default is ``false``. +``druid.tls.enabled`` +^^^^^^^^^^^^^^^^^^^^^ + +Enable TLS when connecting to Druid. + +The default is ``false``. + +``druid.tls.truststore-path`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Path to the trust certificate file. + +``druid.tls.truststore-password`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Password for the trust certificate file. + Data Types ---------- diff --git a/presto-druid/src/main/java/com/facebook/presto/druid/DruidConfig.java b/presto-druid/src/main/java/com/facebook/presto/druid/DruidConfig.java index 05c5af91e1b13..886c182c7e3df 100644 --- a/presto-druid/src/main/java/com/facebook/presto/druid/DruidConfig.java +++ b/presto-druid/src/main/java/com/facebook/presto/druid/DruidConfig.java @@ -15,6 +15,7 @@ import com.facebook.airlift.configuration.Config; import com.facebook.airlift.configuration.ConfigDescription; +import com.facebook.airlift.configuration.ConfigSecuritySensitive; import com.facebook.airlift.configuration.LegacyConfig; import com.google.common.base.Splitter; import com.google.common.base.StandardSystemProperty; @@ -41,6 +42,10 @@ public class DruidConfig private String ingestionStoragePath = StandardSystemProperty.JAVA_IO_TMPDIR.value(); private boolean caseSensitiveNameMatchingEnabled; + private boolean tlsEnabled; + private String trustStorePath; + private String trustStorePassword; + public enum DruidAuthenticationType { NONE, @@ -211,4 +216,41 @@ public DruidConfig setCaseSensitiveNameMatchingEnabled(boolean caseSensitiveName this.caseSensitiveNameMatchingEnabled = caseSensitiveNameMatchingEnabled; return this; } + + public boolean isTlsEnabled() + { + return tlsEnabled; + } + + @Config("druid.tls.enabled") + public DruidConfig setTlsEnabled(boolean tlsEnabled) + { + this.tlsEnabled = tlsEnabled; + return this; + } + + public String getTrustStorePath() + { + return trustStorePath; + } + + @Config("druid.tls.truststore-path") + public DruidConfig setTrustStorePath(String path) + { + this.trustStorePath = path; + return this; + } + + public String getTrustStorePassword() + { + return trustStorePassword; + } + + @Config("druid.tls.truststore-password") + @ConfigSecuritySensitive + public DruidConfig setTrustStorePassword(String password) + { + this.trustStorePassword = password; + return this; + } } diff --git a/presto-druid/src/main/java/com/facebook/presto/druid/authentication/DruidAuthenticationModule.java b/presto-druid/src/main/java/com/facebook/presto/druid/authentication/DruidAuthenticationModule.java index 7bb42ac8e7a01..747d22befb97d 100644 --- a/presto-druid/src/main/java/com/facebook/presto/druid/authentication/DruidAuthenticationModule.java +++ b/presto-druid/src/main/java/com/facebook/presto/druid/authentication/DruidAuthenticationModule.java @@ -14,6 +14,7 @@ package com.facebook.presto.druid.authentication; import com.facebook.airlift.configuration.AbstractConfigurationAwareModule; +import com.facebook.airlift.http.client.HttpClientConfig; import com.facebook.presto.druid.DruidConfig; import com.facebook.presto.druid.ForDruidClient; import com.google.inject.Binder; @@ -26,6 +27,7 @@ import static com.facebook.presto.druid.DruidConfig.DruidAuthenticationType.BASIC; import static com.facebook.presto.druid.DruidConfig.DruidAuthenticationType.KERBEROS; import static com.facebook.presto.druid.DruidConfig.DruidAuthenticationType.NONE; +import static java.util.Objects.requireNonNull; public class DruidAuthenticationModule extends AbstractConfigurationAwareModule @@ -33,17 +35,19 @@ public class DruidAuthenticationModule @Override protected void setup(Binder binder) { + DruidConfig druidConfig = buildConfigObject(DruidConfig.class); + bindAuthenticationModule( config -> config.getDruidAuthenticationType() == NONE, - noneAuthenticationModule()); + noneAuthenticationModule(druidConfig)); bindAuthenticationModule( config -> config.getDruidAuthenticationType() == BASIC, - basicAuthenticationModule()); + basicAuthenticationModule(druidConfig)); bindAuthenticationModule( config -> config.getDruidAuthenticationType() == KERBEROS, - kerberosbAuthenticationModule()); + kerberosbAuthenticationModule(druidConfig)); } private void bindAuthenticationModule(Predicate predicate, Module module) @@ -51,24 +55,40 @@ private void bindAuthenticationModule(Predicate predicate, Module m install(installModuleIf(DruidConfig.class, predicate, module)); } - private static Module noneAuthenticationModule() + private static Module noneAuthenticationModule(DruidConfig druidConfig) { - return binder -> httpClientBinder(binder).bindHttpClient("druid-client", ForDruidClient.class); + return binder -> httpClientBinder(binder).bindHttpClient("druid-client", ForDruidClient.class) + .withConfigDefaults(config -> applyTlsConfig(config, druidConfig)); } - private static Module basicAuthenticationModule() + private static Module basicAuthenticationModule(DruidConfig druidConfig) { return binder -> httpClientBinder(binder).bindHttpClient("druid-client", ForDruidClient.class) .withConfigDefaults( - config -> config.setAuthenticationEnabled(false) //disable Kerberos auth + config -> { + config.setAuthenticationEnabled(false); //disable Kerberos auth + applyTlsConfig(config, druidConfig); + } ).withFilter( DruidBasicAuthHttpRequestFilter.class); } - private static Module kerberosbAuthenticationModule() + private static Module kerberosbAuthenticationModule(DruidConfig druidConfig) { return binder -> httpClientBinder(binder).bindHttpClient("druid-client", ForDruidClient.class) .withConfigDefaults( - config -> config.setAuthenticationEnabled(true)); + config -> { + config.setAuthenticationEnabled(true); + applyTlsConfig(config, druidConfig); + }); + } + + private static void applyTlsConfig(HttpClientConfig config, DruidConfig druidConfig) + { + if (druidConfig.isTlsEnabled()) { + requireNonNull(druidConfig.getTrustStorePath(), "druid.tls.truststore-path is null"); + config.setTrustStorePath(druidConfig.getTrustStorePath()); + config.setTrustStorePassword(druidConfig.getTrustStorePassword()); // Not adding null check for truststore password as it can be null for self-signed certs + } } } diff --git a/presto-druid/src/test/java/com/facebook/presto/druid/TestDruidConfig.java b/presto-druid/src/test/java/com/facebook/presto/druid/TestDruidConfig.java index 96dfba6e26f3b..aedbfcaeb1819 100644 --- a/presto-druid/src/test/java/com/facebook/presto/druid/TestDruidConfig.java +++ b/presto-druid/src/test/java/com/facebook/presto/druid/TestDruidConfig.java @@ -41,15 +41,18 @@ public void testDefaults() .setBasicAuthenticationUsername(null) .setBasicAuthenticationPassword(null) .setIngestionStoragePath(StandardSystemProperty.JAVA_IO_TMPDIR.value()) - .setCaseSensitiveNameMatchingEnabled(false)); + .setCaseSensitiveNameMatchingEnabled(false) + .setTlsEnabled(false) + .setTrustStorePath(null) + .setTrustStorePassword(null)); } @Test public void testExplicitPropertyMappings() { Map properties = new ImmutableMap.Builder() - .put("druid.broker-url", "http://druid.broker:1234") - .put("druid.coordinator-url", "http://druid.coordinator:4321") + .put("druid.broker-url", "https://druid.broker:1234") + .put("druid.coordinator-url", "https://druid.coordinator:4321") .put("druid.schema-name", "test") .put("druid.compute-pushdown-enabled", "true") .put("druid.hadoop.config.resources", "/etc/core-site.xml,/etc/hdfs-site.xml") @@ -58,11 +61,14 @@ public void testExplicitPropertyMappings() .put("druid.basic.authentication.password", "http_basic_password") .put("druid.ingestion.storage.path", "hdfs://foo/bar/") .put("case-sensitive-name-matching", "true") + .put("druid.tls.enabled", "true") + .put("druid.tls.truststore-path", "/tmp/truststore") + .put("druid.tls.truststore-password", "truststore-password") .build(); DruidConfig expected = new DruidConfig() - .setDruidBrokerUrl("http://druid.broker:1234") - .setDruidCoordinatorUrl("http://druid.coordinator:4321") + .setDruidBrokerUrl("https://druid.broker:1234") + .setDruidCoordinatorUrl("https://druid.coordinator:4321") .setDruidSchema("test") .setComputePushdownEnabled(true) .setHadoopConfiguration(ImmutableList.of("/etc/core-site.xml", "/etc/hdfs-site.xml")) @@ -70,7 +76,10 @@ public void testExplicitPropertyMappings() .setBasicAuthenticationUsername("http_basic_username") .setBasicAuthenticationPassword("http_basic_password") .setIngestionStoragePath("hdfs://foo/bar/") - .setCaseSensitiveNameMatchingEnabled(true); + .setCaseSensitiveNameMatchingEnabled(true) + .setTlsEnabled(true) + .setTrustStorePath(("/tmp/truststore")) + .setTrustStorePassword("truststore-password"); ConfigAssertions.assertFullMapping(properties, expected); }