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

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


The following commit(s) were added to refs/heads/master by this push:
     new 8da180126 [KYUUBI #5503][AUTHZ] Check plan auth checked should not set 
tag to all child nodes
8da180126 is described below

commit 8da1801268c87ecfa39e5730e705b669a118d22b
Author: Angerszhuuuu <[email protected]>
AuthorDate: Sun Oct 29 15:45:03 2023 +0800

    [KYUUBI #5503][AUTHZ] Check plan auth checked should not set tag to all 
child nodes
    
    ### _Why are the changes needed?_
    To close #5503
    
    For lateral sql won't check table2's privilege
    ```
    test("xxx") {
        val db1 = defaultDb
        val table1 = "table1"
        val table2 = "table2"
        val view1 = "view1"
        withCleanTmpResources(
          Seq((s"$db1.$table1", "table"), (s"$db1.$table2", "table"), 
(s"$db1.$view1", "view"))) {
          doAs(admin, sql(s"CREATE TABLE IF NOT EXISTS $db1.$table1 (id int, 
scope int)"))
          doAs(admin, sql(s"CREATE TABLE IF NOT EXISTS $db1.$table2 (id int, 
age int)"))
          doAs(admin, sql(
            s"""
               |SELECT t1.id, age
               |FROM $db1.$table1 t1,
               |LATERAL (
               |  SELECT *
               |  FROM $db1.$table2 t2
               |  WHERE t1.id = t2.id
               |)
               |""".stripMargin).explain(true))
        }
      }
    ```
    
    It was caused by  https://github.com/apache/kyuubi/pull/4529
    
![image](https://github.com/apache/kyuubi/assets/46485123/28cdc061-2c2a-44d3-a8d2-a07f5f6f058c)
    
    But after we fix #5417 and #5415, we didn't need this change. We should 
remove it.
    
    ### _How was this patch tested?_
    - [x] Add some test cases that check the changes thoroughly including 
negative and positive cases if possible
    
    - [ ] Add screenshots for manual tests if appropriate
    
    - [ ] [Run 
test](https://kyuubi.readthedocs.io/en/master/contributing/code/testing.html#running-tests)
 locally before make a pull request
    
    ### _Was this patch authored or co-authored using generative AI tooling?_
    No
    
    Closes #5540 from AngersZhuuuu/TEST_REVERT_4504.
    
    Closes #5503
    
    63fa03771 [Angerszhuuuu] Update RangerSparkExtensionSuite.scala
    f3118d293 [Angerszhuuuu] Update RuleAuthorization.scala
    f6b6dcccc [Angerszhuuuu] follow comment
    2c7ae5d50 [Angerszhuuuu] Update RuleAuthorization.scala
    bddc11733 [Angerszhuuuu] Update RangerSparkExtensionSuite.scala
    6bb0c39b4 [Angerszhuuuu] Update RangerSparkExtensionSuite.scala
    42c924f45 [Angerszhuuuu] Update RangerSparkExtensionSuite.scala
    bbb2c3170 [Angerszhuuuu] [KYUUBI #5503][AUTHZ] Check plan auth checked 
should not set tag to all child nodes
    
    Authored-by: Angerszhuuuu <[email protected]>
    Signed-off-by: Cheng Pan <[email protected]>
---
 .../spark/authz/ranger/RuleAuthorization.scala     | 18 ++++++--
 .../authz/ranger/RangerSparkExtensionSuite.scala   | 54 ++++++++++++++++++++--
 2 files changed, 62 insertions(+), 10 deletions(-)

diff --git 
a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RuleAuthorization.scala
 
b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RuleAuthorization.scala
index 3203108df..91221c522 100644
--- 
a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RuleAuthorization.scala
+++ 
b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RuleAuthorization.scala
@@ -30,6 +30,8 @@ import org.apache.kyuubi.plugin.spark.authz.ObjectType._
 import org.apache.kyuubi.plugin.spark.authz.ranger.RuleAuthorization._
 import org.apache.kyuubi.plugin.spark.authz.ranger.SparkRangerAdminPlugin._
 import org.apache.kyuubi.plugin.spark.authz.util.AuthZUtils._
+import org.apache.kyuubi.plugin.spark.authz.util.PermanentViewMarker
+
 class RuleAuthorization(spark: SparkSession) extends Rule[LogicalPlan] {
   override def apply(plan: LogicalPlan): LogicalPlan = {
     plan match {
@@ -41,7 +43,7 @@ class RuleAuthorization(spark: SparkSession) extends 
Rule[LogicalPlan] {
 
 object RuleAuthorization {
 
-  val KYUUBI_AUTHZ_TAG = TreeNodeTag[Boolean]("__KYUUBI_AUTHZ_TAG")
+  val KYUUBI_AUTHZ_TAG = TreeNodeTag[Unit]("__KYUUBI_AUTHZ_TAG")
 
   private def checkPrivileges(spark: SparkSession, plan: LogicalPlan): 
LogicalPlan = {
     val auditHandler = new SparkRangerAuditHandler
@@ -97,13 +99,19 @@ object RuleAuthorization {
   }
 
   private def markAuthChecked(plan: LogicalPlan): LogicalPlan = {
-    plan.transformUp { case p =>
-      p.setTagValue(KYUUBI_AUTHZ_TAG, true)
-      p
+    plan match {
+      case _: PermanentViewMarker =>
+        plan.transformUp { case p =>
+          p.setTagValue(KYUUBI_AUTHZ_TAG, ())
+          p
+        }
+      case _ =>
+        plan.setTagValue(KYUUBI_AUTHZ_TAG, ())
     }
+    plan
   }
 
   private def isAuthChecked(plan: LogicalPlan): Boolean = {
-    plan.find(_.getTagValue(KYUUBI_AUTHZ_TAG).contains(true)).nonEmpty
+    plan.find(_.getTagValue(KYUUBI_AUTHZ_TAG).nonEmpty).nonEmpty
   }
 }
diff --git 
a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RangerSparkExtensionSuite.scala
 
b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RangerSparkExtensionSuite.scala
index 07c8efeda..8923819c3 100644
--- 
a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RangerSparkExtensionSuite.scala
+++ 
b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RangerSparkExtensionSuite.scala
@@ -113,12 +113,12 @@ abstract class RangerSparkExtensionSuite extends 
AnyFunSuite
       if (i == 1) {
         assert(logicalPlan.getTagValue(KYUUBI_AUTHZ_TAG).isEmpty)
       } else {
-        assert(logicalPlan.getTagValue(KYUUBI_AUTHZ_TAG).getOrElse(false))
+        assert(logicalPlan.getTagValue(KYUUBI_AUTHZ_TAG).nonEmpty)
       }
       rule.apply(logicalPlan)
     }
 
-    assert(logicalPlan.getTagValue(KYUUBI_AUTHZ_TAG).getOrElse(false))
+    assert(logicalPlan.getTagValue(KYUUBI_AUTHZ_TAG).nonEmpty)
   }
 
   test("[KYUUBI #3226]: Another session should also check even if the plan is 
cached.") {
@@ -140,7 +140,7 @@ abstract class RangerSparkExtensionSuite extends AnyFunSuite
           // session1: first query, should auth once.[LogicalRelation]
           val df = sql(select)
           val plan1 = df.queryExecution.optimizedPlan
-          assert(plan1.getTagValue(KYUUBI_AUTHZ_TAG).getOrElse(false))
+          assert(plan1.getTagValue(KYUUBI_AUTHZ_TAG).nonEmpty)
 
           // cache
           df.cache()
@@ -148,7 +148,7 @@ abstract class RangerSparkExtensionSuite extends AnyFunSuite
           // session1: second query, should auth once.[InMemoryRelation]
           // (don't need to check in again, but it's okay to check in once)
           val plan2 = sql(select).queryExecution.optimizedPlan
-          assert(plan1 != plan2 && 
plan2.getTagValue(KYUUBI_AUTHZ_TAG).getOrElse(false))
+          assert(plan1 != plan2 && 
plan2.getTagValue(KYUUBI_AUTHZ_TAG).nonEmpty)
 
           // session2: should auth once.
           val otherSessionDf = spark.newSession().sql(select)
@@ -159,7 +159,7 @@ abstract class RangerSparkExtensionSuite extends AnyFunSuite
           // make sure it use cache.
           assert(plan3.isInstanceOf[InMemoryRelation])
           // auth once only.
-          assert(plan3.getTagValue(KYUUBI_AUTHZ_TAG).getOrElse(false))
+          assert(plan3.getTagValue(KYUUBI_AUTHZ_TAG).nonEmpty)
         })
     }
   }
@@ -952,4 +952,48 @@ class HiveCatalogRangerSparkExtensionSuite extends 
RangerSparkExtensionSuite {
       }
     }
   }
+
+  test("[KYUUBI #5503][AUTHZ] Check plan auth checked should not set tag to 
all child nodes") {
+    assume(isSparkV32OrGreater, "Spark 3.1 not support lateral subquery.")
+    val db1 = defaultDb
+    val table1 = "table1"
+    val perm_view = "perm_view"
+    withSingleCallEnabled {
+      withCleanTmpResources(
+        Seq((s"$db1.$table1", "table"), (s"$db1.$perm_view", "view"))) {
+        doAs(admin, sql(s"CREATE TABLE IF NOT EXISTS $db1.$table1 (id int, 
scope int)"))
+        doAs(admin, sql(s"CREATE VIEW $db1.$perm_view AS SELECT * FROM 
$db1.$table1"))
+        interceptContains[AccessControlException](
+          doAs(
+            someone,
+            sql(
+              s"""
+                 |SELECT t1.id
+                 |FROM $db1.$table1 t1,
+                 |LATERAL (
+                 |  SELECT *
+                 |  FROM $db1.$perm_view t2
+                 |  WHERE t1.id = t2.id
+                 |)
+                 |""".stripMargin).show()))(
+          s"does not have [select] privilege on " +
+            s"[$db1/$perm_view/id,$db1/$perm_view/scope]")
+        interceptContains[AccessControlException](
+          doAs(
+            permViewOnlyUser,
+            sql(
+              s"""
+                 |SELECT t1.id
+                 |FROM $db1.$table1 t1,
+                 |LATERAL (
+                 |  SELECT *
+                 |  FROM $db1.$perm_view t2
+                 |  WHERE t1.id = t2.id
+                 |)
+                 |""".stripMargin).show()))(
+          s"does not have [select] privilege on " +
+            s"[$db1/$table1/id,$db1/$table1/scope]")
+      }
+    }
+  }
 }

Reply via email to