This is an automated email from the ASF dual-hosted git repository.
yao 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 754b57fdc [KYUUBI #5692][Bug] Authz not skip explain command
754b57fdc is described below
commit 754b57fdcea7647ad7856e07c9fcb979801d719c
Author: Angerszhuuuu <[email protected]>
AuthorDate: Mon Nov 20 10:33:51 2023 +0800
[KYUUBI #5692][Bug] Authz not skip explain command
### _Why are the changes needed?_
To close #5692
Currently explain command still will check privilege of child logical plan.
`EXPLAIN SELECT id FROM $db1.$table1`
```
CommandResult [plan#15], Execute ExplainCommand, [[Error occurred during
query planning: ], [Permission denied: user [someone] does not have [select]
privilege on [default/table1/id]]]
+- ExplainCommand 'Project ['id], SimpleMode
```
In this pr, we skip the plan under same execution id of the explain command
### _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 #5693 from AngersZhuuuu/KYUUBI-5692.
Closes #5692
93e6eaa71 [Angerszhuuuu] update
75a608719 [Angerszhuuuu] ODne
c9cc8dc10 [Angerszhuuuu] fix ut
0579bd3bf [Angerszhuuuu] follow comment
127c28db1 [Angerszhuuuu] Update RangerSparkExtensionSuite.scala
1353020eb [Angerszhuuuu] update
c7c0c1424 [Angerszhuuuu] Merge branch 'master' into KYUUBI-5692
b376964e6 [Angerszhuuuu] Update RangerSparkExtensionSuite.scala
697173471 [Angerszhuuuu] [KYUUBI #5692][Bug] Authz not skip explain command
Authored-by: Angerszhuuuu <[email protected]>
Signed-off-by: Kent Yao <[email protected]>
---
.../plugin/spark/authz/PrivilegesBuilder.scala | 9 ++++++++-
.../plugin/spark/authz/rule/Authorization.scala | 21 +++++++++++++++++++++
.../plugin/spark/authz/util/ReservedKeys.scala | 1 +
.../authz/ranger/RangerSparkExtensionSuite.scala | 22 ++++++++++++++++++++++
4 files changed, 52 insertions(+), 1 deletion(-)
diff --git
a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/PrivilegesBuilder.scala
b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/PrivilegesBuilder.scala
index df1738006..81dfa6e4e 100644
---
a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/PrivilegesBuilder.scala
+++
b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/PrivilegesBuilder.scala
@@ -22,11 +22,12 @@ import scala.collection.mutable.ArrayBuffer
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.catalyst.expressions.{Expression, NamedExpression}
import org.apache.spark.sql.catalyst.plans.logical._
+import org.apache.spark.sql.execution.command.ExplainCommand
import org.slf4j.LoggerFactory
import org.apache.kyuubi.plugin.spark.authz.OperationType.OperationType
import org.apache.kyuubi.plugin.spark.authz.PrivilegeObjectActionType._
-import org.apache.kyuubi.plugin.spark.authz.rule.Authorization.KYUUBI_AUTHZ_TAG
+import org.apache.kyuubi.plugin.spark.authz.rule.Authorization._
import
org.apache.kyuubi.plugin.spark.authz.rule.permanentview.PermanentViewMarker
import org.apache.kyuubi.plugin.spark.authz.serde._
import org.apache.kyuubi.plugin.spark.authz.util.AuthZUtils._
@@ -302,6 +303,12 @@ object PrivilegesBuilder {
val inputObjs = new ArrayBuffer[PrivilegeObject]
val outputObjs = new ArrayBuffer[PrivilegeObject]
val opType = plan match {
+ // ExplainCommand run will execute the plan, should avoid check
privilege for the plan.
+ case _: ExplainCommand =>
+ setExplainCommandExecutionId(spark)
+ OperationType.EXPLAIN
+ case _ if isExplainCommandChild(spark) =>
+ OperationType.EXPLAIN
// RunnableCommand
case cmd: Command => buildCommand(cmd, inputObjs, outputObjs, spark)
// Queries
diff --git
a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/rule/Authorization.scala
b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/rule/Authorization.scala
index 6c7d0afa6..d83541825 100644
---
a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/rule/Authorization.scala
+++
b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/rule/Authorization.scala
@@ -21,9 +21,11 @@ import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, Subquery}
import org.apache.spark.sql.catalyst.rules.Rule
import org.apache.spark.sql.catalyst.trees.TreeNodeTag
+import org.apache.spark.sql.execution.SQLExecution.EXECUTION_ID_KEY
import org.apache.kyuubi.plugin.spark.authz.rule.Authorization._
import
org.apache.kyuubi.plugin.spark.authz.rule.permanentview.PermanentViewMarker
+import org.apache.kyuubi.plugin.spark.authz.util.ReservedKeys._
abstract class Authorization(spark: SparkSession) extends Rule[LogicalPlan] {
override def apply(plan: LogicalPlan): LogicalPlan = {
@@ -65,4 +67,23 @@ object Authorization {
case p => p.getTagValue(KYUUBI_AUTHZ_TAG).nonEmpty
}
}
+
+ def setExplainCommandExecutionId(sparkSession: SparkSession): Unit = {
+ sparkSession.sparkContext.setLocalProperty(
+ KYUUBI_EXPLAIN_COMMAND_EXECUTION_ID,
+ executionId(sparkSession))
+ }
+
+ def isExplainCommandChild(sparkSession: SparkSession): Boolean = {
+ if (null == executionId(sparkSession)) {
+ false
+ } else {
+ executionId(sparkSession).equals(
+
sparkSession.sparkContext.getLocalProperty(KYUUBI_EXPLAIN_COMMAND_EXECUTION_ID))
+ }
+ }
+
+ private def executionId(sparkSession: SparkSession): String = {
+ sparkSession.sparkContext.getLocalProperty(EXECUTION_ID_KEY)
+ }
}
diff --git
a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/ReservedKeys.scala
b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/ReservedKeys.scala
index 60d989845..81259be2a 100644
---
a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/ReservedKeys.scala
+++
b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/ReservedKeys.scala
@@ -22,4 +22,5 @@ object ReservedKeys {
final val KYUUBI_SESSION_USER = "kyuubi.session.user"
final val KYUUBI_SESSION_SIGN_PUBLICKEY = "kyuubi.session.sign.publickey"
final val KYUUBI_SESSION_USER_SIGN = "kyuubi.session.user.sign"
+ final var KYUUBI_EXPLAIN_COMMAND_EXECUTION_ID =
"kyuubi.authz.command.explain.executionid"
}
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 d3a10cf9a..a48b35a50 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
@@ -1340,4 +1340,26 @@ class HiveCatalogRangerSparkExtensionSuite extends
RangerSparkExtensionSuite {
}
}
}
+
+ test("[KYUUBI #5692][Bug] Authz not skip explain command") {
+ val db1 = defaultDb
+ val table1 = "table1"
+ withSingleCallEnabled {
+ withCleanTmpResources(Seq((s"$db1.$table1", "table"))) {
+ doAs(admin, sql(s"CREATE TABLE IF NOT EXISTS $db1.$table1 (id int,
scope int)"))
+ val explainSql =
+ s"""
+ |EXPLAIN
+ |SELECT id FROM $db1.$table1
+ |""".stripMargin
+ doAs(admin, sql(explainSql))
+ val result = doAs(someone, sql(explainSql).collect()).head.getString(0)
+ assert(!result.contains("Error occurred during query planning"))
+ assert(!result.contains(s"does not have [select] privilege on
[$db1/$table1/id]"))
+ interceptContains[AccessControlException](
+ doAs(someone, sql(s"SELECT id FROM $db1.$table1").collect()))(
+ s"does not have [select] privilege on [$db1/$table1/id]")
+ }
+ }
+ }
}