Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[KYUUBI #5594][AUTHZ] BuildQuery should respect normal node's input #5627

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3cbba42
Update PrivilegesBuilder.scala
AngersZhuuuu Nov 1, 2023
80013b9
Update PrivilegesBuilder.scala
AngersZhuuuu Nov 1, 2023
c549b6a
update
AngersZhuuuu Nov 1, 2023
4dd47a1
update
AngersZhuuuu Nov 1, 2023
6f6a36e
Merge branch 'master' into KYUUBI-5594]-AUTH]BuildQuery-should-respec…
AngersZhuuuu Nov 1, 2023
c2c6fa4
Update PrivilegesBuilder.scala
AngersZhuuuu Nov 1, 2023
dcca394
Update PrivilegesBuilder.scala
AngersZhuuuu Nov 1, 2023
404f1ea
Update PrivilegesBuilder.scala
AngersZhuuuu Nov 2, 2023
86fc475
Update PrivilegesBuilder.scala
AngersZhuuuu Nov 2, 2023
c34f32e
Merge branch 'master' into KYUUBI-5594
AngersZhuuuu Nov 6, 2023
60872ef
Update RangerSparkExtensionSuite.scala
AngersZhuuuu Nov 6, 2023
270f21d
Update RangerSparkExtensionSuite.scala
AngersZhuuuu Nov 6, 2023
8785ad1
Update PrivilegesBuilder.scala
AngersZhuuuu Nov 6, 2023
29b67c4
Update PrivilegesBuilder.scala
AngersZhuuuu Nov 6, 2023
9f87182
Revert "Update PrivilegesBuilder.scala"
AngersZhuuuu Nov 7, 2023
f481283
Revert "Update PrivilegesBuilder.scala"
AngersZhuuuu Nov 7, 2023
0bb7624
Revert "Revert "Update PrivilegesBuilder.scala""
AngersZhuuuu Nov 7, 2023
04184e3
update
AngersZhuuuu Nov 7, 2023
93fc689
Merge branch 'master' into KYUUBI-5594
AngersZhuuuu Nov 23, 2023
8214228
update
AngersZhuuuu Nov 24, 2023
b00bf5e
Update PrivilegesBuilder.scala
AngersZhuuuu Nov 24, 2023
d6e984e
update
AngersZhuuuu Nov 24, 2023
3bafa7c
update
AngersZhuuuu Nov 24, 2023
8e53236
update
AngersZhuuuu Nov 27, 2023
0ebdd5d
Merge branch 'master' into KYUUBI-5594
AngersZhuuuu Nov 27, 2023
e0f28a6
Merge branch 'master' into KYUUBI-5594
AngersZhuuuu Nov 29, 2023
d0b022e
Update RuleApplyPermanentViewMarker.scala
AngersZhuuuu Nov 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ package org.apache.kyuubi.plugin.spark.authz
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.expressions.{AttributeSet, Expression, NamedExpression}
import org.apache.spark.sql.catalyst.plans.logical._
import org.apache.spark.sql.execution.command.ExplainCommand
import org.slf4j.LoggerFactory
Expand Down Expand Up @@ -69,12 +69,19 @@ object PrivilegesBuilder {
if (projectionList.isEmpty) {
privilegeObjects += PrivilegeObject(table, plan.output.map(_.name))
} else {
val cols = (projectionList ++ conditionList).flatMap(collectLeaves)
.filter(plan.outputSet.contains).map(_.name).distinct
val cols = columnPrune(projectionList ++ conditionList, plan.outputSet)
privilegeObjects += PrivilegeObject(table, cols)
}
}

def columnPrune(projectionList: Seq[NamedExpression], output: AttributeSet): Seq[String] = {
(projectionList ++ conditionList)
.flatMap(collectLeaves)
.filter(output.contains)
.map(_.name)
.distinct
}

