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

peter-toth pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new 97a0147bd644 [SPARK-57882][SQL] Enforce AuthV2 metadata authorization 
on GetPrimaryKeys and GetCrossReference operations
97a0147bd644 is described below

commit 97a0147bd644182d526577fcd59ae84f0989009f
Author: Peter Toth <[email protected]>
AuthorDate: Fri Jul 3 18:11:54 2026 +0200

    [SPARK-57882][SQL] Enforce AuthV2 metadata authorization on GetPrimaryKeys 
and GetCrossReference operations
    
    ### What changes were proposed in this pull request?
    Add the `isAuthV2Enabled()/authorizeMetaGets()` authorization gate to 
`GetPrimaryKeysOperation.runInternal()` and 
`GetCrossReferenceOperation.runInternal()` in the Hive Thrift server, mirroring 
the pattern already used by the sibling `MetadataOperation` subclasses 
(`GetTablesOperation`, `GetColumnsOperation`, etc.). The check uses 
table-scoped `TABLE_OR_VIEW` privilege objects for the referenced table(s); 
`GetCrossReferenceOperation` handles the `getImportedKeys`/`getExportedKeys` 
cas [...]
    
    ### Why are the changes needed?
    When Hive AuthV2 authorization is configured 
(`hive.security.authorization.manager` set to a `HiveAuthorizerFactory` with 
authorization enabled), metadata operations gate metastore access through 
`authorizeMetaGets`. Every sibling `MetadataOperation` subclass does this, and 
Spark's own `SparkGet*Operation` classes do too. `GetPrimaryKeysOperation` and 
`GetCrossReferenceOperation` are the only metadata operations that omit the 
gate, and `SparkSQLOperationManager` does not override them [...]
    
    ### Does this PR introduce _any_ user-facing change?
    Only when Hive AuthV2 authorization is enabled: 
`DatabaseMetaData.getPrimaryKeys`/`getImportedKeys`/`getExportedKeys`/`getCrossReference`
 now perform the same authorization check as the other metadata calls, and 
access to unauthorized tables' key metadata is rejected. With authorization 
disabled (the default), behavior is unchanged.
    
    ### How was this patch tested?
    Compiled `hive-thriftserver` and ran the existing 
`SparkMetadataOperationSuite` (15 tests, all passing). The gate is a no-op when 
authorization is disabled, which is the path the suite exercises, so behavior 
is unchanged there.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    Generated-by: Claude Code (Opus 4.8)
    
    Closes #56962 from peter-toth/SPARK-57882-authv2-metadata-gate-pk-fk.
    
    Authored-by: Peter Toth <[email protected]>
    Signed-off-by: Peter Toth <[email protected]>
    (cherry picked from commit c79692e43ac07aaf80955f2aa43bf4ae8e9b7d9d)
    Signed-off-by: Peter Toth <[email protected]>
---
 .../cli/operation/GetCrossReferenceOperation.java  | 25 ++++++++++++++++++++++
 .../cli/operation/GetPrimaryKeysOperation.java     | 16 ++++++++++++++
 2 files changed, 41 insertions(+)

diff --git 
a/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/operation/GetCrossReferenceOperation.java
 
b/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/operation/GetCrossReferenceOperation.java
index 3a29859a2074..04a6d50ad649 100644
--- 
a/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/operation/GetCrossReferenceOperation.java
+++ 
b/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/operation/GetCrossReferenceOperation.java
@@ -20,12 +20,16 @@ package org.apache.hive.service.cli.operation;
 import org.apache.hadoop.hive.metastore.IMetaStoreClient;
 import org.apache.hadoop.hive.metastore.api.ForeignKeysRequest;
 import org.apache.hadoop.hive.metastore.api.SQLForeignKey;
+import 
org.apache.hadoop.hive.ql.security.authorization.plugin.HiveOperationType;
+import 
org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject;
+import 
org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject.HivePrivilegeObjectType;
 import org.apache.hadoop.hive.serde2.thrift.Type;
 import org.apache.hive.service.cli.*;
 import org.apache.hive.service.cli.session.HiveSession;
 import org.apache.hive.service.rpc.thrift.TRowSet;
 import org.apache.hive.service.rpc.thrift.TTableSchema;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -117,6 +121,27 @@ public class GetCrossReferenceOperation extends 
