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

dengzhhu653 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new 08bce2a2f93 HIVE-29796: HS2 in Kerberos mode should obfuscate details 
in error lo… (#6694)
08bce2a2f93 is described below

commit 08bce2a2f930660bde11d1daabb858085135ffe1
Author: Sai Hemanth Gantasala 
<[email protected]>
AuthorDate: Fri Aug 21 02:26:08 2026 -0700

    HIVE-29796: HS2 in Kerberos mode should obfuscate details in error lo… 
(#6694)
---
 service-rpc/pom.xml                                |  17 ++++
 .../rpc/thrift/TCancelDelegationTokenReq.java      |   6 +-
 .../rpc/thrift/TRenewDelegationTokenReq.java       |   6 +-
 .../TestDelegationTokenRequestRedaction.java       |  49 +++++++++
 .../apache/hive/service/auth/HiveAuthFactory.java  |  15 +--
 .../hive/service/cli/thrift/ThriftCLIService.java  |   4 +-
 .../auth/TestDelegationTokenLeakPrevention.java    | 109 +++++++++++++++++++++
 7 files changed, 187 insertions(+), 19 deletions(-)

diff --git a/service-rpc/pom.xml b/service-rpc/pom.xml
index e7f1205894c..f47063c6367 100644
--- a/service-rpc/pom.xml
+++ b/service-rpc/pom.xml
@@ -162,6 +162,23 @@
                   </replacements>
                 </configuration>
               </execution>
+              <execution>
+                <id>mask-delegation-token</id>
+                <phase>process-sources</phase>
+                <goals>
+                  <goal>replace</goal>
+                </goals>
+                <configuration>
+                  
<basedir>${basedir}/src/gen/thrift/gen-javabean/org/apache/hive/service/rpc/thrift/</basedir>
+                  
<filesToInclude>TCancelDelegationTokenReq.java,TRenewDelegationTokenReq.java</filesToInclude>
+                  <replacements>
+                    <replacement>
+                      <token>    if \(this.delegationToken \=\= null\) \{\n    
  sb.append\(\"null"\)\;\n    \} else \{\n      
sb.append\(this.delegationToken\)\;\n    \}</token>
+                      <value>    sb.append("*** REDACTED ***");</value>
+                    </replacement>
+                  </replacements>
+                </configuration>
+              </execution>
             </executions>
           </plugin>
         </plugins>
diff --git 
a/service-rpc/src/gen/thrift/gen-javabean/org/apache/hive/service/rpc/thrift/TCancelDelegationTokenReq.java
 
b/service-rpc/src/gen/thrift/gen-javabean/org/apache/hive/service/rpc/thrift/TCancelDelegationTokenReq.java
index 396b1fa23cb..1f2941b0ef9 100644
--- 
a/service-rpc/src/gen/thrift/gen-javabean/org/apache/hive/service/rpc/thrift/TCancelDelegationTokenReq.java
+++ 
b/service-rpc/src/gen/thrift/gen-javabean/org/apache/hive/service/rpc/thrift/TCancelDelegationTokenReq.java
@@ -333,11 +333,7 @@ public java.lang.String toString() {
     first = false;
     if (!first) sb.append(", ");
     sb.append("delegationToken:");
-    if (this.delegationToken == null) {
-      sb.append("null");
-    } else {
-      sb.append(this.delegationToken);
-    }
+    sb.append("*** REDACTED ***");
     first = false;
     sb.append(")");
     return sb.toString();
diff --git 
a/service-rpc/src/gen/thrift/gen-javabean/org/apache/hive/service/rpc/thrift/TRenewDelegationTokenReq.java
 
b/service-rpc/src/gen/thrift/gen-javabean/org/apache/hive/service/rpc/thrift/TRenewDelegationTokenReq.java
index 57ab7481b3f..7457b2d170d 100644
--- 
a/service-rpc/src/gen/thrift/gen-javabean/org/apache/hive/service/rpc/thrift/TRenewDelegationTokenReq.java
+++ 
b/service-rpc/src/gen/thrift/gen-javabean/org/apache/hive/service/rpc/thrift/TRenewDelegationTokenReq.java
@@ -333,11 +333,7 @@ public java.lang.String toString() {
     first = false;
     if (!first) sb.append(", ");
     sb.append("delegationToken:");
-    if (this.delegationToken == null) {
-      sb.append("null");
-    } else {
-      sb.append(this.delegationToken);
-    }
+    sb.append("*** REDACTED ***");
     first = false;
     sb.append(")");
     return sb.toString();
diff --git 
a/service-rpc/src/test/org/apache/hive/service/rpc/thrift/TestDelegationTokenRequestRedaction.java
 
b/service-rpc/src/test/org/apache/hive/service/rpc/thrift/TestDelegationTokenRequestRedaction.java
new file mode 100644
index 00000000000..9d3f48c6ca5
--- /dev/null
+++ 
b/service-rpc/src/test/org/apache/hive/service/rpc/thrift/TestDelegationTokenRequestRedaction.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hive.service.rpc.thrift;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class TestDelegationTokenRequestRedaction {
+  private static final String LIVE_TOKEN = "LIVE_DELEGATION_TOKEN_ABC123";
+
+  @Test
+  public void testCancelReqToStringRedactsDelegationToken() {
+    TCancelDelegationTokenReq req = new TCancelDelegationTokenReq();
+    req.setDelegationToken(LIVE_TOKEN);
+
+    String reqString = req.toString();
+    assertTrue(reqString.contains("delegationToken:"));
+    assertTrue(reqString.toLowerCase().contains("redacted"));
+    assertFalse(reqString.contains(LIVE_TOKEN));
+  }
+
+  @Test
+  public void testRenewReqToStringRedactsDelegationToken() {
+    TRenewDelegationTokenReq req = new TRenewDelegationTokenReq();
+    req.setDelegationToken(LIVE_TOKEN);
+
+    String reqString = req.toString();
+    assertTrue(reqString.contains("delegationToken:"));
+    assertTrue(reqString.toLowerCase().contains("redacted"));
+    assertFalse(reqString.contains(LIVE_TOKEN));
+  }
+}
diff --git a/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java 
b/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java
index c7e8165717f..bfa9831ed37 100644
--- a/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java
+++ b/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java
@@ -258,8 +258,7 @@ public void cancelDelegationToken(String delegationToken) 
throws HiveSQLExceptio
     try {
       delegationTokenManager.cancelDelegationToken(delegationToken);
     } catch (IOException e) {
-      throw new HiveSQLException(
-          "Error canceling delegation token " + delegationToken, "08S01", e);
+      throw new HiveSQLException(delegationTokenErrorMessage("canceling"), 
"08S01", e);
     }
   }
 
@@ -271,8 +270,7 @@ public void renewDelegationToken(String delegationToken) 
throws HiveSQLException
     try {
       delegationTokenManager.renewDelegationToken(delegationToken);
     } catch (IOException e) {
-      throw new HiveSQLException(
-          "Error renewing delegation token " + delegationToken, "08S01", e);
+      throw new HiveSQLException(delegationTokenErrorMessage("renewing"), 
"08S01", e);
     }
   }
 
@@ -284,7 +282,7 @@ public String verifyDelegationToken(String delegationToken) 
throws HiveSQLExcept
     try {
       return delegationTokenManager.verifyDelegationToken(delegationToken);
     } catch (IOException e) {
-      String msg =  "Error verifying delegation token " + delegationToken;
+      String msg = delegationTokenErrorMessage("verifying");
       LOG.error(msg, e);
       throw new HiveSQLException(msg, "08S01", e);
     }
@@ -298,11 +296,14 @@ public String getUserFromToken(String delegationToken) 
throws HiveSQLException {
     try {
       return delegationTokenManager.getUserFromToken(delegationToken);
     } catch (IOException e) {
-      throw new HiveSQLException(
-          "Error extracting user from delegation token " + delegationToken, 
"08S01", e);
+      throw new HiveSQLException(delegationTokenErrorMessage("extracting user 
from"), "08S01", e);
     }
   }
 
+  private static String delegationTokenErrorMessage(String operation) {
+    return "Error " + operation + " delegation token";
+  }
+
   public static void verifyProxyAccess(String realUser, String proxyUser, 
String ipAddress,
     HiveConf hiveConf) throws HiveSQLException {
     try {
diff --git 
a/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java 
b/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java
index a901edecc0f..e6053cb92e8 100644
--- a/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java
+++ b/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java
@@ -363,7 +363,7 @@ public TCancelDelegationTokenResp 
CancelDelegationToken(TCancelDelegationTokenRe
             hiveAuthFactory, req.getDelegationToken());
         resp.setStatus(OK_STATUS);
       } catch (HiveSQLException e) {
-        LOG.error("Failed to cancel delegation token [request: {}]", req, e);
+        LOG.error("Failed to cancel delegation token for session {}", 
req.getSessionHandle(), e);
         resp.setStatus(HiveSQLException.toTStatus(e));
       }
     }
@@ -382,7 +382,7 @@ public TRenewDelegationTokenResp 
RenewDelegationToken(TRenewDelegationTokenReq r
             hiveAuthFactory, req.getDelegationToken());
         resp.setStatus(OK_STATUS);
       } catch (HiveSQLException e) {
-        LOG.error("Failed to renew delegation token [request: {}]", e);
+        LOG.error("Failed to renew delegation token for session {}", 
req.getSessionHandle(), e);
         resp.setStatus(HiveSQLException.toTStatus(e));
       }
     }
diff --git 
a/service/src/test/org/apache/hive/service/auth/TestDelegationTokenLeakPrevention.java
 
b/service/src/test/org/apache/hive/service/auth/TestDelegationTokenLeakPrevention.java
new file mode 100644
index 00000000000..aa4c92d55e9
--- /dev/null
+++ 
b/service/src/test/org/apache/hive/service/auth/TestDelegationTokenLeakPrevention.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hive.service.auth;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+
+import org.apache.hadoop.hive.conf.HiveConf;
+import 
org.apache.hadoop.hive.metastore.security.MetastoreDelegationTokenManager;
+import org.apache.hive.service.cli.HiveSQLException;
+import org.apache.hive.service.rpc.thrift.TStatus;
+import org.junit.Test;
+import org.apache.thrift.transport.TTransportException;
+
+public class TestDelegationTokenLeakPrevention {
+  private static final String LIVE_TOKEN = "LIVE_DELEGATION_TOKEN_ABC123";
+
+  @Test
+  public void testCancelDelegationTokenExceptionDoesNotContainToken() throws 
Exception {
+    MetastoreDelegationTokenManager tokenManager = 
mock(MetastoreDelegationTokenManager.class);
+    doThrow(new 
IOException("boom")).when(tokenManager).cancelDelegationToken(LIVE_TOKEN);
+
+    HiveAuthFactory authFactory = 
createAuthFactoryWithTokenManager(tokenManager);
+    assertTokenIsNotExposed(() -> 
authFactory.cancelDelegationToken(LIVE_TOKEN),
+        "Error canceling delegation token");
+  }
+
+  @Test
+  public void testRenewDelegationTokenExceptionDoesNotContainToken() throws 
Exception {
+    MetastoreDelegationTokenManager tokenManager = 
mock(MetastoreDelegationTokenManager.class);
+    doThrow(new 
IOException("boom")).when(tokenManager).renewDelegationToken(LIVE_TOKEN);
+
+    HiveAuthFactory authFactory = 
createAuthFactoryWithTokenManager(tokenManager);
+    assertTokenIsNotExposed(() -> authFactory.renewDelegationToken(LIVE_TOKEN),
+        "Error renewing delegation token");
+  }
+
+  @Test
+  public void testVerifyDelegationTokenExceptionDoesNotContainToken() throws 
Exception {
+    MetastoreDelegationTokenManager tokenManager = 
mock(MetastoreDelegationTokenManager.class);
+    doThrow(new 
IOException("boom")).when(tokenManager).verifyDelegationToken(LIVE_TOKEN);
+
+    HiveAuthFactory authFactory = 
createAuthFactoryWithTokenManager(tokenManager);
+    assertTokenIsNotExposed(() -> 
authFactory.verifyDelegationToken(LIVE_TOKEN),
+        "Error verifying delegation token");
+  }
+
+  @Test
+  public void testGetUserFromTokenExceptionDoesNotContainToken() throws 
Exception {
+    MetastoreDelegationTokenManager tokenManager = 
mock(MetastoreDelegationTokenManager.class);
+    doThrow(new 
IOException("boom")).when(tokenManager).getUserFromToken(LIVE_TOKEN);
+
+    HiveAuthFactory authFactory = 
createAuthFactoryWithTokenManager(tokenManager);
+    assertTokenIsNotExposed(() -> authFactory.getUserFromToken(LIVE_TOKEN),
+        "Error extracting user from delegation token");
+  }
+
+  private HiveAuthFactory 
createAuthFactoryWithTokenManager(MetastoreDelegationTokenManager tokenManager)
+      throws NoSuchFieldException, IllegalAccessException, TTransportException 
{
+    HiveAuthFactory authFactory = new HiveAuthFactory(new HiveConf(), false);
+    Field delegationTokenManagerField = 
HiveAuthFactory.class.getDeclaredField("delegationTokenManager");
+    delegationTokenManagerField.setAccessible(true);
+    delegationTokenManagerField.set(authFactory, tokenManager);
+    return authFactory;
+  }
+
+  private void assertTokenIsNotExposed(ThrowingRunnable callback, String 
expectedMessagePrefix)
+      throws Exception {
+    try {
+      callback.run();
+      fail("Expected HiveSQLException to be thrown");
+    } catch (HiveSQLException e) {
+      assertMessageIsSanitized(e.getMessage(), expectedMessagePrefix);
+      TStatus status = HiveSQLException.toTStatus(e);
+      assertMessageIsSanitized(status.getErrorMessage(), 
expectedMessagePrefix);
+    }
+  }
+
+  private void assertMessageIsSanitized(String message, String 
expectedMessagePrefix) {
+    assertTrue(message.contains(expectedMessagePrefix));
+    assertFalse(message.contains(LIVE_TOKEN));
+  }
+
+  @FunctionalInterface
+  private interface ThrowingRunnable {
+    void run() throws Exception;
+  }
+}

Reply via email to