plan match {
case p if p.getTagValue(KYUUBI_AUTHZ_TAG).nonEmpty =>

Expand Down Expand Up @@ -125,7 +132,17 @@ object PrivilegesBuilder {

case p =>
for (child <- p.children) {
buildQuery(child, privilegeObjects, projectionList, conditionList, spark)
val childCols = columnPrune(projectionList ++ conditionList, child.outputSet)
if (childCols.isEmpty) {
buildQuery(
child,
privilegeObjects,
p.inputSet.map(_.toAttribute).toSeq,
conditionList,
spark)
} else {
buildQuery(child, privilegeObjects, projectionList, conditionList, spark)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ import java.nio.file.Path
import scala.util.Try

import org.apache.hadoop.security.UserGroupInformation
import org.apache.spark.sql.{Row, SparkSessionExtensions}
import org.apache.spark.sql.{DataFrame, Row, SparkSessionExtensions}
import org.apache.spark.sql.catalyst.analysis.NoSuchTableException
import org.apache.spark.sql.catalyst.catalog.HiveTableRelation
import org.apache.spark.sql.catalyst.expressions.PythonUDF
import org.apache.spark.sql.catalyst.plans.logical.Statistics
import org.apache.spark.sql.execution.columnar.InMemoryRelation
import org.apache.spark.sql.execution.datasources.LogicalRelation
import org.apache.spark.sql.functions.col
import org.apache.spark.sql.types.{IntegerType, StructField, StructType}
import org.scalatest.BeforeAndAfterAll
// scalastyle:off
import org.scalatest.funsuite.AnyFunSuite
Expand Down Expand Up @@ -1368,4 +1371,80 @@ class HiveCatalogRangerSparkExtensionSuite extends RangerSparkExtensionSuite {
}
}
}

test("[KYUUBI #5594][AUTHZ] BuildQuery should respect normal node's input ") {
assume(!isSparkV35OrGreater, "mapInPandas not supported after spark 3.5")
val db1 = defaultDb
val table1 = "table1"
val view1 = "view1"
withSingleCallEnabled {
withCleanTmpResources(Seq((s"$db1.$table1", "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 VIEW $db1.$view1 AS SELECT * FROM $db1.$table1"))

val table = spark.read.table(s"$db1.$table1")
val mapTableInPandasUDF = PythonUDF(
"mapInPandasUDF",
null,
StructType(Seq(StructField("id", IntegerType), StructField("scope", IntegerType))),
table.queryExecution.analyzed.output,
205,
true)
interceptContains[AccessControlException](
doAs(
someone,
invokeAs(
table,
"mapInPandas",
(classOf[PythonUDF], mapTableInPandasUDF))
.asInstanceOf[DataFrame].select(col("id"), col("scope")).limit(1).show(true)))(
s"does not have [select] privilege on [$db1/$table1/id,$db1/$table1/scope]")

val view = spark.read.table(s"$db1.$view1")
val mapViewInPandasUDF = PythonUDF(
"mapInPandasUDF",
null,
StructType(Seq(StructField("id", IntegerType), StructField("scope", IntegerType))),
view.queryExecution.analyzed.output,
205,
true)
interceptContains[AccessControlException](
doAs(
someone,
invokeAs(
view,
"mapInPandas",
(classOf[PythonUDF], mapViewInPandasUDF))
.asInstanceOf[DataFrame].select(col("id"), col("scope")).limit(1).show(true)))(
s"does not have [select] privilege on [$db1/$view1/id,$db1/$view1/scope]")
}
}
}

test("[KYUUBI #5594][AUTHZ] BuildQuery should respect sort agg input") {
val db1 = defaultDb
val table1 = "table1"
val view1 = "view1"
withSingleCallEnabled {
withCleanTmpResources(Seq((s"$db1.$table1", "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 VIEW $db1.$view1 AS SELECT * FROM $db1.$table1"))
interceptContains[AccessControlException](
doAs(
someone,
sql(s"SELECT count(*) FROM $db1.$table1 WHERE id > 1").collect()))(
s"does not have [select] privilege on [$db1/$table1/id,$db1/$table1/scope]")
interceptContains[AccessControlException](
doAs(
someone,
sql(s"SELECT count(*) FROM $db1.$view1 WHERE id > 1").collect()))(
s"does not have [select] privilege on [$db1/$view1/id,$db1/$view1/scope]")
interceptContains[AccessControlException](
doAs(
someone,
sql(s"SELECT count(id) FROM $db1.$view1 WHERE id > 1").collect()))(
s"does not have [select] privilege on [$db1/$view1/id]")
}
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a UT, the plan is


GlobalLimit 1
+- LocalLimit 1
   +- Project [cast(id#22 as string) AS id#30, cast(scope#23 as string) AS scope#31]
      +- MapInPandas mapInPandasUDF(id#17, scope#18)#21, [id#22, scope#23]
         +- HiveTableRelation [`spark_catalog`.`default`.`table1`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#17, scope#18], Partition Cols: []]

Without this pr, this query only extract table, miss column privilege

"Permission denied: user [someone] does not have [select] privilege on [default/table1]" did not contain "does not have [select] privilege on [default/table1/id,default/table1/scope]"
ScalaTestFailureLocation: org.apache.kyuubi.plugin.spark.authz.ranger.HiveCatalogRangerSparkExtensionSuite at (RangerSparkExtensionSuite.scala:1125)
org.scalatest.exceptions.TestFailedException: "Permission denied: user [someone] does not have [select] privilege on [default/table1]" did not contain "does not have [select] privilege on [default/table1/id,default/table1/scope]"
	at org.scalatest.Assertions.newAssertionFailedException(Assertions.scala:472)

}
Loading