MetadataOperation {
     setState(OperationState.RUNNING);
     try {
        IMetaStoreClient metastoreClient = 
getParentSession().getMetaStoreClient();
+      if (isAuthV2Enabled()) {
+        List<HivePrivilegeObject> privObjs = new ArrayList<>();
+        if (parentTableName != null) {
+          privObjs.add(new HivePrivilegeObject(
+              HivePrivilegeObjectType.TABLE_OR_VIEW, parentSchemaName, 
parentTableName));
+        }
+        if (foreignTableName != null) {
+          privObjs.add(new HivePrivilegeObject(
+              HivePrivilegeObjectType.TABLE_OR_VIEW, foreignSchemaName, 
foreignTableName));
+        }
+        String cmdStr = "catalog : " + parentCatalogName
+            + ", parentSchema : " + parentSchemaName + ", parentTable : " + 
parentTableName
+            + ", foreignSchema : " + foreignSchemaName + ", foreignTable : " + 
foreignTableName;
+        if (privObjs.isEmpty()) {
+          // Neither table is specified, so the request cannot be scoped to 
any privilege object;
+          // reject it instead of skipping the authorization check.
+          throw new HiveSQLException(
+              "Access denied: neither parent nor foreign table specified. " + 
cmdStr);
+        }
+        authorizeMetaGets(HiveOperationType.GET_COLUMNS, privObjs, cmdStr);
+      }
      ForeignKeysRequest fkReq = new ForeignKeysRequest(parentSchemaName, 
parentTableName, foreignSchemaName, foreignTableName);
      List<SQLForeignKey> fks = metastoreClient.getForeignKeys(fkReq);
       if (fks == null) {
diff --git 
a/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/operation/GetPrimaryKeysOperation.java
 
b/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/operation/GetPrimaryKeysOperation.java
index 927328342974..c7dd29e7305c 100644
--- 
a/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/operation/GetPrimaryKeysOperation.java
+++ 
b/sql/hive-thriftserver/src/main/java/org/apache/hive/service/cli/operation/GetPrimaryKeysOperation.java
@@ -20,12 +20,16 @@ package org.apache.hive.service.cli.operation;
 import org.apache.hadoop.hive.metastore.IMetaStoreClient;
 import org.apache.hadoop.hive.metastore.api.PrimaryKeysRequest;
 import org.apache.hadoop.hive.metastore.api.SQLPrimaryKey;
+import 
org.apache.hadoop.hive.ql.security.authorization.plugin.HiveOperationType;
+import 
org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject;
+import 
org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject.HivePrivilegeObjectType;
 import org.apache.hadoop.hive.serde2.thrift.Type;
 import org.apache.hive.service.cli.*;
 import org.apache.hive.service.cli.session.HiveSession;
 import org.apache.hive.service.rpc.thrift.TRowSet;
 import org.apache.hive.service.rpc.thrift.TTableSchema;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -75,6 +79,18 @@ public class GetPrimaryKeysOperation extends 
MetadataOperation {
     setState(OperationState.RUNNING);
     try {
       IMetaStoreClient metastoreClient = 
getParentSession().getMetaStoreClient();
+      if (isAuthV2Enabled()) {
+        String cmdStr = "catalog : " + catalogName + ", schema : " + schemaName
+            + ", table : " + tableName;
+        if (tableName == null) {
+          // The request cannot be scoped to a privilege object without a 
table name; reject it
+          // instead of skipping the authorization check.
+          throw new HiveSQLException("Access denied: no table specified. " + 
cmdStr);
+        }
+        List<HivePrivilegeObject> privObjs = Collections.singletonList(
+            new HivePrivilegeObject(HivePrivilegeObjectType.TABLE_OR_VIEW, 
schemaName, tableName));
+        authorizeMetaGets(HiveOperationType.GET_COLUMNS, privObjs, cmdStr);
+      }
       PrimaryKeysRequest sqlReq = new PrimaryKeysRequest(schemaName, 
tableName);
       List<SQLPrimaryKey> pks = metastoreClient.getPrimaryKeys(sqlReq);
       if (pks == null) {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to