Skip to content

Commit 0096db0

Browse files
committed
test RuleFunctionAuthorization in RangerSparkExtensionSuite.
1 parent 60df218 commit 0096db0

File tree

5 files changed

+257
-80
lines changed

5 files changed

+257
-80
lines changed

extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RuleFunctionAuthorization.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,7 @@ case class RuleFunctionAuthorization(spark: SparkSession) extends (LogicalPlan =
5050
}
5151

5252
addAccessRequest(inputs, isInput = true)
53-
checkPrivileges(requests, auditHandler)
54-
}
5553

56-
def checkPrivileges(
57-
requests: mutable.ArrayBuffer[AccessRequest],
58-
auditHandler: SparkRangerAuditHandler): Unit = {
5954
val requestArrays = requests.map(Seq(_))
6055
if (authorizeInSingleCall) {
6156
verify(requestArrays.flatten, auditHandler)

extensions/spark/kyuubi-spark-authz/src/test/gen/scala/org/apache/kyuubi/plugin/spark/authz/gen/PolicyJsonFileGenerator.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class PolicyJsonFileGenerator extends AnyFunSuite {
110110
policyAccessForPermViewAccessOnly,
111111
policyAccessForTable2AccessOnly,
112112
policyAccessForPaimonNsTable1SelectOnly,
113+
policyAccessForDefaultDbUDF,
113114
// row filter
114115
policyFilterForSrcTableKeyLessThan20,
115116
policyFilterForPermViewKeyLessThan20,
@@ -371,4 +372,20 @@ class PolicyJsonFileGenerator extends AnyFunSuite {
371372
users = List(table1OnlyUserForNs),
372373
accesses = allowTypes(select),
373374
delegateAdmin = true)))
375+
376+
private val policyAccessForDefaultDbUDF = KRangerPolicy(
377+
name = "defaultdb_udf",
378+
description = "Policy for default db udf",
379+
resources = Map(
380+
databaseRes(defaultDb),
381+
"udf" -> KRangerPolicyResource(values = List("kyuubi_func*"))),
382+
policyItems = List(
383+
KRangerPolicyItem(
384+
users = List(bob),
385+
accesses = allowTypes(select, update, create, drop, alter, index, lock, all, read, write),
386+
delegateAdmin = true),
387+
KRangerPolicyItem(
388+
users = List(kent),
389+
accesses = allowTypes(select),
390+
delegateAdmin = true)))
374391
}

extensions/spark/kyuubi-spark-authz/src/test/resources/sparkSql_hive_jenkins.json

