diff --git a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RuleApplyPermanentViewMarker.scala b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RuleApplyPermanentViewMarker.scala index 917410807..679b5d65d 100644 --- a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RuleApplyPermanentViewMarker.scala +++ b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RuleApplyPermanentViewMarker.scala @@ -17,7 +17,7 @@ package org.apache.kyuubi.plugin.spark.authz.ranger -import org.apache.spark.sql.catalyst.expressions.ScalarSubquery +import org.apache.spark.sql.catalyst.expressions.SubqueryExpression import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, View} import org.apache.spark.sql.catalyst.rules.Rule @@ -38,11 +38,11 @@ class RuleApplyPermanentViewMarker extends Rule[LogicalPlan] { case p: PermanentViewMarker => p case permanentView: View if hasResolvedPermanentView(permanentView) => val resolvedSubquery = permanentView.transformAllExpressions { - case scalarSubquery: ScalarSubquery => + case subquery: SubqueryExpression => // TODO: Currently, we do not do an auth check in the subquery // as the main query part also secures it. But for performance consideration, // we also pre-check it in subqueries and fail fast with negative privileges. - scalarSubquery.copy(plan = PermanentViewMarker(scalarSubquery.plan, null)) + subquery.withNewPlan(plan = PermanentViewMarker(subquery.plan, null)) } PermanentViewMarker(resolvedSubquery, resolvedSubquery.desc) case other => apply(other) 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 d109a7f2b..8e1fe0587 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 @@ -748,7 +748,7 @@ class HiveCatalogRangerSparkExtensionSuite extends RangerSparkExtensionSuite { } } - test("[KYUUBI #5417] should not check dependent subquery plan privilege") { + test("[KYUUBI #5417] should not check scalar-subquery in permanent view") { val db1 = defaultDb val table1 = "table1" val table2 = "table2" @@ -791,4 +791,48 @@ class HiveCatalogRangerSparkExtensionSuite extends RangerSparkExtensionSuite { assert(e2.getMessage.contains(s"does not have [select] privilege on [$db1/$view1/new_id]")) } } + + test("[KYUUBI #5417] should not check in-subquery in permanent view") { + 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, scope int)")) + + val e1 = intercept[AccessControlException] { + doAs( + someone, + sql( + s""" + |WITH temp AS ( + | SELECT max(scope) max_scope + | FROM $db1.$table1) + |SELECT id as new_id FROM $db1.$table2 + |WHERE scope in (SELECT max_scope FROM temp) + |""".stripMargin).show()) + } + // Will first check subquery privilege. + assert(e1.getMessage.contains(s"does not have [select] privilege on [$db1/$table1/scope]")) + + doAs( + admin, + sql( + s""" + |CREATE VIEW $db1.$view1 + |AS + |WITH temp AS ( + | SELECT max(scope) max_scope + | FROM $db1.$table1) + |SELECT id as new_id FROM $db1.$table2 + |WHERE scope in (SELECT max_scope FROM temp) + |""".stripMargin)) + // Will just check permanent view privilege. + val e2 = intercept[AccessControlException]( + doAs(someone, sql(s"SELECT * FROM $db1.$view1".stripMargin).show())) + assert(e2.getMessage.contains(s"does not have [select] privilege on [$db1/$view1/new_id]")) + } + } }