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 #5793][AUTHZ][BUG] PVM with nested scalar-subquery should not check src table privilege #5796

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -28,13 +28,27 @@ import org.apache.kyuubi.plugin.spark.authz.rule.permanentview.PermanentViewMark
* Transforming up [[PermanentViewMarker]]
*/
class RuleEliminatePermanentViewMarker(sparkSession: SparkSession) extends Rule[LogicalPlan] {

def eliminatePVM(plan: LogicalPlan): LogicalPlan = {
plan.transformUp {
case pvm: PermanentViewMarker =>
val ret = pvm.child.transformAllExpressions {
case s: SubqueryExpression => s.withNewPlan(eliminatePVM(s.plan))
}
// For each SubqueryExpression's PVM, we should mark as resolved to
// avoid check privilege of PVM's internal Subquery.
Authorization.markAuthChecked(ret)
ret
}
}

override def apply(plan: LogicalPlan): LogicalPlan = {
var matched = false
val eliminatedPVM = plan.transformUp {
case pvm: PermanentViewMarker =>
matched = true
pvm.child.transformAllExpressions {
case s: SubqueryExpression => s.withNewPlan(apply(s.plan))
case s: SubqueryExpression => s.withNewPlan(eliminatePVM(s.plan))
}
}
if (matched) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package org.apache.kyuubi.plugin.spark.authz.rule.permanentview

import org.apache.spark.sql.catalyst.catalog.CatalogTable
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
Expand All @@ -32,15 +33,24 @@ import org.apache.kyuubi.plugin.spark.authz.util.AuthZUtils._
*/
class RuleApplyPermanentViewMarker extends Rule[LogicalPlan] {

private def resolveSubqueryExpression(
plan: LogicalPlan,
catalogTable: CatalogTable): LogicalPlan = {
plan.transformAllExpressions {
case subquery: SubqueryExpression =>
subquery.withNewPlan(plan = PermanentViewMarker(
resolveSubqueryExpression(subquery.plan, catalogTable),
catalogTable))
}
}

override def apply(plan: LogicalPlan): LogicalPlan = {
plan mapChildren {
case p: PermanentViewMarker => p
case permanentView: View if hasResolvedPermanentView(permanentView) =>
val resolved = permanentView.transformAllExpressions {
case subquery: SubqueryExpression =>
subquery.withNewPlan(plan = PermanentViewMarker(subquery.plan, permanentView.desc))
}
PermanentViewMarker(resolved, permanentView.desc)
PermanentViewMarker(
resolveSubqueryExpression(permanentView, permanentView.desc),
permanentView.desc)
case other => apply(other)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1368,4 +1368,50 @@ class HiveCatalogRangerSparkExtensionSuite extends RangerSparkExtensionSuite {
}
}
}

test("[KYUUBI #5793][BUG] PVM with nested scala-subquery should not src table privilege") {
val db1 = defaultDb
val table1 = "table1"
val table2 = "table2"
val table3 = "table3"
val view1 = "perm_view"
withSingleCallEnabled {
withCleanTmpResources(
Seq(
(s"$db1.$table1", "table"),
(s"$db1.$table2", "table"),
(s"$db1.$table3", "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,
| name string,
| age int,
| scope int)
| """.stripMargin))
doAs(admin, sql(s"CREATE TABLE IF NOT EXISTS $db1.$table3(id int, scope int)"))
doAs(
admin,
sql(
s"""
|CREATE VIEW $db1.$view1
|AS
|SELECT id, name, max(scope) as max_scope, sum(age) sum_age
|FROM $db1.$table2
|WHERE scope in (
| SELECT max(scope) max_scope
| FROM $db1.$table1
| WHERE id IN (SELECT id FROM $db1.$table3)
|)
|GROUP BY id, name
|""".stripMargin))

checkAnswer(permViewOnlyUser, s"SELECT * FROM $db1.$view1", Array.empty[Row])
}
}
}
}