Skip to content
Open
Changes from 7 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 @@ -24,14 +24,17 @@ import scala.collection.JavaConverters._

import org.apache.hadoop.security.UserGroupInformation
import org.apache.ranger.plugin.policyengine.{RangerAccessRequestImpl, RangerPolicyEngine}
import org.apache.spark.internal.Logging

import org.apache.kyuubi.plugin.spark.authz.OperationType.OperationType
import org.apache.kyuubi.plugin.spark.authz.ranger.AccessType._
import org.apache.kyuubi.util.reflect.DynMethods
import org.apache.kyuubi.util.reflect.DynMethods.UnboundMethod
import org.apache.kyuubi.util.reflect.ReflectUtils._

case class AccessRequest private (accessType: AccessType) extends RangerAccessRequestImpl

object AccessRequest {
object AccessRequest extends Logging {
def apply(
resource: AccessResource,
user: UserGroupInformation,
Expand All @@ -45,12 +48,11 @@ object AccessRequest {
req.setUserGroups(userGroups)
req.setAction(opType.toString)
try {
val roles = invokeAs[JSet[String]](
SparkRangerAdminPlugin,
"getRolesFromUserAndGroups",
(classOf[String], userName),
(classOf[JSet[String]], userGroups))
invokeAs[Unit](req, "setUserRoles", (classOf[JSet[String]], roles))
getRolesFromUserAndGroupsMethod.zip(setUserRolesMethod).foreach {
case (getMethod, setMethod) =>
val roles = getMethod.invoke[JSet[String]](SparkRangerAdminPlugin, userName, userGroups)
setMethod.invoke[Unit](req, roles)
}
} catch {
case _: Exception =>
}
Expand All @@ -68,17 +70,43 @@ object AccessRequest {
req
}

private val getRolesFromUserAndGroupsMethod: Option[UnboundMethod] =
getMethod(
SparkRangerAdminPlugin.getClass,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SparkRangerAdminPlugin.getClass,
classOf[SparkRangerAdminPlugin],

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SparkRangerAdminPlugin is an object and does not seem to work with classOf.

"getRolesFromUserAndGroups",
classOf[String],
classOf[JSet[String]])

private val setUserRolesMethod: Option[UnboundMethod] =
getMethod(classOf[AccessRequest], "setUserRoles", classOf[JSet[String]])

private def getUserGroupsFromUgi(user: UserGroupInformation): JSet[String] = {
user.getGroupNames.toSet.asJava
}

private lazy val getUserStoreEnricherMethod: Option[UnboundMethod] =
getMethod(SparkRangerAdminPlugin.getClass, "getUserStoreEnricher")

private lazy val getRangerUserStoreMethod: Option[UnboundMethod] =
getMethod(
Class.forName("org.apache.ranger.plugin.contextenricher.RangerUserStoreEnricher"),
"getRangerUserStore")

private lazy val getUserGroupMappingMethod: Option[UnboundMethod] =
getMethod(
Class.forName("org.apache.ranger.plugin.util.RangerUserStore"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's located at ranger-plugins-common, should be always accessible?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's located at ranger-plugins-common, should be always accessible?

I don't get your point, but the logic here seems to be consistent with previous.

val userGroupMapping =
invokeAs[JHashMap[String, JSet[String]]](userStore, "getUserGroupMapping")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, it's a new feature of Ranger 2.1, we must use reflection as long as we support lower Ranger versions

"getUserGroupMapping")

private def getUserGroupsFromUserStore(user: UserGroupInformation): Option[JSet[String]] = {
try {
val storeEnricher = invokeAs[AnyRef](SparkRangerAdminPlugin, "getUserStoreEnricher")
val userStore = invokeAs[AnyRef](storeEnricher, "getRangerUserStore")
val userGroupMapping =
invokeAs[JHashMap[String, JSet[String]]](userStore, "getUserGroupMapping")
Some(userGroupMapping.get(user.getShortUserName))
getUserStoreEnricherMethod.zip(getRangerUserStoreMethod)
.zip(getUserGroupMappingMethod).map {
case ((getEnricher, getUserStore), getMapping) =>
val enricher = getEnricher.invoke[AnyRef](SparkRangerAdminPlugin)
val userStore = getUserStore.invoke[AnyRef](enricher)
val userGroupMapping = getMapping.invoke[JHashMap[String, JSet[String]]](userStore)
userGroupMapping.get(user.getShortUserName)
}.headOption
} catch {
case _: NoSuchMethodException =>
None
Expand All @@ -94,4 +122,21 @@ object AccessRequest {
}
}

private def getMethod(
clz: Class[_],
methodName: String,
argClasses: Class[_]*): Option[UnboundMethod] = {
try {
Some(DynMethods.builder(methodName)
.hiddenImpl(clz, argClasses: _*)
.impl(clz, argClasses: _*)
.buildChecked)
} catch {
case e: Exception =>
logWarning(
s"$clz does not have $methodName${argClasses.map(_.getName).mkString("(", ", ", ")")}",
e)
None
}
}
}
Loading