From 1b3de28b2cccb0b25643f2bee7aead36601e8bf8 Mon Sep 17 00:00:00 2001 From: davidyuan Date: Thu, 6 Mar 2025 22:35:48 +0800 Subject: [PATCH] [KYUUBI #6958] Test INSERT TABLE ### Why are the changes needed? Currently , ranger check missing paimon insert table command, add test cases #6958 ### How was this patch tested? 1. Test INSERT INTO: 1.1 table1OnlyUserForNs could select table1, try to insert table1 1.2 someone has no any permission, try to insert table1 2. Test INSERT OVERWRITE: 2.1 table1OnlyUserForNs could select table1, try to insert table2 2.2 someone has no any permiession, try select table1 then insert table2 ### Was this patch authored or co-authored using generative AI tooling? No Closes #6959 from davidyuan1223/test_insert. Closes #6958 d1f41ba81 [davidyuan] Merge branch 'master' into test_insert b56e701d4 [davidyuan] Test Insert Table 8306210ee [davidyuan] update Authored-by: davidyuan Signed-off-by: Cheng Pan --- .../authz/gen/PolicyJsonFileGenerator.scala | 13 ++++ .../test/resources/sparkSql_hive_jenkins.json | 66 ++++++++++++++----- .../spark/authz/RangerTestResources.scala | 1 + ...imonCatalogRangerSparkExtensionSuite.scala | 57 ++++++++++++++++ 4 files changed, 122 insertions(+), 15 deletions(-) diff --git a/extensions/spark/kyuubi-spark-authz/src/test/gen/scala/org/apache/kyuubi/plugin/spark/authz/gen/PolicyJsonFileGenerator.scala b/extensions/spark/kyuubi-spark-authz/src/test/gen/scala/org/apache/kyuubi/plugin/spark/authz/gen/PolicyJsonFileGenerator.scala index 079def2b9..edff7d8a0 100644 --- a/extensions/spark/kyuubi-spark-authz/src/test/gen/scala/org/apache/kyuubi/plugin/spark/authz/gen/PolicyJsonFileGenerator.scala +++ b/extensions/spark/kyuubi-spark-authz/src/test/gen/scala/org/apache/kyuubi/plugin/spark/authz/gen/PolicyJsonFileGenerator.scala @@ -109,6 +109,7 @@ class PolicyJsonFileGenerator extends AnyFunSuite { policyAccessForDefaultBobSelect, policyAccessForPermViewAccessOnly, policyAccessForTable2AccessOnly, + policyAccessForPaimonNsTable1SelectOnly, // row filter policyFilterForSrcTableKeyLessThan20, policyFilterForPermViewKeyLessThan20, @@ -358,4 +359,16 @@ class PolicyJsonFileGenerator extends AnyFunSuite { users = List(table2OnlyUser), accesses = allowTypes(select), delegateAdmin = true))) + + private val policyAccessForPaimonNsTable1SelectOnly = KRangerPolicy( + name = "someone_access_table1_in_ns", + resources = Map( + databaseRes(icebergNamespace, hudiNamespace, paimonNamespace, deltaNamespace), + tableRes("table1"), + allColumnRes), + policyItems = List( + KRangerPolicyItem( + users = List(table1OnlyUserForNs), + accesses = allowTypes(select), + delegateAdmin = true))) } diff --git a/extensions/spark/kyuubi-spark-authz/src/test/resources/sparkSql_hive_jenkins.json b/extensions/spark/kyuubi-spark-authz/src/test/resources/sparkSql_hive_jenkins.json index 07ceb5580..16bdd5087 100644 --- a/extensions/spark/kyuubi-spark-authz/src/test/resources/sparkSql_hive_jenkins.json +++ b/extensions/spark/kyuubi-spark-authz/src/test/resources/sparkSql_hive_jenkins.json @@ -474,6 +474,42 @@ "isEnabled" : true, "version" : 1, "service" : "hive_jenkins", + "name" : "someone_access_table1_in_ns", + "policyType" : 0, + "policyPriority" : 0, + "isAuditEnabled" : true, + "resources" : { + "column" : { + "values" : [ "*" ], + "isExcludes" : false, + "isRecursive" : false + }, + "database" : { + "values" : [ "iceberg_ns", "hudi_ns", "paimon_ns", "delta_ns" ], + "isExcludes" : false, + "isRecursive" : false + }, + "table" : { + "values" : [ "table1" ], + "isExcludes" : false, + "isRecursive" : false + } + }, + "policyItems" : [ { + "accesses" : [ { + "type" : "select", + "isAllowed" : true + } ], + "users" : [ "user_table1_only_for_ns" ], + "delegateAdmin" : true + } ], + "isDenyAllElse" : false + }, { + "id" : 10, + "guid" : "d3d94468-02a4-3259-b55d-38e6d163e820", + "isEnabled" : true, + "version" : 1, + "service" : "hive_jenkins", "name" : "src_key_less_than_20", "policyType" : 2, "policyPriority" : 0, @@ -503,8 +539,8 @@ } ], "isDenyAllElse" : false }, { - "id" : 10, - "guid" : "d3d94468-02a4-3259-b55d-38e6d163e820", + "id" : 11, + "guid" : "6512bd43-d9ca-36e0-ac99-0b0a82652dca", "isEnabled" : true, "version" : 1, "service" : "hive_jenkins", @@ -537,8 +573,8 @@ } ], "isDenyAllElse" : false }, { - "id" : 11, - "guid" : "6512bd43-d9ca-36e0-ac99-0b0a82652dca", + "id" : 12, + "guid" : "c20ad4d7-6fe9-3759-aa27-a0c99bff6710", "isEnabled" : true, "version" : 1, "service" : "hive_jenkins", @@ -576,8 +612,8 @@ } ], "isDenyAllElse" : false }, { - "id" : 12, - "guid" : "c20ad4d7-6fe9-3759-aa27-a0c99bff6710", + "id" : 13, + "guid" : "c51ce410-c124-310e-8db5-e4b97fc2af39", "isEnabled" : true, "version" : 1, "service" : "hive_jenkins", @@ -615,8 +651,8 @@ } ], "isDenyAllElse" : false }, { - "id" : 13, - "guid" : "c51ce410-c124-310e-8db5-e4b97fc2af39", + "id" : 14, + "guid" : "aab32389-22bc-325a-af60-6eb525ffdc56", "isEnabled" : true, "version" : 1, "service" : "hive_jenkins", @@ -654,8 +690,8 @@ } ], "isDenyAllElse" : false }, { - "id" : 14, - "guid" : "aab32389-22bc-325a-af60-6eb525ffdc56", + "id" : 15, + "guid" : "9bf31c7f-f062-336a-96d3-c8bd1f8f2ff3", "isEnabled" : true, "version" : 1, "service" : "hive_jenkins", @@ -693,8 +729,8 @@ } ], "isDenyAllElse" : false }, { - "id" : 15, - "guid" : "9bf31c7f-f062-336a-96d3-c8bd1f8f2ff3", + "id" : 16, + "guid" : "c74d97b0-1eae-357e-84aa-9d5bade97baf", "isEnabled" : true, "version" : 1, "service" : "hive_jenkins", @@ -732,8 +768,8 @@ } ], "isDenyAllElse" : false }, { - "id" : 16, - "guid" : "c74d97b0-1eae-357e-84aa-9d5bade97baf", + "id" : 17, + "guid" : "70efdf2e-c9b0-3607-9795-c442636b55fb", "isEnabled" : true, "version" : 1, "service" : "hive_jenkins", @@ -1176,4 +1212,4 @@ "version" : 1 }, "auditMode" : "audit-default" -} +} \ No newline at end of file diff --git a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/RangerTestResources.scala b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/RangerTestResources.scala index c2ed9aa0b..895aa923f 100644 --- a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/RangerTestResources.scala +++ b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/RangerTestResources.scala @@ -29,6 +29,7 @@ object RangerTestUsers { val defaultTableOwner = "default_table_owner" val permViewOnlyUser = "user_perm_view_only" val table2OnlyUser = "user_table2_only" + val table1OnlyUserForNs = "user_table1_only_for_ns" // non-authorized users val invisibleUser = "i_am_invisible" diff --git a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/PaimonCatalogRangerSparkExtensionSuite.scala b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/PaimonCatalogRangerSparkExtensionSuite.scala index dab3d33db..4f8da3bc2 100644 --- a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/PaimonCatalogRangerSparkExtensionSuite.scala +++ b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/PaimonCatalogRangerSparkExtensionSuite.scala @@ -299,6 +299,63 @@ class PaimonCatalogRangerSparkExtensionSuite extends RangerSparkExtensionSuite { } } + test("INSERT INTO") { + withCleanTmpResources(Seq( + (s"$catalogV2.$namespace1.$table1", "table"))) { + val createTable = createTableSql(namespace1, table1) + doAs(admin, sql(createTable)) + val insertSql = + s""" + |INSERT INTO $catalogV2.$namespace1.$table1 VALUES + |(1, "a"), (2, "b"); + |""".stripMargin + // Test user have select permission to insert + doAs(table1OnlyUserForNs, sql(s"SELECT * FROM $catalogV2.$namespace1.$table1")) + interceptEndsWith[AccessControlException] { + doAs(table1OnlyUserForNs, sql(insertSql)) + }(s"does not have [update] privilege on [$namespace1/$table1]") + + // Test user have not any permission to insert + interceptEndsWith[AccessControlException] { + doAs(someone, sql(insertSql)) + }(s"does not have [update] privilege on [$namespace1/$table1]") + + doAs(admin, sql(insertSql)) + } + } + + test("INSERT OVERWRITE") { + val table2 = "table2" + withCleanTmpResources(Seq( + (s"$catalogV2.$namespace1.$table1", "table"), + (s"$catalogV2.$namespace1.$table2", "table"))) { + val createTable1 = createTableSql(namespace1, table1) + val createTable2 = createTableSql(namespace1, table2) + doAs(admin, sql(createTable1)) + doAs(admin, sql(createTable2)) + + doAs(admin, sql(s"INSERT INTO $catalogV2.$namespace1.$table1 VALUES (1, 'a'), (2, 'b')")) + + val insertOverwriteSql = + s""" + |INSERT OVERWRITE $catalogV2.$namespace1.$table2 + |SELECT * FROM $catalogV2.$namespace1.$table1 + |""".stripMargin + // Test user has select table1 permission to insert + doAs(table1OnlyUserForNs, sql(s"SELECT * FROM $catalogV2.$namespace1.$table1")) + interceptEndsWith[AccessControlException] { + doAs(table1OnlyUserForNs, sql(insertOverwriteSql)) + }(s"does not have [update] privilege on [$namespace1/$table2]") + + // Test user has not any permission to insert + interceptEndsWith[AccessControlException] { + doAs(someone, sql(insertOverwriteSql)) + }(s"does not have [select] privilege on [$namespace1/$table1/id]") + + doAs(admin, sql(insertOverwriteSql)) + } + } + def createTableSql(namespace: String, table: String): String = s""" |CREATE TABLE IF NOT EXISTS $catalogV2.$namespace.$table