You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kyuubi.apache.org by ch...@apache.org on 2026/09/04 09:04:45 UTC

(kyuubi) branch master updated: [KYUUBI #7671][AUTHZ] Cover all injected authz rules in the excludedRules check

This is an automated email from the ASF dual-hosted git repository.

pan3793 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 330a6426d8 [KYUUBI #7671][AUTHZ] Cover all injected authz rules in the excludedRules check
330a6426d8 is described below

commit 330a6426d8126da8721bd288e7b1257193204149
Author: Aleksandr Efimov <dz...@gmail.com>
AuthorDate: Fri Sep 4 17:04:35 2026 +0800

    [KYUUBI #7671][AUTHZ] Cover all injected authz rules in the excludedRules check
    
    ### Why are the changes needed?
    
    Closes #7671, the follow-up wForget asked for while reviewing #7637.
    
    `AuthzConfigurationChecker` matches `org.apache.kyuubi.plugin.spark.authz.ranger` in the effective `spark.sql.optimizer.excludedRules`, which was the whole extension when the check was written. Most rules live under `org.apache.kyuubi.plugin.spark.authz.rule` now, so a rule added there is outside the denylist. This matches the extension's own package instead.
    
    It is future-proofing rather than a fix for a live bypass, and worth saying why. `spark.sql.optimizer.excludedRules` filters optimizer batches only and Spark has no analyzer counterpart, so the resolution rules that apply masking and row filtering cannot be excluded at all. Of the four optimizer rules `RangerSparkExtension` injects, `RuleAuthorization` is in `…authz.ranger` and already covered; the other three — `RuleEliminateMarker`, `RuleEliminatePermanentViewMarker`, `RuleEliminate [...]
    
    The change does reject configurations that are accepted today, which is why it is separate from #7637 rather than part of it.
    
    ### How was this patch tested?
    
    A new case in `AuthzConfigurationCheckerSuite` covers the three `…authz.rule` rules by their `ruleName`, through both paths the checker guards: the value in effect, and the `SET` syntax.
    
    30 tests green across `AuthzConfigurationCheckerSuite`, `DataMaskingForInMemoryParquetSuite` and the row filtering suite. With the constant reverted to the ranger package the new case fails, so it tests the change rather than the code around it.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Assisted-by: Claude Opus 5
    
    Closes #7672 from alexandrefimov/kyuubi-authz-excluded-rules-prefix.
    
    Closes #7671
    
    2df8dede5 [Aleksandr Efimov] [KYUUBI #7671][AUTHZ] Cover all injected authz rules in the excludedRules check
    
    Authored-by: Aleksandr Efimov <dz...@gmail.com>
    Signed-off-by: Cheng Pan <ch...@apache.org>
---
 .../rule/config/AuthzConfigurationChecker.scala    | 10 +++++---
 .../rule/AuthzConfigurationCheckerSuite.scala      | 28 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/rule/config/AuthzConfigurationChecker.scala b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/rule/config/AuthzConfigurationChecker.scala
index e2c7cfb52b..c4d95195f2 100644
--- a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/rule/config/AuthzConfigurationChecker.scala
+++ b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/rule/config/AuthzConfigurationChecker.scala
@@ -32,7 +32,11 @@ case class AuthzConfigurationChecker(spark: SparkSession) extends (LogicalPlan =
   final val RESTRICT_LIST_KEY = "spark.kyuubi.conf.restricted.list"
   final val EXCLUDED_RULES_KEY = "spark.sql.optimizer.excludedRules"
 
-  final private val AUTHZ_RANGER_RULE_PACKAGE = "org.apache.kyuubi.plugin.spark.authz.ranger"
+  // Every rule the extension injects lives under this package, not only the ranger ones:
+  // the marker-eliminating rules sit in org.apache.kyuubi.plugin.spark.authz.rule, and new
+  // rules land there too. Excluding one of those breaks the query at planning today rather
+  // than lifting a check, but the denylist should not depend on that staying true.
+  final private val AUTHZ_RULE_PACKAGE = "org.apache.kyuubi.plugin.spark.authz"
 
   private val restrictedConfList: Set[String] =
     Set(
@@ -48,13 +52,13 @@ case class AuthzConfigurationChecker(spark: SparkSession) extends (LogicalPlan =
     // case below never sees them. Check the value that is actually in effect on every
     // plan instead - check rules are not affected by spark.sql.optimizer.excludedRules,
     // which only filters optimizer batches, so this check cannot be turned off the same way.
-    if (spark.conf.getOption(EXCLUDED_RULES_KEY).exists(_.contains(AUTHZ_RANGER_RULE_PACKAGE))) {
+    if (spark.conf.getOption(EXCLUDED_RULES_KEY).exists(_.contains(AUTHZ_RULE_PACKAGE))) {
       throw new AccessControlException("Excluding Authz security rules is not allowed")
     }
     plan match {
       case SetCommand(Some((
             EXCLUDED_RULES_KEY,
-            Some(v)))) if v.contains(AUTHZ_RANGER_RULE_PACKAGE) =>
+            Some(v)))) if v.contains(AUTHZ_RULE_PACKAGE) =>
         throw new AccessControlException("Excluding Authz security rules is not allowed")
       case SetCommand(Some((k, Some(_)))) if restrictedConfList.contains(k) =>
         throw new AccessControlException(s"Modifying config $k is not allowed")
diff --git a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/rule/AuthzConfigurationCheckerSuite.scala b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/rule/AuthzConfigurationCheckerSuite.scala
index 3b764c0e3d..c0b68cae86 100644
--- a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/rule/AuthzConfigurationCheckerSuite.scala
+++ b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/rule/AuthzConfigurationCheckerSuite.scala
@@ -84,6 +84,34 @@ class AuthzConfigurationCheckerSuite extends KyuubiFunSuite with SparkSessionPro
     }
   }
 
+  test("check every authz rule the extension injects, not only the ranger ones") {
+    val extension = AuthzConfigurationChecker(spark)
+    val plan = sql("select 1").queryExecution.analyzed
+
+    // the marker-eliminating rules live in org.apache.kyuubi.plugin.spark.authz.rule and are
+    // optimizer rules, so spark.sql.optimizer.excludedRules reaches them the same way it
+    // reaches RuleAuthorization
+    Seq(
+      RuleEliminateMarker.ruleName,
+      RuleEliminatePermanentViewMarker(spark).ruleName,
+      RuleEliminateTypeOf.ruleName).foreach { rule =>
+      spark.conf.set(extension.EXCLUDED_RULES_KEY, rule)
+      try {
+        intercept[AccessControlException](extension.apply(plan))
+      } finally {
+        spark.conf.unset(extension.EXCLUDED_RULES_KEY)
+      }
+    }
+
+    val setPlan = sql(s"set ${extension.EXCLUDED_RULES_KEY}=${RuleEliminateMarker.ruleName}")
+      .queryExecution.analyzed
+    try {
+      intercept[AccessControlException](extension.apply(setPlan))
+    } finally {
+      spark.conf.unset(extension.EXCLUDED_RULES_KEY)
+    }
+  }
+
   test("apply spark configuration restriction rules for RESET") {
     sql("set spark.kyuubi.conf.restricted.list=spark.sql.abc,spark.sql.xyz")
     val extension = AuthzConfigurationChecker(spark)