Lines changed: 80 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,72 @@
510510
"isEnabled" : true,
511511
"version" : 1,
512512
"service" : "hive_jenkins",
513+
"name" : "defaultdb_udf",
514+
"policyType" : 0,
515+
"policyPriority" : 0,
516+
"description" : "Policy for default db udf",
517+
"isAuditEnabled" : true,
518+
"resources" : {
519+
"database" : {
520+
"values" : [ "default" ],
521+
"isExcludes" : false,
522+
"isRecursive" : false
523+
},
524+
"udf" : {
525+
"values" : [ "kyuubi_func*" ],
526+
"isExcludes" : false,
527+
"isRecursive" : false
528+
}
529+
},
530+
"policyItems" : [ {
531+
"accesses" : [ {
532+
"type" : "select",
533+
"isAllowed" : true
534+
}, {
535+
"type" : "update",
536+
"isAllowed" : true
537+
}, {
538+
"type" : "create",
539+
"isAllowed" : true
540+
}, {
541+
"type" : "drop",
542+
"isAllowed" : true
543+
}, {
544+
"type" : "alter",
545+
"isAllowed" : true
546+
}, {
547+
"type" : "index",
548+
"isAllowed" : true
549+
}, {
550+
"type" : "lock",
551+
"isAllowed" : true
552+
}, {
553+
"type" : "all",
554+
"isAllowed" : true
555+
}, {
556+
"type" : "read",
557+
"isAllowed" : true
558+
}, {
559+
"type" : "write",
560+
"isAllowed" : true
561+
} ],
562+
"users" : [ "bob" ],
563+
"delegateAdmin" : true
564+
}, {
565+
"accesses" : [ {
566+
"type" : "select",
567+
"isAllowed" : true
568+
} ],
569+
"users" : [ "kent" ],
570+
"delegateAdmin" : true
571+
} ],
572+
"isDenyAllElse" : false
573+
}, {
574+
"id" : 11,
575+
"guid" : "6512bd43-d9ca-36e0-ac99-0b0a82652dca",
576+
"isEnabled" : true,
577+
"version" : 1,
578+
"service" : "hive_jenkins",
513579
"name" : "src_key_less_than_20",
514580
"policyType" : 2,
515581
"policyPriority" : 0,
@@ -539,8 +605,8 @@
539605
} ],
540606
"isDenyAllElse" : false
541607
}, {
542-
"id" : 11,
543-
"guid" : "6512bd43-d9ca-36e0-ac99-0b0a82652dca",
608+
"id" : 12,
609+
"guid" : "c20ad4d7-6fe9-3759-aa27-a0c99bff6710",
544610
"isEnabled" : true,
545611
"version" : 1,
546612
"service" : "hive_jenkins",
@@ -573,8 +639,8 @@
573639
} ],
574640
"isDenyAllElse" : false
575641
}, {
576-
"id" : 12,
577-
"guid" : "c20ad4d7-6fe9-3759-aa27-a0c99bff6710",
642+
"id" : 13,
643+
"guid" : "c51ce410-c124-310e-8db5-e4b97fc2af39",
578644
"isEnabled" : true,
579645
"version" : 1,
580646
"service" : "hive_jenkins",
@@ -612,8 +678,8 @@
612678
} ],
613679
"isDenyAllElse" : false
614680
}, {
615-
"id" : 13,
616-
"guid" : "c51ce410-c124-310e-8db5-e4b97fc2af39",
681+
"id" : 14,
682+
"guid" : "aab32389-22bc-325a-af60-6eb525ffdc56",
617683
"isEnabled" : true,
618684
"version" : 1,
619685
"service" : "hive_jenkins",
@@ -651,8 +717,8 @@
651717
} ],
652718
"isDenyAllElse" : false
653719
}, {
654-
"id" : 14,
655-
"guid" : "aab32389-22bc-325a-af60-6eb525ffdc56",
720+
"id" : 15,
721+
"guid" : "9bf31c7f-f062-336a-96d3-c8bd1f8f2ff3",
656722
"isEnabled" : true,
657723
"version" : 1,
658724
"service" : "hive_jenkins",
@@ -690,8 +756,8 @@
690756
} ],
691757
"isDenyAllElse" : false
692758
}, {
693-
"id" : 15,
694-
"guid" : "9bf31c7f-f062-336a-96d3-c8bd1f8f2ff3",
759+
"id" : 16,
760+
"guid" : "c74d97b0-1eae-357e-84aa-9d5bade97baf",
695761
"isEnabled" : true,
696762
"version" : 1,
697763
"service" : "hive_jenkins",
@@ -729,8 +795,8 @@
729795
} ],
730796
"isDenyAllElse" : false
731797
}, {
732-
"id" : 16,
733-
"guid" : "c74d97b0-1eae-357e-84aa-9d5bade97baf",
798+
"id" : 17,
799+
"guid" : "70efdf2e-c9b0-3607-9795-c442636b55fb",
734800
"isEnabled" : true,
735801
"version" : 1,
736802
"service" : "hive_jenkins",
@@ -768,8 +834,8 @@
768834
} ],
769835
"isDenyAllElse" : false
770836
}, {
771-
"id" : 17,
772-
"guid" : "70efdf2e-c9b0-3607-9795-c442636b55fb",
837+
"id" : 18,
838+
"guid" : "6f4922f4-5568-361a-8cdf-4ad2299f6d23",
773839
"isEnabled" : true,
774840
"version" : 1,
775841
"service" : "hive_jenkins",

extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/FunctionPrivilegesBuilderSuite.scala

Lines changed: 72 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,13 @@
1717

1818
package org.apache.kyuubi.plugin.spark.authz
1919

20-
import scala.collection.mutable
21-
2220
import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
23-
import org.mockito.ArgumentMatchers.any
24-
import org.mockito.Mockito
25-
import org.mockito.invocation.InvocationOnMock
26-
import org.mockito.stubbing.Answer
2721
import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach}
2822
// scalastyle:off
2923
import org.scalatest.funsuite.AnyFunSuite
3024

