From fde8c8b56270d8ba74f66dc188b0ae9f4fb8201a Mon Sep 17 00:00:00 2001 From: cgivre Date: Sun, 24 Aug 2025 11:01:47 -0400 Subject: [PATCH 01/22] Exclude old Maven Libraries from Tools --- tools/fmpp/pom.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/fmpp/pom.xml b/tools/fmpp/pom.xml index eb2b3bb5cb9..5858241351a 100644 --- a/tools/fmpp/pom.xml +++ b/tools/fmpp/pom.xml @@ -66,10 +66,18 @@ commons-logging-api commons-logging + + org.apache.maven + maven-compat + bsh org.beanshell + + maven-plugin-api + org.apache.maven + From a5bf37343fa8dc4a4a7f1195cb39d05c96db2326 Mon Sep 17 00:00:00 2001 From: cgivre Date: Sun, 24 Aug 2025 11:33:48 -0400 Subject: [PATCH 02/22] One more --- tools/fmpp/pom.xml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/fmpp/pom.xml b/tools/fmpp/pom.xml index 5858241351a..6b44979b4bb 100644 --- a/tools/fmpp/pom.xml +++ b/tools/fmpp/pom.xml @@ -66,10 +66,6 @@ commons-logging-api commons-logging - - org.apache.maven - maven-compat - bsh org.beanshell @@ -78,6 +74,14 @@ maven-plugin-api org.apache.maven + + maven-compat + org.apache.maven + + + maven-model + org.apache.maven + From f59838bf5f5592ac7c094271d3a1c7b7d45234e7 Mon Sep 17 00:00:00 2001 From: cgivre Date: Sun, 24 Aug 2025 12:31:18 -0400 Subject: [PATCH 03/22] Bump parquet to version 1.15.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e8ece2041d3..9eef0ec065a 100644 --- a/pom.xml +++ b/pom.xml @@ -128,7 +128,7 @@ 2.0.65.Final 4.1.118.Final 2.11.0 - 1.15.1 + 1.15.2 1750144553 3.25.5 ${project.basedir}/src/main/protobuf/ From 089693a853fce682dda9c19a6531ae4ed28882f4 Mon Sep 17 00:00:00 2001 From: cgivre Date: Sun, 24 Aug 2025 13:00:32 -0400 Subject: [PATCH 04/22] Bump zookeeper to 3.7.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9eef0ec065a..d5fbf138b12 100644 --- a/pom.xml +++ b/pom.xml @@ -148,7 +148,7 @@ 2.23.2 2.12.2 7.31.0 - 3.5.10 + 3.7.2 From 15c88458523b3a1c26a710430e37a8af5229fd1b Mon Sep 17 00:00:00 2001 From: cgivre Date: Sun, 24 Aug 2025 17:13:54 -0400 Subject: [PATCH 05/22] Update Phoenix POM --- contrib/storage-phoenix/pom.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/contrib/storage-phoenix/pom.xml b/contrib/storage-phoenix/pom.xml index aad0fac4763..035e52133c3 100644 --- a/contrib/storage-phoenix/pom.xml +++ b/contrib/storage-phoenix/pom.xml @@ -118,6 +118,10 @@ org.jboss.netty netty + + org.apache.zookeeper + zookeeper-jute + @@ -342,6 +346,16 @@ + + org.apache.zookeeper + zookeeper + ${zookeeper.version} + + + org.apache.zookeeper + zookeeper-jute + ${zookeeper.version} + From 4558702edb2ce3b899ba6df1676f997ce39732b3 Mon Sep 17 00:00:00 2001 From: cgivre Date: Sun, 24 Aug 2025 17:23:04 -0400 Subject: [PATCH 06/22] Fixed version drift in Phoenix Plugin --- contrib/storage-phoenix/pom.xml | 43 ++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/contrib/storage-phoenix/pom.xml b/contrib/storage-phoenix/pom.xml index 035e52133c3..7cf9b5faa18 100644 --- a/contrib/storage-phoenix/pom.xml +++ b/contrib/storage-phoenix/pom.xml @@ -32,6 +32,7 @@ 5.1.3 2.4.17 + 4.1.4 false @@ -202,7 +203,7 @@ org.apache.phoenix - phoenix-hbase-compat-2.4.0 + phoenix-hbase-compat-2.4.1 ${phoenix.version} test @@ -277,6 +278,46 @@ + + org.apache.hbase + hbase-client + ${hbase.minicluster.version} + + + org.apache.hbase + hbase-server + ${hbase.minicluster.version} + + + org.apache.hbase + hbase-common + ${hbase.minicluster.version} + + + org.apache.hbase + hbase-zookeeper + ${hbase.minicluster.version} + + + org.apache.hbase + hbase-protocol + ${hbase.minicluster.version} + + + org.apache.hbase.thirdparty + hbase-shaded-protobuf + ${hbase.shaded.version} + + + org.apache.hbase.thirdparty + hbase-shaded-miscellaneous + ${hbase.shaded.version} + + + org.apache.hbase.thirdparty + hbase-shaded-netty + ${hbase.shaded.version} + org.apache.hadoop hadoop-hdfs-client From f4608cd03daf3ecf749bc8de6eaecedcc232a673 Mon Sep 17 00:00:00 2001 From: cgivre Date: Sun, 24 Aug 2025 17:29:01 -0400 Subject: [PATCH 07/22] Minor POM cleanup --- contrib/storage-phoenix/pom.xml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/contrib/storage-phoenix/pom.xml b/contrib/storage-phoenix/pom.xml index 7cf9b5faa18..c9927b86733 100644 --- a/contrib/storage-phoenix/pom.xml +++ b/contrib/storage-phoenix/pom.xml @@ -125,11 +125,6 @@ - - org.apache.phoenix - phoenix-hbase-compat-2.4.1 - ${phoenix.version} - org.apache.phoenix phoenix-core @@ -280,22 +275,22 @@ org.apache.hbase - hbase-client + hbase-common ${hbase.minicluster.version} org.apache.hbase - hbase-server + hbase-zookeeper ${hbase.minicluster.version} org.apache.hbase - hbase-common + hbase-metrics ${hbase.minicluster.version} org.apache.hbase - hbase-zookeeper + hbase-metrics-api ${hbase.minicluster.version} @@ -303,6 +298,16 @@ hbase-protocol ${hbase.minicluster.version} + + org.apache.hbase + hbase-hadoop2-compat + ${hbase.minicluster.version} + + + org.apache.hbase + hbase-mapreduce + ${hbase.minicluster.version} + org.apache.hbase.thirdparty hbase-shaded-protobuf From fca71cc39b77e87b6ff5130221efb221657158ee Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 3 Jan 2025 08:23:25 +0100 Subject: [PATCH 08/22] [MINOR UPDATE] upgrade Phoenix to 5.2.1 --- contrib/storage-phoenix/pom.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/contrib/storage-phoenix/pom.xml b/contrib/storage-phoenix/pom.xml index c9927b86733..40b4c0bd742 100644 --- a/contrib/storage-phoenix/pom.xml +++ b/contrib/storage-phoenix/pom.xml @@ -29,10 +29,9 @@ Drill : Contrib : Storage : Phoenix - 5.1.3 - - 2.4.17 - 4.1.4 + 5.2.1 + + 2.5.10 false From 3b9be37ffa78781e013533e243f642fecc64e75e Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 3 Jan 2025 22:01:27 +0100 Subject: [PATCH 09/22] compile issue --- contrib/storage-phoenix/pom.xml | 12 ++++-------- .../exec/store/phoenix/PhoenixStoragePlugin.java | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/contrib/storage-phoenix/pom.xml b/contrib/storage-phoenix/pom.xml index 40b4c0bd742..82d2343fe0f 100644 --- a/contrib/storage-phoenix/pom.xml +++ b/contrib/storage-phoenix/pom.xml @@ -392,14 +392,10 @@ - org.apache.zookeeper - zookeeper - ${zookeeper.version} - - - org.apache.zookeeper - zookeeper-jute - ${zookeeper.version} + org.apiguardian + apiguardian-api + 1.1.2 + test diff --git a/contrib/storage-phoenix/src/main/java/org/apache/drill/exec/store/phoenix/PhoenixStoragePlugin.java b/contrib/storage-phoenix/src/main/java/org/apache/drill/exec/store/phoenix/PhoenixStoragePlugin.java index daf4e480fa7..de0b8514759 100644 --- a/contrib/storage-phoenix/src/main/java/org/apache/drill/exec/store/phoenix/PhoenixStoragePlugin.java +++ b/contrib/storage-phoenix/src/main/java/org/apache/drill/exec/store/phoenix/PhoenixStoragePlugin.java @@ -43,12 +43,12 @@ import org.apache.drill.exec.store.phoenix.rules.PhoenixConvention; import com.fasterxml.jackson.core.type.TypeReference; -import org.apache.drill.exec.util.ImpersonationUtil; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableSet; +import org.apache.drill.exec.util.ImpersonationUtil; import org.apache.hadoop.security.UserGroupInformation; -import org.apache.tephra.shaded.com.google.common.collect.ImmutableSet; public class PhoenixStoragePlugin extends AbstractStoragePlugin { From 02b59da87cd8c440b3ee8488880670a6b96325cc Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 3 Jan 2025 23:29:34 +0100 Subject: [PATCH 10/22] npe --- .../org/apache/drill/common/exceptions/UserExceptionUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/apache/drill/common/exceptions/UserExceptionUtils.java b/common/src/main/java/org/apache/drill/common/exceptions/UserExceptionUtils.java index 1d9fbff6f3b..15b6ec5f8a6 100644 --- a/common/src/main/java/org/apache/drill/common/exceptions/UserExceptionUtils.java +++ b/common/src/main/java/org/apache/drill/common/exceptions/UserExceptionUtils.java @@ -33,7 +33,8 @@ private static String decorateHint(final String text) { return String.format("[Hint: %s]", text); } public static String getUserHint(final Throwable ex) { - if (ex.getMessage().startsWith("Error getting user info for current user")) { + final String message = ex.getMessage(); + if (message != null && message.startsWith("Error getting user info for current user")) { //User does not exist hint return decorateHint(USER_DOES_NOT_EXIST); } else { From 4960ac0dec1746db4857c8d85d2e45db3b52a67a Mon Sep 17 00:00:00 2001 From: cgivre Date: Sun, 24 Aug 2025 18:52:14 -0400 Subject: [PATCH 11/22] Update Zookeeper to 3.9.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d5fbf138b12..ab34d9f4de2 100644 --- a/pom.xml +++ b/pom.xml @@ -148,7 +148,7 @@ 2.23.2 2.12.2 7.31.0 - 3.7.2 + 3.9.3 From 03818a1d230893c7da352f68fe4f7aaebb546199 Mon Sep 17 00:00:00 2001 From: cgivre Date: Sun, 24 Aug 2025 21:32:56 -0400 Subject: [PATCH 12/22] Rollback ZK Upgrade to 3.8.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ab34d9f4de2..d6fc006f652 100644 --- a/pom.xml +++ b/pom.xml @@ -148,7 +148,7 @@ 2.23.2 2.12.2 7.31.0 - 3.9.3 + 3.8.2 From fda19c6b442fd41ab9122212f0a639405a05703d Mon Sep 17 00:00:00 2001 From: "Charles S. Givre" Date: Sun, 24 Aug 2025 22:59:49 -0400 Subject: [PATCH 13/22] Revert to Zookeeper 3.7.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d6fc006f652..d5fbf138b12 100644 --- a/pom.xml +++ b/pom.xml @@ -148,7 +148,7 @@ 2.23.2 2.12.2 7.31.0 - 3.8.2 + 3.7.2 From 5752ed92c0bcd2994d6a540babe71f38a10ddbb3 Mon Sep 17 00:00:00 2001 From: cgivre Date: Mon, 25 Aug 2025 12:21:37 -0400 Subject: [PATCH 14/22] Tests working from CLI --- contrib/storage-phoenix/pom.xml | 397 ++++-------------- .../exec/store/phoenix/PhoenixBaseTest.java | 28 +- .../exec/store/phoenix/PhoenixBasicsIT.java | 100 +++-- .../exec/store/phoenix/PhoenixTestSuite.java | 9 +- .../secured/SecuredPhoenixTestSuite.java | 3 +- 5 files changed, 161 insertions(+), 376 deletions(-) diff --git a/contrib/storage-phoenix/pom.xml b/contrib/storage-phoenix/pom.xml index 82d2343fe0f..fc2ec796337 100644 --- a/contrib/storage-phoenix/pom.xml +++ b/contrib/storage-phoenix/pom.xml @@ -1,41 +1,45 @@ - + 4.0.0 + org.apache.drill.contrib drill-contrib-parent 1.23.0-SNAPSHOT + drill-storage-phoenix Drill : Contrib : Storage : Phoenix 5.2.1 - - 2.5.10 + 2.6.3 + 4.1.5 false + org.apache.drill.exec drill-java-exec @@ -48,20 +52,25 @@ ${project.version} test + org.apache.drill drill-common - tests ${project.version} + tests test + + org.apache.phoenix phoenix-core ${phoenix.version} - test - tests + + com.google.protobuf + protobuf-java + org.slf4j * @@ -70,276 +79,100 @@ log4j log4j - - commons-logging - commons-logging - - - javax.servlet - * - - - org.ow2.asm - asm - - - org.ow2.asm - asm-all - - - commons-configuration - commons-configuration - - - org.apache.commons - commons-csv - - - org.apache.hbase - hbase-endpoint - - - com.salesforce.i18n - i18n-util - - - jline - jline - - - com.codahale.metrics - metrics-core - - - com.codahale.metrics - metrics-graphite - - - org.jboss.netty - netty - - - org.apache.zookeeper - zookeeper-jute - + org.apache.phoenix phoenix-core ${phoenix.version} + tests + test - org.slf4j - * - - - log4j - log4j - - - commons-logging - commons-logging - - - javax.servlet - * - - - org.ow2.asm - asm - - - org.ow2.asm - asm-all - - - commons-configuration - commons-configuration - - - org.apache.hbase - hbase-testing-util - - - org.apache.htrace - htrace-core - - - org.apache.commons - commons-csv - - - org.apache.hbase - hbase-endpoint - - - jline - jline - - - com.salesforce.i18n - i18n-util - - - com.codahale.metrics - metrics-core - - - com.codahale.metrics - metrics-graphite - - - org.jboss.netty - netty + com.google.protobuf + protobuf-java + + org.apache.phoenix - phoenix-hbase-compat-2.4.1 + phoenix-hbase-compat-2.6.0 ${phoenix.version} test - - - org.apache.kerby - kerb-core - ${kerby.version} - test - - - org.apache.hbase - hbase-it - ${hbase.minicluster.version} - tests - test - org.apache.hbase - hbase-endpoint + com.google.protobuf + protobuf-java + + org.apache.hbase - hbase-common - ${hbase.minicluster.version} - tests - test - - - org.apache.hbase - hbase-client - ${hbase.minicluster.version} - test - - - org.apache.hbase - hbase-server - ${hbase.minicluster.version} - test - - - org.apache.hbase - hbase-protocol-shaded - ${hbase.minicluster.version} - test - - - org.apache.hbase - hbase-hadoop-compat - ${hbase.minicluster.version} - test - - - org.apache.hbase - hbase-asyncfs - tests - ${hbase.minicluster.version} + hbase-testing-util + ${hbase.version} test - commons-logging - commons-logging + org.apache.hadoop + hadoop-minicluster - log4j - log4j + org.apache.hadoop + hadoop-minikdc - org.slf4j - * + org.apache.hadoop + hadoop-yarn-server-tests + org.apache.hbase - hbase-common - ${hbase.minicluster.version} - - - org.apache.hbase - hbase-zookeeper - ${hbase.minicluster.version} - - - org.apache.hbase - hbase-metrics - ${hbase.minicluster.version} - - - org.apache.hbase - hbase-metrics-api - ${hbase.minicluster.version} + hbase-server + ${hbase.version} + test org.apache.hbase - hbase-protocol - ${hbase.minicluster.version} + hbase-client + ${hbase.version} + test org.apache.hbase - hbase-hadoop2-compat - ${hbase.minicluster.version} + hbase-common + ${hbase.version} org.apache.hbase - hbase-mapreduce - ${hbase.minicluster.version} - - - org.apache.hbase.thirdparty - hbase-shaded-protobuf - ${hbase.shaded.version} + hbase-zookeeper + ${hbase.version} + + - org.apache.hbase.thirdparty - hbase-shaded-miscellaneous - ${hbase.shaded.version} + org.apache.zookeeper + zookeeper + ${zookeeper.version} - org.apache.hbase.thirdparty - hbase-shaded-netty - ${hbase.shaded.version} - - - org.apache.hadoop - hadoop-hdfs-client - ${hadoop.version} - - - commons-logging - commons-logging - - - test - + org.apache.zookeeper + zookeeper-jute + ${zookeeper.version} + org.apache.hadoop hadoop-minikdc ${hadoop.version} test + commons-logging @@ -349,16 +182,14 @@ log4j log4j - - org.slf4j - * - + + - org.apache.hbase - hbase-testing-util - ${hbase.minicluster.version} + org.apache.hadoop + hadoop-auth + ${hadoop.version} test @@ -369,88 +200,28 @@ log4j log4j - - org.slf4j - * - - - javax.servlet - servlet-api - - - io.netty - netty - - - com.zaxxer - HikariCP-java7 - - - org.apache.commons - commons-csv - - - org.apiguardian - apiguardian-api - 1.1.2 - test - + + + - - maven-resources-plugin - - - copy-java-sources - process-sources - - copy-resources - - - ${basedir}/target/classes/org/apache/drill/exec/store/phoenix - - - src/main/java/org/apache/drill/exec/store/phoenix - true - - - - - - org.apache.maven.plugins maven-surefire-plugin ${skipTests} - 1 + 1 false - - **/PhoenixTestSuite.class - **/SecuredPhoenixTestSuite.class - - - **/*Test.java - - -Xms2048m -Xmx2048m + + -Xms2048m -Xmx2048m + --add-opens=java.base/java.lang=ALL-UNNAMED + --add-opens=java.base/java.util=ALL-UNNAMED + - - - - jdk14+ - - [14,) - - - true - - - diff --git a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixBaseTest.java b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixBaseTest.java index 53b7adc7dd0..e04f39ab462 100644 --- a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixBaseTest.java +++ b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixBaseTest.java @@ -17,7 +17,18 @@ */ package org.apache.drill.exec.store.phoenix; -import static org.junit.Assert.assertFalse; +import com.google.common.collect.Maps; +import com.univocity.parsers.csv.CsvParser; +import com.univocity.parsers.csv.CsvParserSettings; +import org.apache.drill.exec.store.StoragePluginRegistry; +import org.apache.drill.test.ClusterFixture; +import org.apache.drill.test.ClusterFixtureBuilder; +import org.apache.drill.test.ClusterTest; +import org.apache.hadoop.fs.Path; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.FileInputStream; import java.io.InputStreamReader; @@ -37,22 +48,11 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.drill.exec.store.StoragePluginRegistry; -import com.google.common.collect.Maps; -import org.apache.drill.test.ClusterFixture; -import org.apache.drill.test.ClusterFixtureBuilder; -import org.apache.drill.test.ClusterTest; -import org.apache.hadoop.fs.Path; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.slf4j.LoggerFactory; - -import com.univocity.parsers.csv.CsvParser; -import com.univocity.parsers.csv.CsvParserSettings; +import static org.junit.Assert.assertFalse; public class PhoenixBaseTest extends ClusterTest { - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(PhoenixBaseTest.class); + private static final Logger logger = LoggerFactory.getLogger(PhoenixBaseTest.class); public final static String U_U_I_D = UUID.randomUUID().toString(); private final static AtomicInteger initCount = new AtomicInteger(0); diff --git a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixBasicsIT.java b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixBasicsIT.java index bb61e01632f..012c5c65e8e 100644 --- a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixBasicsIT.java +++ b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixBasicsIT.java @@ -7,80 +7,92 @@ * "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 + * 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. + * 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.drill.exec.store.phoenix; -import static org.apache.hadoop.hbase.HConstants.HBASE_DIR; -import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_CAT; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.phoenix.util.PhoenixRuntime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; -import java.util.Optional; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hbase.HBaseTestingUtility; -import org.apache.hadoop.hbase.HConstants; -import org.apache.hadoop.hbase.LocalHBaseCluster; -import org.apache.phoenix.util.PhoenixRuntime; -import org.slf4j.LoggerFactory; +import static org.apache.hadoop.hbase.HConstants.HBASE_DIR; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; -/** - * This is a copy of {@code org.apache.phoenix.end2end.QueryServerBasicsIT} until - * PHOENIX-6613 is fixed - */ public class PhoenixBasicsIT { private static final HBaseTestingUtility util = new HBaseTestingUtility(); - - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(PhoenixBasicsIT.class); + private static final Logger logger = LoggerFactory.getLogger(PhoenixBasicsIT.class); protected static String CONN_STRING; - static LocalHBaseCluster hbaseCluster; public static synchronized void doSetup() throws Exception { Configuration conf = util.getConfiguration(); - // Start ZK by hand - util.startMiniZKCluster(); + + // Keep it embedded & filesystem-only (no HDFS) + conf.set("hbase.cluster.distributed", "false"); + conf.setBoolean("hbase.unsafe.stream.capability.enforce", false); + conf.setInt("hbase.master.wait.on.regionservers.mintostart", 1); + + // Randomize service ports, disable HTTP/Jetty info servers to avoid Netty/servlet deps + conf.setInt("hbase.master.port", 0); + conf.setInt("hbase.master.info.port", -1); + conf.setInt("hbase.regionserver.port", 0); + conf.setInt("hbase.regionserver.info.port", -1); + conf.unset("hbase.http.filter.initializers"); // make sure no web filters get bootstrapped + + // Force loopback to dodge IPv6/hostname hiccups + conf.set("hbase.zookeeper.quorum", "127.0.0.1"); + conf.set("hbase.master.hostname", "127.0.0.1"); + conf.set("hbase.regionserver.hostname", "127.0.0.1"); + + // Root dir on local FS (file:///), so HTU won't start MiniDFS Path rootdir = util.getDataTestDirOnTestFS(PhoenixBasicsIT.class.getSimpleName()); - // There is no setRootdir method that is available in all supported HBase versions. - conf.set(HBASE_DIR, rootdir.toString()); - hbaseCluster = new LocalHBaseCluster(conf, 1); - hbaseCluster.startup(); + conf.set(HBASE_DIR, rootdir.toUri().toString()); // keep URI form - CONN_STRING = PhoenixRuntime.JDBC_PROTOCOL + ":localhost:" + getZookeeperPort(); - logger.info("JDBC connection string is " + CONN_STRING); - } + // Start ZK + 1 Master + 1 RegionServer WITHOUT HDFS + util.startMiniZKCluster(); + util.startMiniHBaseCluster(1, 1); - public static int getZookeeperPort() { - return util.getConfiguration().getInt(HConstants.ZOOKEEPER_CLIENT_PORT, 2181); + int zkPort = util.getZkCluster().getClientPort(); + CONN_STRING = PhoenixRuntime.JDBC_PROTOCOL + ":localhost:" + zkPort; + logger.info("JDBC connection string is {}", CONN_STRING); } public static void testCatalogs() throws Exception { - try (final Connection connection = DriverManager.getConnection(CONN_STRING)) { + try (Connection connection = DriverManager.getConnection(CONN_STRING)) { assertFalse(connection.isClosed()); - try (final ResultSet resultSet = connection.getMetaData().getCatalogs()) { - final ResultSetMetaData metaData = resultSet.getMetaData(); - assertFalse("unexpected populated resultSet", resultSet.next()); - assertEquals(1, metaData.getColumnCount()); - assertEquals(TABLE_CAT, metaData.getColumnName(1)); + try (ResultSet rs = connection.getMetaData().getCatalogs()) { + ResultSetMetaData md = rs.getMetaData(); + String col = md.getColumnLabel(1); // label is safer than name + if (!"TABLE_CAT".equals(col) && !"TENANT_ID".equals(col)) { + // fall back to name just in case some drivers differ + col = md.getColumnName(1); + } + assertTrue("Unexpected first column: " + col, + "TABLE_CAT".equals(col) || "TENANT_ID".equals(col)); } } } public static synchronized void afterClass() throws IOException { - Optional.of(hbaseCluster).ifPresent(LocalHBaseCluster::shutdown); - util.shutdownMiniCluster(); + util.shutdownMiniHBaseCluster(); // stops RS & Master + util.shutdownMiniZKCluster(); // stops ZK } } diff --git a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixTestSuite.java b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixTestSuite.java index 0e430904c22..3be298e2b76 100644 --- a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixTestSuite.java +++ b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/PhoenixTestSuite.java @@ -17,9 +17,6 @@ */ package org.apache.drill.exec.store.phoenix; -import java.util.TimeZone; -import java.util.concurrent.atomic.AtomicInteger; - import org.apache.drill.categories.SlowTest; import org.apache.drill.test.BaseTest; import org.junit.AfterClass; @@ -28,8 +25,12 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; +import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.TimeZone; +import java.util.concurrent.atomic.AtomicInteger; + @RunWith(Suite.class) @SuiteClasses ({ @@ -40,7 +41,7 @@ @Category({ SlowTest.class }) public class PhoenixTestSuite extends BaseTest { - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(PhoenixTestSuite.class); + private static final Logger logger = LoggerFactory.getLogger(PhoenixTestSuite.class); private static volatile boolean runningSuite = false; private static final AtomicInteger initCount = new AtomicInteger(0); diff --git a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixTestSuite.java b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixTestSuite.java index 89f1a999044..7631ea7dcb2 100644 --- a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixTestSuite.java +++ b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixTestSuite.java @@ -26,6 +26,7 @@ import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.Suite; +import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.TimeZone; @@ -41,7 +42,7 @@ @Category({ SlowTest.class, RowSetTest.class }) public class SecuredPhoenixTestSuite extends BaseTest { - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SecuredPhoenixTestSuite.class); + private static final Logger logger = LoggerFactory.getLogger(SecuredPhoenixTestSuite.class); private static volatile boolean runningSuite = false; private static final AtomicInteger initCount = new AtomicInteger(0); From c042983d9d70584e3be30a6090ad4d02c5cf9b55 Mon Sep 17 00:00:00 2001 From: cgivre Date: Mon, 25 Aug 2025 14:22:59 -0400 Subject: [PATCH 15/22] Try again with ZK 3.9.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d5fbf138b12..ab34d9f4de2 100644 --- a/pom.xml +++ b/pom.xml @@ -148,7 +148,7 @@ 2.23.2 2.12.2 7.31.0 - 3.7.2 + 3.9.3 From bdde40a28f218bce084eb137060aab3e59993d5b Mon Sep 17 00:00:00 2001 From: cgivre Date: Mon, 25 Aug 2025 14:24:14 -0400 Subject: [PATCH 16/22] Update parquet in Hive Plugin --- contrib/storage-hive/hive-exec-shade/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/storage-hive/hive-exec-shade/pom.xml b/contrib/storage-hive/hive-exec-shade/pom.xml index aa6032b1065..3ab44d1946a 100644 --- a/contrib/storage-hive/hive-exec-shade/pom.xml +++ b/contrib/storage-hive/hive-exec-shade/pom.xml @@ -32,7 +32,7 @@ Drill : Contrib : Storage : Hive : Exec Shaded - 1.15.1 + 1.15.2 From 907b38e21cd887c5d51da30ede08845257c76249 Mon Sep 17 00:00:00 2001 From: cgivre Date: Mon, 25 Aug 2025 12:21:37 -0400 Subject: [PATCH 17/22] Tests working from CLI --- contrib/storage-phoenix/pom.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/contrib/storage-phoenix/pom.xml b/contrib/storage-phoenix/pom.xml index fc2ec796337..1c72fb8590e 100644 --- a/contrib/storage-phoenix/pom.xml +++ b/contrib/storage-phoenix/pom.xml @@ -167,6 +167,19 @@ ${zookeeper.version} + + org.apache.hadoop + hadoop-hdfs-client + ${hadoop.version} + + + commons-logging + commons-logging + + + test + + org.apache.hadoop hadoop-minikdc From b67d276ae0010b046f3380f4570890eb6989dc3a Mon Sep 17 00:00:00 2001 From: cgivre Date: Tue, 2 Sep 2025 09:05:28 -0400 Subject: [PATCH 18/22] WIP --- contrib/storage-phoenix/pom.xml | 3 +- .../phoenix/secured/PhoenixEnvironment.java | 54 +++++++++++++------ 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/contrib/storage-phoenix/pom.xml b/contrib/storage-phoenix/pom.xml index 1c72fb8590e..e7317bd9029 100644 --- a/contrib/storage-phoenix/pom.xml +++ b/contrib/storage-phoenix/pom.xml @@ -39,7 +39,6 @@ - org.apache.drill.exec drill-java-exec @@ -232,6 +231,8 @@ -Xms2048m -Xmx2048m --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED + -Dhbase.security.authentication=simple + -Dhadoop.security.authentication=simple diff --git a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java index 88b3d607857..038d2058a17 100644 --- a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java +++ b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java @@ -17,20 +17,6 @@ */ package org.apache.drill.exec.store.phoenix.secured; -import static org.apache.hadoop.hbase.HConstants.HBASE_DIR; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.InetAddress; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; - import org.apache.commons.io.FileUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; @@ -38,8 +24,11 @@ import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.LocalHBaseCluster; +import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; import org.apache.hadoop.hbase.security.HBaseKerberosUtils; import org.apache.hadoop.hbase.security.User; +import org.apache.hadoop.hbase.security.access.AccessController; +import org.apache.hadoop.hbase.security.token.TokenProvider; import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.http.HttpConfig; import org.apache.hadoop.minikdc.MiniKdc; @@ -49,6 +38,20 @@ import org.apache.phoenix.util.InstanceResolver; import org.apache.phoenix.util.PhoenixRuntime; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.InetAddress; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.apache.hadoop.hbase.HConstants.HBASE_DIR; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + /** * This is a copy of class from `org.apache.phoenix:phoenix-queryserver-it`, * see original javadoc in {@code org.apache.phoenix.end2end.QueryServerEnvironment}. @@ -195,8 +198,7 @@ private static void ensureIsEmptyDirectory(File f) throws IOException { /** * Setup and start kerberosed, hbase */ - public PhoenixEnvironment(final Configuration confIn, int numberOfUsers, boolean tls) - throws Exception { + public PhoenixEnvironment(final Configuration confIn, int numberOfUsers, boolean tls) throws Exception { Configuration conf = util.getConfiguration(); conf.addResource(confIn); @@ -228,6 +230,26 @@ public PhoenixEnvironment(final Configuration confIn, int numberOfUsers, boolean conf.setInt(HConstants.REGIONSERVER_PORT, 0); conf.setInt(HConstants.REGIONSERVER_INFO_PORT, 0); + conf.set("hadoop.security.authentication", "kerberos"); + conf.set("hbase.security.authentication", "kerberos"); + + File serviceKeytab = getServiceKeytab(); // already generated by your MiniKdc setup + String servicePrincipal = HBaseKerberosUtils.getPrincipalForTesting(); + if (serviceKeytab == null || servicePrincipal == null) { + throw new IllegalStateException("MiniKdc did not provide service keytab/principal"); + } + + conf.set("hbase.master.keytab.file", serviceKeytab.getAbsolutePath()); + conf.set("hbase.regionserver.keytab.file", serviceKeytab.getAbsolutePath()); + conf.set("hbase.master.kerberos.principal", servicePrincipal); + conf.set("hbase.regionserver.kerberos.principal", servicePrincipal); + + // Coprocessors, proxy user configs, etc. (whatever you already have) + conf.setStrings(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, AccessController.class.getName()); + conf.setStrings(CoprocessorHost.REGIONSERVER_COPROCESSOR_CONF_KEY, AccessController.class.getName()); + conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, + AccessController.class.getName(), TokenProvider.class.getName()); + // Clear the cached singletons so we can inject our own. InstanceResolver.clearSingletons(); // Make sure the ConnectionInfo doesn't try to pull a default Configuration From 5beb224963f6f0c81162c8fd97f46825dc13f889 Mon Sep 17 00:00:00 2001 From: cgivre Date: Thu, 4 Sep 2025 08:51:10 -0400 Subject: [PATCH 19/22] Kerberos now working in Phoenix --- contrib/storage-phoenix/pom.xml | 107 +++++++++++-- .../phoenix/secured/PhoenixEnvironment.java | 143 ++++++++++++++---- .../secured/SecuredPhoenixBaseTest.java | 30 +++- pom.xml | 4 +- 4 files changed, 238 insertions(+), 46 deletions(-) diff --git a/contrib/storage-phoenix/pom.xml b/contrib/storage-phoenix/pom.xml index e7317bd9029..f483dc7ff34 100644 --- a/contrib/storage-phoenix/pom.xml +++ b/contrib/storage-phoenix/pom.xml @@ -194,28 +194,102 @@ log4j log4j - - - - - - org.apache.hadoop - hadoop-auth - ${hadoop.version} - test - + - commons-logging - commons-logging + org.apache.kerby + kerb-simplekdc - log4j - log4j + org.apache.kerby + kerb-client + + + org.apache.kerby + kerb-common + + + org.apache.kerby + kerb-core + + + org.apache.kerby + kerb-crypto + + + org.apache.kerby + kerb-util + + + org.apache.kerby + kerb-simplekdc + ${kerby.version} + test + + + org.apache.kerby + kerb-client + ${kerby.version} + test + + + org.apache.kerby + kerb-common + ${kerby.version} + test + + + org.apache.kerby + kerb-core + ${kerby.version} + test + + + org.apache.kerby + kerb-crypto + ${kerby.version} + test + + + org.apache.kerby + kerb-util + ${kerby.version} + test + + + org.apache.kerby + kerby-config + ${kerby.version} + test + + + org.apache.kerby + kerby-asn1 + ${kerby.version} + test + + + org.apache.kerby + kerby-pkix + ${kerby.version} + test + + + org.apache.kerby + kerby-util + ${kerby.version} + test + + + org.bouncycastle + bcprov-jdk18on + 1.78.1 + test + @@ -231,8 +305,9 @@ -Xms2048m -Xmx2048m --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED - -Dhbase.security.authentication=simple - -Dhadoop.security.authentication=simple + -Djava.net.preferIPv4Stack=true + -Dsun.security.krb5.debug=true + -Dsun.security.krb5.allowUdp=false diff --git a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java index 038d2058a17..7fd95385bc9 100644 --- a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java +++ b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java @@ -37,6 +37,8 @@ import org.apache.phoenix.query.ConfigurationFactory; import org.apache.phoenix.util.InstanceResolver; import org.apache.phoenix.util.PhoenixRuntime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -46,6 +48,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.UUID; import static org.apache.hadoop.hbase.HConstants.HBASE_DIR; @@ -80,7 +83,7 @@ public class PhoenixEnvironment { static { try { // uncomment it for debugging purposes - // System.setProperty("sun.security.krb5.debug", "true"); + System.setProperty("sun.security.krb5.debug", "true"); LOCAL_HOST_REVERSE_DNS_LOOKUP_NAME = InetAddress.getByName("127.0.0.1").getCanonicalHostName(); String userName = System.getProperty("user.name"); LOGIN_USER = userName != null ? userName : "securecluster"; @@ -100,6 +103,7 @@ public class PhoenixEnvironment { private int numCreatedUsers; private final String phoenixUrl; + private static final Logger logger = LoggerFactory.getLogger(PhoenixEnvironment.class); private static Configuration conf() { Configuration configuration = HBaseConfiguration.create(); @@ -206,49 +210,97 @@ public PhoenixEnvironment(final Configuration confIn, int numberOfUsers, boolean ensureIsEmptyDirectory(tempDir); ensureIsEmptyDirectory(keytabDir); keytab = new File(keytabDir, "test.keytab"); + // Start a MiniKDC - kdc = util.setupMiniKdc(keytab); - // Create a service principal and spnego principal in one keytab - // NB. Due to some apparent limitations between HDFS and HBase in the same JVM, trying to - // use separate identies for HBase and HDFS results in a GSS initiate error. The quick - // solution is to just use a single "service" principal instead of "hbase" and "hdfs" - // (or "dn" and "nn") per usual. - kdc.createPrincipal(keytab, SPNEGO_PRINCIPAL, PQS_PRINCIPAL, SERVICE_PRINCIPAL); - // Start ZK by hand + File kdcWorkDir = new File(new File(getTempDir()), "kdc-" + System.currentTimeMillis()); + ensureIsEmptyDirectory(kdcWorkDir); + + Properties kdcConf = org.apache.hadoop.minikdc.MiniKdc.createConf(); + kdcConf.setProperty(org.apache.hadoop.minikdc.MiniKdc.KDC_BIND_ADDRESS, "127.0.0.1"); + kdcConf.setProperty("kdc.tcp.port", "0"); + kdcConf.setProperty("kdc.allow_udp", "false"); + kdcConf.setProperty("kdc.encryption.types", "aes128-cts-hmac-sha1-96"); + kdcConf.setProperty("kdc.fast.enabled", "false"); + kdcConf.setProperty("kdc.preauth.required", "true"); + kdcConf.setProperty("kdc.allowable.clockskew", "300000"); // 5m + kdcConf.setProperty(org.apache.hadoop.minikdc.MiniKdc.DEBUG, "true"); + + kdc = new org.apache.hadoop.minikdc.MiniKdc(kdcConf, kdcWorkDir); + kdc.start(); + + // Write krb5.conf that disables referrals/canonicalization + File krb5File = new File(kdcWorkDir, "krb5.conf"); + writeKrb5Conf(krb5File.toPath(), kdc.getRealm(), "127.0.0.1", kdc.getPort()); + System.setProperty("java.security.krb5.conf", krb5File.getAbsolutePath()); + System.setProperty("sun.security.krb5.allowUdp", "false"); + System.setProperty("sun.security.krb5.disableReferrals", "true"); + System.setProperty("java.net.preferIPv4Stack", "true"); + System.setProperty("sun.security.krb5.debug", "true"); + System.clearProperty("java.security.krb5.realm"); // avoid env overrides + System.clearProperty("java.security.krb5.kdc"); + + // Fresh keytab every run; create principals in one shot + if (keytab.exists() && !keytab.delete()) { + throw new IOException("Couldn't delete old keytab: " + keytab); + } + keytab.getParentFile().mkdirs(); + + // Use a conventional service principal to avoid canonicalization surprises + final String SERVICE_PRINCIPAL_LOCAL = "hbase/localhost"; + final String SPNEGO_PRINCIPAL_LOCAL = "HTTP/localhost"; + final String PQS_PRINCIPAL_LOCAL = "phoenixqs/localhost"; + + kdc.createPrincipal( + keytab, + SPNEGO_PRINCIPAL_LOCAL, + PQS_PRINCIPAL_LOCAL, + SERVICE_PRINCIPAL_LOCAL + ); + // --- End explicit MiniKDC setup --- + + // Start ZK by hand util.startMiniZKCluster(); // Create a number of unprivileged users createUsers(numberOfUsers); - // Set configuration for HBase - HBaseKerberosUtils.setPrincipalForTesting(SERVICE_PRINCIPAL + "@" + kdc.getRealm()); + // HBase ↔ Kerberos wiring: set creds BEFORE setSecuredConfiguration + final String servicePrincipal = "hbase/localhost@" + kdc.getRealm(); + + conf.set("hadoop.security.authentication", "kerberos"); + conf.set("hbase.security.authentication", "kerberos"); + + conf.set("hbase.master.keytab.file", keytab.getAbsolutePath()); + conf.set("hbase.regionserver.keytab.file", keytab.getAbsolutePath()); + conf.set("hbase.master.kerberos.principal", servicePrincipal); + conf.set("hbase.regionserver.kerberos.principal", servicePrincipal); + + // Make HBase copy its secured defaults *after* we have principals/keytab in conf + HBaseKerberosUtils.setPrincipalForTesting(servicePrincipal); + HBaseKerberosUtils.setKeytabFileForTesting(keytab.getAbsolutePath()); HBaseKerberosUtils.setSecuredConfiguration(conf); + + // HDFS side setHdfsSecuredConfiguration(conf); + + // UGI must see kerberos + UserGroupInformation.setConfiguration(conf); + + // Preflight: prove the keytab/KDC works *before* we start HBase + UserGroupInformation.loginUserFromKeytab(servicePrincipal, keytab.getAbsolutePath()); + logger.info("UGI login OK for {}", servicePrincipal); + UserGroupInformation.setConfiguration(conf); + conf.setInt(HConstants.MASTER_PORT, 0); conf.setInt(HConstants.MASTER_INFO_PORT, 0); conf.setInt(HConstants.REGIONSERVER_PORT, 0); conf.setInt(HConstants.REGIONSERVER_INFO_PORT, 0); - conf.set("hadoop.security.authentication", "kerberos"); - conf.set("hbase.security.authentication", "kerberos"); - - File serviceKeytab = getServiceKeytab(); // already generated by your MiniKdc setup - String servicePrincipal = HBaseKerberosUtils.getPrincipalForTesting(); - if (serviceKeytab == null || servicePrincipal == null) { - throw new IllegalStateException("MiniKdc did not provide service keytab/principal"); - } - - conf.set("hbase.master.keytab.file", serviceKeytab.getAbsolutePath()); - conf.set("hbase.regionserver.keytab.file", serviceKeytab.getAbsolutePath()); - conf.set("hbase.master.kerberos.principal", servicePrincipal); - conf.set("hbase.regionserver.kerberos.principal", servicePrincipal); - // Coprocessors, proxy user configs, etc. (whatever you already have) conf.setStrings(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, AccessController.class.getName()); conf.setStrings(CoprocessorHost.REGIONSERVER_COPROCESSOR_CONF_KEY, AccessController.class.getName()); - conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, - AccessController.class.getName(), TokenProvider.class.getName()); + conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, AccessController.class.getName(), TokenProvider.class.getName()); // Clear the cached singletons so we can inject our own. InstanceResolver.clearSingletons(); @@ -280,10 +332,47 @@ public Configuration getConfiguration(Configuration confToClone) { phoenixUrl = PhoenixRuntime.JDBC_PROTOCOL + ":localhost:" + getZookeeperPort(); } + private static void writeKrb5Conf(java.nio.file.Path path, String realm, String host, int port) throws Exception { + String cfg = + "[libdefaults]\n" + + " default_realm = " + realm + "\n" + + " dns_lookup_kdc = false\n" + + " dns_lookup_realm = false\n" + + " dns_canonicalize_hostname = false\n" + + " rdns = false\n" + + " udp_preference_limit = 1\n" + + " default_tkt_enctypes = aes128-cts-hmac-sha1-96\n" + + " default_tgs_enctypes = aes128-cts-hmac-sha1-96\n" + + " permitted_enctypes = aes128-cts-hmac-sha1-96\n" + + "\n" + + "[realms]\n" + + " " + realm + " = {\n" + + " kdc = " + host + ":" + port + "\n" + + " admin_server = " + host + ":" + port + "\n" + + " }\n"; + java.nio.file.Files.createDirectories(path.getParent()); + java.nio.file.Files.write(path, cfg.getBytes(java.nio.charset.StandardCharsets.UTF_8)); + } + + public int getZookeeperPort() { return util.getConfiguration().getInt(HConstants.ZOOKEEPER_CLIENT_PORT, 2181); } + private static void createPrincipalIfAbsent(MiniKdc kdc, File keytab, String principal) throws Exception { + try { + kdc.createPrincipal(keytab, principal); + } catch (org.apache.kerby.kerberos.kerb.KrbException e) { + String msg = e.getMessage(); + if (msg != null && msg.contains("already exists")) { + // Principal is already in the KDC; fine to proceed. + // (Keys were generated when it was first created.) + return; + } + throw e; + } + } + public void stop() throws Exception { // Remove our custom ConfigurationFactory for future tests InstanceResolver.clearSingletons(); diff --git a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java index 193b7ba9544..3f8aa06101c 100644 --- a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java +++ b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java @@ -18,6 +18,7 @@ package org.apache.drill.exec.store.phoenix.secured; import ch.qos.logback.classic.Level; +import com.google.common.collect.Lists; import com.sun.security.auth.module.Krb5LoginModule; import org.apache.drill.common.config.DrillProperties; import org.apache.drill.common.exceptions.UserRemoteException; @@ -29,7 +30,6 @@ import org.apache.drill.exec.store.phoenix.PhoenixDataSource; import org.apache.drill.exec.store.phoenix.PhoenixStoragePluginConfig; import org.apache.drill.exec.util.ImpersonationUtil; -import com.google.common.collect.Lists; import org.apache.drill.test.ClusterFixture; import org.apache.drill.test.ClusterFixtureBuilder; import org.apache.drill.test.ClusterTest; @@ -69,6 +69,8 @@ public abstract class SecuredPhoenixBaseTest extends ClusterTest { private final static AtomicInteger initCount = new AtomicInteger(0); + + @BeforeClass public static void setUpBeforeClass() throws Exception { TimeZone.setDefault(TimeZone.getTimeZone("UTC")); @@ -92,6 +94,17 @@ private static void startSecuredDrillCluster() throws Exception { Map.Entry user3 = environment.getUser(3); dirTestWatcher.start(SecuredPhoenixTestSuite.class); // until DirTestWatcher ClassRule is implemented for JUnit5 + //udfDir = dirTestWatcher.makeSubDir(Paths.get("udf")); + + // Create a UDF directory with proper permissions in the test directory + //File udfRoot = new File(dirTestWatcher.getRootDir(), "drill/udf"); + //udfRoot.mkdirs(); + + // Set proper permissions on the UDF directory and all parent directories + //setDirectoryPermissions(udfRoot); + //setDirectoryPermissions(udfRoot.getParentFile()); // drill directory + setDirectoryPermissions(dirTestWatcher.getRootDir()); // root directory + ClusterFixtureBuilder builder = ClusterFixture.builder(dirTestWatcher) .configProperty(ExecConstants.USER_AUTHENTICATION_ENABLED, true) .configProperty(ExecConstants.USER_AUTHENTICATOR_IMPL, UserAuthenticatorTestImpl.TYPE) @@ -101,6 +114,11 @@ private static void startSecuredDrillCluster() throws Exception { .configProperty(ExecConstants.BIT_AUTHENTICATION_MECHANISM, "kerberos") .configProperty(ExecConstants.SERVICE_PRINCIPAL, HBaseKerberosUtils.getPrincipalForTesting()) .configProperty(ExecConstants.SERVICE_KEYTAB_LOCATION, environment.getServiceKeytab().getAbsolutePath()) + // Set UDF directory to a location we control with proper permissions + .configProperty(ExecConstants.DYNAMIC_UDF_SUPPORT_ENABLED, false) + //.configProperty(ExecConstants.UDF_DIRECTORY_ROOT, udfDir.getAbsolutePath()) + //.configProperty(ExecConstants.UDF_DIRECTORY_FS, getLocalFileSystem().getUri()) + .configProperty(ExecConstants.UDF_DISABLE_DYNAMIC, true) .configClientProperty(DrillProperties.SERVICE_PRINCIPAL, HBaseKerberosUtils.getPrincipalForTesting()) .configClientProperty(DrillProperties.USER, user1.getKey()) .configClientProperty(DrillProperties.KEYTAB, user1.getValue().getAbsolutePath()); @@ -124,6 +142,16 @@ private static void startSecuredDrillCluster() throws Exception { registry.put(PhoenixStoragePluginConfig.NAME + "123", config); } + /** + * Set proper permissions on a directory to ensure it's writable and executable + */ + private static void setDirectoryPermissions(File dir) { + if (dir != null && dir.exists()) { + dir.setWritable(true, false); // writable by all + dir.setExecutable(true, false); // executable by all + dir.setReadable(true, false); // readable by all + } + } /** * Initialize HBase via Phoenix diff --git a/pom.xml b/pom.xml index ab34d9f4de2..60f7ec19604 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 1.10.0 1.7 5.5.0 - 10.14.2.0 + 10.17.1.0 3072 apache/drill @@ -107,7 +107,7 @@ 1.8.2 5.7.2 - 1.0.1 + 2.0.3 0.18.1 true 2.23.1 From db4563cefcc6aa4a7a2df8f2ad912b6d31128ebd Mon Sep 17 00:00:00 2001 From: cgivre Date: Tue, 9 Sep 2025 09:21:32 -0400 Subject: [PATCH 20/22] Unit tests passing. Thank you claude code --- .../org/apache/drill/common/KerberosUtil.java | 5 +- .../secured/SecuredPhoenixBaseTest.java | 51 ++++++++++++++----- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/common/src/main/java/org/apache/drill/common/KerberosUtil.java b/common/src/main/java/org/apache/drill/common/KerberosUtil.java index 44403e92f9a..cb7d511eda9 100644 --- a/common/src/main/java/org/apache/drill/common/KerberosUtil.java +++ b/common/src/main/java/org/apache/drill/common/KerberosUtil.java @@ -17,6 +17,9 @@ */ package org.apache.drill.common; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -24,7 +27,7 @@ import static com.google.common.base.Preconditions.checkState; public final class KerberosUtil { - private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(KerberosUtil.class); + private static final Logger logger = LoggerFactory.getLogger(KerberosUtil.class); // Per this link http://docs.oracle.com/javase/jndi/tutorial/ldap/security/gssapi.html // "... GSS-API SASL mechanism was retrofitted to mean only Kerberos v5 ..." diff --git a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java index 3f8aa06101c..0c03d70752c 100644 --- a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java +++ b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java @@ -94,16 +94,23 @@ private static void startSecuredDrillCluster() throws Exception { Map.Entry user3 = environment.getUser(3); dirTestWatcher.start(SecuredPhoenixTestSuite.class); // until DirTestWatcher ClassRule is implemented for JUnit5 - //udfDir = dirTestWatcher.makeSubDir(Paths.get("udf")); // Create a UDF directory with proper permissions in the test directory - //File udfRoot = new File(dirTestWatcher.getRootDir(), "drill/udf"); - //udfRoot.mkdirs(); - - // Set proper permissions on the UDF directory and all parent directories - //setDirectoryPermissions(udfRoot); - //setDirectoryPermissions(udfRoot.getParentFile()); // drill directory - setDirectoryPermissions(dirTestWatcher.getRootDir()); // root directory + File udfDir = dirTestWatcher.makeSubDir(Paths.get("udf")); + + // Pre-create all subdirectories that Drill will need with proper permissions + File drillDir = new File(udfDir, "drill"); + File happyDir = new File(drillDir, "happy"); + File udfSubDir = new File(happyDir, "udf"); + File registryDir = new File(udfSubDir, "registry"); + File stagingDir = new File(udfSubDir, "staging"); + File tmpDir = new File(udfSubDir, "tmp"); + + // Create all directories and set permissions + registryDir.mkdirs(); + stagingDir.mkdirs(); + tmpDir.mkdirs(); + setDirectoryPermissions(udfDir); ClusterFixtureBuilder builder = ClusterFixture.builder(dirTestWatcher) .configProperty(ExecConstants.USER_AUTHENTICATION_ENABLED, true) @@ -112,17 +119,23 @@ private static void startSecuredDrillCluster() throws Exception { .configProperty(ExecConstants.IMPERSONATION_ENABLED, true) .configProperty(ExecConstants.BIT_AUTHENTICATION_ENABLED, true) .configProperty(ExecConstants.BIT_AUTHENTICATION_MECHANISM, "kerberos") + .configProperty(ExecConstants.USE_LOGIN_PRINCIPAL, true) .configProperty(ExecConstants.SERVICE_PRINCIPAL, HBaseKerberosUtils.getPrincipalForTesting()) .configProperty(ExecConstants.SERVICE_KEYTAB_LOCATION, environment.getServiceKeytab().getAbsolutePath()) // Set UDF directory to a location we control with proper permissions - .configProperty(ExecConstants.DYNAMIC_UDF_SUPPORT_ENABLED, false) - //.configProperty(ExecConstants.UDF_DIRECTORY_ROOT, udfDir.getAbsolutePath()) - //.configProperty(ExecConstants.UDF_DIRECTORY_FS, getLocalFileSystem().getUri()) + .configProperty(ExecConstants.UDF_DIRECTORY_ROOT, udfDir.getAbsolutePath()) + .configProperty(ExecConstants.UDF_DIRECTORY_FS, "file:///" + udfDir.getAbsolutePath().replace("\\", "/")) + // Disable dynamic UDF support for this test to avoid filesystem issues .configProperty(ExecConstants.UDF_DISABLE_DYNAMIC, true) .configClientProperty(DrillProperties.SERVICE_PRINCIPAL, HBaseKerberosUtils.getPrincipalForTesting()) .configClientProperty(DrillProperties.USER, user1.getKey()) .configClientProperty(DrillProperties.KEYTAB, user1.getValue().getAbsolutePath()); startCluster(builder); + + // After cluster starts, Drill creates subdirectories in the UDF area + // Set permissions recursively on all created subdirectories + setDirectoryPermissions(udfDir); + Properties user2ClientProperties = new Properties(); user2ClientProperties.setProperty(DrillProperties.SERVICE_PRINCIPAL, HBaseKerberosUtils.getPrincipalForTesting()); user2ClientProperties.setProperty(DrillProperties.USER, user2.getKey()); @@ -144,12 +157,26 @@ private static void startSecuredDrillCluster() throws Exception { /** * Set proper permissions on a directory to ensure it's writable and executable + * This method recursively sets permissions on all subdirectories created by Drill */ private static void setDirectoryPermissions(File dir) { if (dir != null && dir.exists()) { + // Set permissions on the directory itself dir.setWritable(true, false); // writable by all - dir.setExecutable(true, false); // executable by all + dir.setExecutable(true, false); // executable by all dir.setReadable(true, false); // readable by all + + // Recursively set permissions on subdirectories + if (dir.isDirectory()) { + File[] children = dir.listFiles(); + if (children != null) { + for (File child : children) { + if (child.isDirectory()) { + setDirectoryPermissions(child); + } + } + } + } } } From 80f472c6761890a6b5a6cb502737114c3eeb1c6c Mon Sep 17 00:00:00 2001 From: cgivre Date: Tue, 9 Sep 2025 10:07:04 -0400 Subject: [PATCH 21/22] Fix checkstyle --- .../phoenix/secured/SecuredPhoenixBaseTest.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java index 0c03d70752c..fdbe85fa3bd 100644 --- a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java +++ b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/SecuredPhoenixBaseTest.java @@ -97,18 +97,16 @@ private static void startSecuredDrillCluster() throws Exception { // Create a UDF directory with proper permissions in the test directory File udfDir = dirTestWatcher.makeSubDir(Paths.get("udf")); - // Pre-create all subdirectories that Drill will need with proper permissions File drillDir = new File(udfDir, "drill"); - File happyDir = new File(drillDir, "happy"); + File happyDir = new File(drillDir, "happy"); File udfSubDir = new File(happyDir, "udf"); File registryDir = new File(udfSubDir, "registry"); File stagingDir = new File(udfSubDir, "staging"); File tmpDir = new File(udfSubDir, "tmp"); - // Create all directories and set permissions registryDir.mkdirs(); - stagingDir.mkdirs(); + stagingDir.mkdirs(); tmpDir.mkdirs(); setDirectoryPermissions(udfDir); @@ -131,11 +129,11 @@ private static void startSecuredDrillCluster() throws Exception { .configClientProperty(DrillProperties.USER, user1.getKey()) .configClientProperty(DrillProperties.KEYTAB, user1.getValue().getAbsolutePath()); startCluster(builder); - + // After cluster starts, Drill creates subdirectories in the UDF area // Set permissions recursively on all created subdirectories setDirectoryPermissions(udfDir); - + Properties user2ClientProperties = new Properties(); user2ClientProperties.setProperty(DrillProperties.SERVICE_PRINCIPAL, HBaseKerberosUtils.getPrincipalForTesting()); user2ClientProperties.setProperty(DrillProperties.USER, user2.getKey()); @@ -163,9 +161,8 @@ private static void setDirectoryPermissions(File dir) { if (dir != null && dir.exists()) { // Set permissions on the directory itself dir.setWritable(true, false); // writable by all - dir.setExecutable(true, false); // executable by all + dir.setExecutable(true, false); // executable by all dir.setReadable(true, false); // readable by all - // Recursively set permissions on subdirectories if (dir.isDirectory()) { File[] children = dir.listFiles(); From c443cffaa92b51ba43d958e3f28db44eb01d5c17 Mon Sep 17 00:00:00 2001 From: "Charles S. Givre" Date: Wed, 10 Sep 2025 23:43:09 -0400 Subject: [PATCH 22/22] Comment out debug line --- .../drill/exec/store/phoenix/secured/PhoenixEnvironment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java index 7fd95385bc9..acc662cc81d 100644 --- a/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java +++ b/contrib/storage-phoenix/src/test/java/org/apache/drill/exec/store/phoenix/secured/PhoenixEnvironment.java @@ -83,7 +83,7 @@ public class PhoenixEnvironment { static { try { // uncomment it for debugging purposes - System.setProperty("sun.security.krb5.debug", "true"); + // System.setProperty("sun.security.krb5.debug", "true"); LOCAL_HOST_REVERSE_DNS_LOOKUP_NAME = InetAddress.getByName("127.0.0.1").getCanonicalHostName(); String userName = System.getProperty("user.name"); LOGIN_USER = userName != null ? userName : "securecluster";