You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kyuubi.apache.org by ya...@apache.org on 2022/12/12 05:37:08 UTC
[incubator-kyuubi] branch master updated: [KYUUBI #3300] [FOLLOWUP] simply reflection method callings in Authz's AccessRequest
This is an automated email from the ASF dual-hosted git repository.
yao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-kyuubi.git
The following commit(s) were added to refs/heads/master by this push:
new 8b8c7d011 [KYUUBI #3300] [FOLLOWUP] simply reflection method callings in Authz's AccessRequest
8b8c7d011 is described below
commit 8b8c7d01179968611f5c5a1434d6ef36d45cf879
Author: liangbowen <li...@gf.com.cn>
AuthorDate: Mon Dec 12 13:36:57 2022 +0800
[KYUUBI #3300] [FOLLOWUP] simply reflection method callings in Authz's AccessRequest
### _Why are the changes needed?_
To simplify the method calling via reflection in Authz's `AccessRequest`, including codes from pull #3308 introduced.
### _How was this patch tested?_
- [ ] Add some test cases that check the changes thoroughly including negative and positive cases if possible
- [ ] Add screenshots for manual tests if appropriate
- [x] [Run test](https://kyuubi.apache.org/docs/latest/develop_tools/testing.html#running-tests) locally before make a pull request
Closes #3945 from bowenliang123/3300-followup.
Closes #3300
3e3f2bf8e [liangbowen] move exception throwing in `invoke` method
ff1c9a05e [liangbowen] import java.util.{HashMap => JHashMap}
2848083e4 [liangbowen] import java.util.{Set => JSet}
a9b4240fb [liangbowen] import java.util.{Set => JSet}
408977e89 [liangbowen] correct error handling in AccessRequest
c785a251c [liangbowen] use invokeAs
9f9c6a1d9 [liangbowen] rename invokeWithCast to invokeAs
258be28f8 [liangbowen] introduce `invokeWithCast` in AuthZUtils for simplifying object casting
f9902099a [liangbowen] simplify reflection method calling in AccessRequest
da767db88 [liangbowen] lint
3b82c3112 [liangbowen] unused imports
d4a71dac5 [liangbowen] unused imports
0c57d0de9 [liangbowen] simply getUserGroupsFromUserStore with reflection methods
Authored-by: liangbowen <li...@gf.com.cn>
Signed-off-by: Kent Yao <ya...@apache.org>
---
.../plugin/spark/authz/PrivilegesBuilder.scala | 3 +-
.../plugin/spark/authz/ranger/AccessRequest.scala | 57 ++++++++--------------
.../plugin/spark/authz/serde/tableExtractors.scala | 10 ++--
.../plugin/spark/authz/util/AuthZUtils.scala | 21 ++++++--
.../spark/authz/util/RangerConfigProvider.scala | 2 +-
5 files changed, 43 insertions(+), 50 deletions(-)
diff --git a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/PrivilegesBuilder.scala b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/PrivilegesBuilder.scala
index c9950b68d..1e97716eb 100644
--- a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/PrivilegesBuilder.scala
+++ b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/PrivilegesBuilder.scala
@@ -169,8 +169,7 @@ object PrivilegesBuilder {
}
case u if u.nodeName == "UnresolvedRelation" =>
- val tableNameM = u.getClass.getMethod("tableName")
- val parts = tableNameM.invoke(u).asInstanceOf[String].split("\\.")
+ val parts = invokeAs[String](u, "tableName").split("\\.")
val db = quote(parts.init)
privilegeObjects += tablePrivileges(TableIdentifier(parts.last, Some(db)))
diff --git a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/AccessRequest.scala b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/AccessRequest.scala
index 7fccff54c..4997dda3b 100644
--- a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/AccessRequest.scala
+++ b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/ranger/AccessRequest.scala
@@ -17,17 +17,17 @@
package org.apache.kyuubi.plugin.spark.authz.ranger
-import java.util
+import java.util.{HashMap => JHashMap, Set => JSet}
import java.util.Date
import scala.collection.JavaConverters._
-import scala.collection.mutable
import org.apache.hadoop.security.UserGroupInformation
import org.apache.ranger.plugin.policyengine.{RangerAccessRequestImpl, RangerPolicyEngine}
import org.apache.kyuubi.plugin.spark.authz.OperationType.OperationType
import org.apache.kyuubi.plugin.spark.authz.ranger.AccessType._
+import org.apache.kyuubi.plugin.spark.authz.util.AuthZUtils.{invoke, invokeAs}
case class AccessRequest private (accessType: AccessType) extends RangerAccessRequestImpl
@@ -45,17 +45,14 @@ object AccessRequest {
req.setUserGroups(userGroups)
req.setAction(opType.toString)
try {
- val getRoles = SparkRangerAdminPlugin.getClass.getMethod(
+ val roles = invokeAs[JSet[String]](
+ SparkRangerAdminPlugin,
"getRolesFromUserAndGroups",
- classOf[String],
- classOf[java.util.Set[String]])
- getRoles.setAccessible(true)
- val roles = getRoles.invoke(SparkRangerAdminPlugin, userName, userGroups)
- val setRoles = req.getClass.getMethod("setUserRoles", classOf[java.util.Set[String]])
- setRoles.setAccessible(true)
- setRoles.invoke(req, roles)
+ (classOf[String], userName),
+ (classOf[JSet[String]], userGroups))
+ invoke(req, "setUserRoles", (classOf[JSet[String]], roles))
} catch {
- case _: NoSuchMethodException =>
+ case _: Exception =>
}
req.setAccessTime(new Date())
accessType match {
@@ -63,48 +60,32 @@ object AccessRequest {
case _ => req.setAccessType(accessType.toString.toLowerCase)
}
try {
- val getClusterName = SparkRangerAdminPlugin.getClass.getMethod("getClusterName")
- getClusterName.setAccessible(true)
- val clusterName = getClusterName.invoke(SparkRangerAdminPlugin)
- val setClusterName = req.getClass.getMethod("setClusterName", classOf[String])
- setClusterName.setAccessible(true)
- setClusterName.invoke(req, clusterName)
+ val clusterName = invokeAs[String](SparkRangerAdminPlugin, "getClusterName")
+ invoke(req, "setClusterName", (classOf[String], clusterName))
} catch {
- case _: NoSuchMethodException =>
+ case _: Exception =>
}
req
}
- private def getUserGroupsFromUgi(user: UserGroupInformation): util.Set[String] = {
+ private def getUserGroupsFromUgi(user: UserGroupInformation): JSet[String] = {
user.getGroupNames.toSet.asJava
}
- private def getUserGroupsFromUserStore(user: UserGroupInformation): Option[util.Set[String]] = {
+ private def getUserGroupsFromUserStore(user: UserGroupInformation): Option[JSet[String]] = {
try {
- val getUserStoreEnricher = SparkRangerAdminPlugin.getClass.getMethod(
- "getUserStoreEnricher")
- getUserStoreEnricher.setAccessible(true)
- val storeEnricher = getUserStoreEnricher.invoke(SparkRangerAdminPlugin)
-
- val getRangerUserStore = storeEnricher.getClass.getMethod("getRangerUserStore")
- getRangerUserStore.setAccessible(true)
- val userStore = getRangerUserStore.invoke(storeEnricher)
-
- val getUserGroupMapping = userStore.getClass.getMethod("getUserGroupMapping")
- getUserGroupMapping.setAccessible(true)
-
- val userGroupMappingMap: mutable.Map[String, util.Set[String]] =
- mapAsScalaMap(getUserGroupMapping.invoke(userStore)
- .asInstanceOf[util.HashMap[String, util.Set[String]]])
-
- userGroupMappingMap.get(user.getShortUserName)
+ val storeEnricher = invoke(SparkRangerAdminPlugin, "getUserStoreEnricher")
+ val userStore = invoke(storeEnricher, "getRangerUserStore")
+ val userGroupMapping =
+ invokeAs[JHashMap[String, JSet[String]]](userStore, "getUserGroupMapping")
+ Some(userGroupMapping.get(user.getShortUserName))
} catch {
case _: NoSuchMethodException =>
None
}
}
- private def getUserGroups(user: UserGroupInformation): util.Set[String] = {
+ private def getUserGroups(user: UserGroupInformation): JSet[String] = {
if (SparkRangerAdminPlugin.useUserGroupsFromUserStoreEnabled) {
getUserGroupsFromUserStore(user)
.getOrElse(getUserGroupsFromUgi(user))
diff --git a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/serde/tableExtractors.scala b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/serde/tableExtractors.scala
index 02cafad39..b801df841 100644
--- a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/serde/tableExtractors.scala
+++ b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/serde/tableExtractors.scala
@@ -51,7 +51,7 @@ object TableExtractor {
def getOwner(v: AnyRef): Option[String] = {
// org.apache.spark.sql.connector.catalog.Table
val table = invoke(v, "table")
- val properties = invoke(table, "properties").asInstanceOf[JMap[String, String]].asScala
+ val properties = invokeAs[JMap[String, String]](table, "properties").asScala
properties.get("owner")
}
}
@@ -102,8 +102,8 @@ class ResolvedTableTableExtractor extends TableExtractor {
*/
class IdentifierTableExtractor extends TableExtractor {
override def apply(spark: SparkSession, v1: AnyRef): Option[Table] = {
- val namespace = invoke(v1, "namespace").asInstanceOf[Array[String]]
- val table = invoke(v1, "name").asInstanceOf[String]
+ val namespace = invokeAs[Array[String]](v1, "namespace")
+ val table = invokeAs[String](v1, "name")
Some(Table(Some(quote(namespace)), table, None))
}
}
@@ -118,7 +118,7 @@ class DataSourceV2RelationTableExtractor extends TableExtractor {
if (v2Relation.isEmpty) {
None
} else {
- val maybeIdentifier = invoke(v2Relation.get, "identifier").asInstanceOf[Option[AnyRef]]
+ val maybeIdentifier = invokeAs[Option[AnyRef]](v2Relation.get, "identifier")
maybeIdentifier.flatMap { id =>
val maybeTable = new IdentifierTableExtractor().apply(spark, id)
val maybeOwner = TableExtractor.getOwner(v2Relation.get)
@@ -133,7 +133,7 @@ class DataSourceV2RelationTableExtractor extends TableExtractor {
*/
class LogicalRelationTableExtractor extends TableExtractor {
override def apply(spark: SparkSession, v1: AnyRef): Option[Table] = {
- val maybeCatalogTable = invoke(v1, "catalogTable").asInstanceOf[Option[AnyRef]]
+ val maybeCatalogTable = invokeAs[Option[AnyRef]](v1, "catalogTable")
maybeCatalogTable.flatMap { ct =>
new CatalogTableTableExtractor().apply(spark, ct)
}
diff --git a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/AuthZUtils.scala b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/AuthZUtils.scala
index 4d4a4cd20..d7d586803 100644
--- a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/AuthZUtils.scala
+++ b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/AuthZUtils.scala
@@ -62,10 +62,23 @@ private[authz] object AuthZUtils {
obj: AnyRef,
methodName: String,
args: (Class[_], AnyRef)*): AnyRef = {
- val (types, values) = args.unzip
- val method = obj.getClass.getMethod(methodName, types: _*)
- method.setAccessible(true)
- method.invoke(obj, values: _*)
+ try {
+ val (types, values) = args.unzip
+ val method = obj.getClass.getMethod(methodName, types: _*)
+ method.setAccessible(true)
+ method.invoke(obj, values: _*)
+ } catch {
+ case e: NoSuchMethodException =>
+ val candidates = obj.getClass.getMethods.map(_.getName).mkString("[", ",", "]")
+ throw new RuntimeException(s"$methodName not in ${obj.getClass} $candidates", e)
+ }
+ }
+
+ def invokeAs[T](
+ obj: AnyRef,
+ methodName: String,
+ args: (Class[_], AnyRef)*): T = {
+ invoke(obj, methodName, args: _*).asInstanceOf[T]
}
def invokeStatic(
diff --git a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/RangerConfigProvider.scala b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/RangerConfigProvider.scala
index b53ecae0f..5919dde31 100644
--- a/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/RangerConfigProvider.scala
+++ b/extensions/spark/kyuubi-spark-authz/src/main/scala/org/apache/kyuubi/plugin/spark/authz/util/RangerConfigProvider.scala
@@ -36,7 +36,7 @@ trait RangerConfigProvider {
def getRangerConf: Configuration = {
try {
// for Ranger 2.1+
- invoke(this, "getConfig").asInstanceOf[Configuration]
+ invokeAs[Configuration](this, "getConfig")
} catch {
case _: NoSuchMethodException =>
// for Ranger 2.0 and below