3125
import org.apache.kyuubi.plugin.spark.authz.OperationType.QUERY
32-
import org.apache.kyuubi.plugin.spark.authz.ranger.{AccessRequest, AccessResource, AccessType, RuleFunctionAuthorization, SparkRangerAuditHandler}
26+
import org.apache.kyuubi.plugin.spark.authz.ranger.AccessType
3327

3428
abstract class FunctionPrivilegesBuilderSuite extends AnyFunSuite
3529
with SparkSessionProvider with BeforeAndAfterAll with BeforeAndAfterEach {
@@ -200,13 +194,15 @@ class HiveFunctionPrivilegesBuilderSuite extends FunctionPrivilegesBuilderSuite
200194
}
201195

202196
test("Built in and UDF Function Call Query") {
203-
val plan = sql(s"SELECT kyuubi_fun_0('TESTSTRING'), " +
204-
s"kyuubi_fun_0(value)," +
205-
s"abs(key)," +
206-
s"abs(-100)," +
207-
s"lower(value)," +
208-
s"lower('TESTSTRING') " +
209-
s"FROM $reusedTable").queryExecution.analyzed
197+
val plan = sql(
198+
s"""
199+
|SELECT
200+
| kyuubi_fun_0('TESTSTRING') AS col1,
201+
| kyuubi_fun_0(value) AS col2,
202+
| abs(key) AS col3, abs(-100) AS col4,
203+
| lower(value) AS col5,lower('TESTSTRING') AS col6
204+
|FROM $reusedTable
205+
|""".stripMargin).queryExecution.analyzed
210206
val (inputs, _, _) = PrivilegesBuilder.buildFunctions(plan, spark)
211207
assert(inputs.size === 2)
212208
inputs.foreach { po =>
@@ -219,36 +215,67 @@ class HiveFunctionPrivilegesBuilderSuite extends FunctionPrivilegesBuilderSuite
219215
}
220216
}
221217

222-
test("[KYUUBI #7186] Introduce RuleFunctionAuthorization") {
223-
224-
val ruleFunc = Mockito.spy[RuleFunctionAuthorization](RuleFunctionAuthorization(spark))
225-
Mockito.doAnswer(new Answer[Unit] {
226-
override def answer(invocation: InvocationOnMock): Unit = {
227-
val requests = invocation.getArgument[mutable.ArrayBuffer[AccessRequest]](0)
228-
requests.foreach { request =>
229-
// deny udf `reusedDb.kyuubi_fun_0`
230-
var database: String = request.getResource.asInstanceOf[AccessResource].getDatabase
231-
var udf: String = request.getResource.asInstanceOf[AccessResource].getUdf
232-
if (database.equalsIgnoreCase(reusedDb) && udf.equalsIgnoreCase("kyuubi_fun_0")) {
233-
throw new AccessControlException("Access denied")
234-
}
235-
}
236-
}
237-
}).when(ruleFunc).checkPrivileges(
238-
any[mutable.ArrayBuffer[AccessRequest]](),
239-
any[SparkRangerAuditHandler]())
240-
241-
val query1 = sql(s"SELECT " +
242-
s"${reusedDb}.kyuubi_fun_0('KYUUBI_STRING')," +
243-
s"${reusedDb}.kyuubi_fun_1('KYUUBI_STRING') ").queryExecution.analyzed
244-
intercept[AccessControlException] { ruleFunc.apply(query1) }
245-
246-
val query2 = sql(s"SELECT " +
247-
s"${reusedDb}.kyuubi_fun_0('KYUUBI_STRING')").queryExecution.analyzed
248-
intercept[AccessControlException] { ruleFunc.apply(query2) }
249-
250-
val query3 = sql(s"SELECT " +
251-
s"${reusedDb}.kyuubi_fun_1('KYUUBI_STRING')").queryExecution.analyzed
252-
ruleFunc.apply(query3)
218+
test("Function Call in Crate Table/View") {
219+
val plan1 = sql(
220+
s"""
221+
|CREATE TABLE table1 AS
222+
|SELECT
223+
| kyuubi_fun_0('KYUUBI_TESTSTRING'),
224+
| kyuubi_fun_0(value)
225+
|FROM $reusedTable
226+
|""".stripMargin).queryExecution.analyzed
227+
val (inputs1, _, _) = PrivilegesBuilder.buildFunctions(plan1, spark)
228+
assert(inputs1.size === 2)
229+
inputs1.foreach { po =>
230+
assert(po.actionType === PrivilegeObjectActionType.OTHER)
231+
assert(po.privilegeObjectType === PrivilegeObjectType.FUNCTION)
232+
assert(po.dbname startsWith reusedDb.toLowerCase)
233+
assert(po.objectName startsWith functionNamePrefix.toLowerCase)
234+
val accessType = ranger.AccessType(po, QUERY, isInput = true)
235+
assert(accessType === AccessType.SELECT)
236+
}
237+
val plan2 = sql("DROP TABLE IF EXISTS table1").queryExecution.analyzed
238+
val (inputs2, _, _) = PrivilegesBuilder.buildFunctions(plan2, spark)
239+
assert(inputs2.size === 0)
240+
241+
val plan3 = sql(
242+
s"""
243+
|CREATE VIEW view1 AS SELECT
244+
| kyuubi_fun_0('KYUUBI_TESTSTRING') AS fun1,
245+
| kyuubi_fun_0(value) AS fun2
246+
|FROM $reusedTable
247+
|""".stripMargin).queryExecution.analyzed
248+
val (inputs3, _, _) = PrivilegesBuilder.buildFunctions(plan3, spark)
249+
assert(inputs3.size === 2)
250+
inputs3.foreach { po =>
251+
assert(po.actionType === PrivilegeObjectActionType.OTHER)
252+
assert(po.privilegeObjectType === PrivilegeObjectType.FUNCTION)
253+
assert(po.dbname startsWith reusedDb.toLowerCase)
254+
assert(po.objectName startsWith functionNamePrefix.toLowerCase)
255+
val accessType = ranger.AccessType(po, QUERY, isInput = true)
256+
assert(accessType === AccessType.SELECT)
257+
}
258+
val plan4 = sql("DROP VIEW IF EXISTS view1").queryExecution.analyzed
259+
val (inputs4, _, _) = PrivilegesBuilder.buildFunctions(plan4, spark)
260+
assert(inputs4.size === 0)
261+
}
262+
263+
test("Function Call in INSERT OVERWRITE") {
264+
val plan = sql(
265+
s"""
266+
|INSERT OVERWRITE TABLE $reusedTable
267+
|SELECT key, kyuubi_fun_0(value)
268+
|FROM $reusedPartTable
269+
|""".stripMargin).queryExecution.analyzed
270+
val (inputsUpdate, _, _) = PrivilegesBuilder.buildFunctions(plan, spark)
271+
assert(inputsUpdate.size === 1)
272+
inputsUpdate.foreach { po =>
273+
assert(po.actionType === PrivilegeObjectActionType.OTHER)
274+
assert(po.privilegeObjectType === PrivilegeObjectType.FUNCTION)
275+
assert(po.dbname startsWith reusedDb.toLowerCase)
276+
assert(po.objectName startsWith functionNamePrefix.toLowerCase)
277+
val accessType = ranger.AccessType(po, QUERY, isInput = true)
278+
assert(accessType === AccessType.SELECT)
279+
}
253280
}
254281
}

0 commit comments

Comments
 (0)