Skip to content

Commit

Permalink
[#3963] feat(core): Apache Ranger Hive authorization pushdown (#4515)
Browse files Browse the repository at this point in the history
### What changes were proposed in this pull request?

Use Gravitino authorization plugin to authorize Ranger Hive.
1. Added RangerHiveAuthorization modul
2. Added RangerAuthorizationPlugin abstract class.
3. Extend RangerHiveAuthorizationPlugin class process Hive authorization
pushdown
4. Added Ranger client extension

### Why are the changes needed?

Fix: #3963

### Does this PR introduce _any_ user-facing change?

1. Added RangerHiveAuthorizationPlugin interface

### How was this patch tested?

RangerHiveIT passed.

---------

Co-authored-by: yuqi <[email protected]>
  • Loading branch information
2 people authored and web-flow committed Aug 22, 2024
1 parent cdf3988 commit a2fec7a
Show file tree
Hide file tree
Showing 40 changed files with 3,913 additions and 353 deletions.
10 changes: 10 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,13 @@
Kyligence/kylinpy
./clients/client-python/gravitino/utils/exceptions.py
./clients/client-python/gravitino/utils/http_client.py

Apache Ranger
./security-admin/src/main/java/org/apache/ranger/defines/JsonDateSerializer.java
./security-admin/src/main/java/org/apache/ranger/defines/RangerCommonEnums.java
./security-admin/src/main/java/org/apache/ranger/view/VList.java
./security-admin/src/main/java/org/apache/ranger/view/VXDataObject.java
./security-admin/src/main/java/org/apache/ranger/view/VXGroup.java
./security-admin/src/main/java/org/apache/ranger/view/VXGroupList.java
./security-admin/src/main/java/org/apache/ranger/view/VXUser.java
./security-admin/src/main/java/org/apache/ranger/view/VXUserList.java
178 changes: 156 additions & 22 deletions api/src/main/java/org/apache/gravitino/authorization/RoleChange.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package org.apache.gravitino.authorization;

import java.util.Objects;
import org.apache.gravitino.annotation.Evolving;

/** The RoleChange interface defines the public API for managing roles in an authorization. */
Expand All @@ -26,31 +27,57 @@ public interface RoleChange {
/**
* Create a RoleChange to add a securable object into a role.
*
* @param roleName The role name.
* @param securableObject The securable object.
* @return return a RoleChange for the add securable object.
* @return return a RoleChange for the added securable object.
*/
static RoleChange addSecurableObject(SecurableObject securableObject) {
return new AddSecurableObject(securableObject);
static RoleChange addSecurableObject(String roleName, SecurableObject securableObject) {
return new AddSecurableObject(roleName, securableObject);
}

/**
* Create a RoleChange to remove a securable object from a role.
*
* @param roleName The role name.
* @param securableObject The securable object.
* @return return a RoleChange for the add securable object.
* @return return a RoleChange for the added securable object.
*/
static RoleChange removeSecurableObject(SecurableObject securableObject) {
return new RemoveSecurableObject(securableObject);
static RoleChange removeSecurableObject(String roleName, SecurableObject securableObject) {
return new RemoveSecurableObject(roleName, securableObject);
}

/** A AddSecurableObject to add securable object to role. */
/**
* Update a securable object RoleChange.
*
* @param roleName The role name.
* @param securableObject The securable object.
* @param newSecurableObject The new securable object.
* @return return a RoleChange for the update securable object.
*/
static RoleChange updateSecurableObject(
String roleName, SecurableObject securableObject, SecurableObject newSecurableObject) {
return new UpdateSecurableObject(roleName, securableObject, newSecurableObject);
}

/** A AddSecurableObject to add a securable object to a role. */
final class AddSecurableObject implements RoleChange {
private final String roleName;
private final SecurableObject securableObject;

private AddSecurableObject(SecurableObject securableObject) {
private AddSecurableObject(String roleName, SecurableObject securableObject) {
this.roleName = roleName;
this.securableObject = securableObject;
}

/**
* Returns the role name to be added.
*
* @return return a role name.
*/
public String getRoleName() {
return this.roleName;
}

/**
* Returns the securable object to be added.
*
Expand All @@ -62,17 +89,18 @@ public SecurableObject getSecurableObject() {

/**
* Compares this AddSecurableObject instance with another object for equality. The comparison is
* based on the add securable object to role.
* based on the added securable object to a role.
*
* @param o The object to compare with this instance.
* @return true if the given object represents the same add securable object; false otherwise.
* @return true if the given object represents the same as the add securable object; false
* otherwise.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AddSecurableObject that = (AddSecurableObject) o;
return securableObject.equals(that.securableObject);
return roleName.equals(that.roleName) && securableObject.equals(that.securableObject);
}

/**
Expand All @@ -83,7 +111,7 @@ public boolean equals(Object o) {
*/
@Override
public int hashCode() {
return securableObject.hashCode();
return Objects.hash(roleName, securableObject);
}

/**
Expand All @@ -94,18 +122,29 @@ public int hashCode() {
*/
@Override
public String toString() {
return "ADDSECURABLEOBJECT " + securableObject;
return "ADDSECURABLEOBJECT " + roleName + " " + securableObject;
}
}

/** A RemoveSecurableObject to remove securable object from role. */
/** A RemoveSecurableObject to remove a securable object from a role. */
final class RemoveSecurableObject implements RoleChange {
private final String roleName;
private final SecurableObject securableObject;

private RemoveSecurableObject(SecurableObject securableObject) {
private RemoveSecurableObject(String roleName, SecurableObject securableObject) {
this.roleName = roleName;
this.securableObject = securableObject;
}

/**
* Returns the role name.
*
* @return return a role name.
*/
public String getRoleName() {
return roleName;
}

/**
* Returns the securable object to be added.
*
Expand All @@ -117,28 +156,29 @@ public SecurableObject getSecurableObject() {

/**
* Compares this RemoveSecurableObject instance with another object for equality. The comparison
* is based on the add securable object to role.
* is based on the added securable object to a role.
*
* @param o The object to compare with this instance.
* @return true if the given object represents the same add securable object; false otherwise.
* @return true if the given object represents the same as remove securable object; false
* otherwise.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RemoveSecurableObject that = (RemoveSecurableObject) o;
return securableObject.equals(that.securableObject);
return roleName.equals(that.roleName) && securableObject.equals(that.securableObject);
}

/**
* Generates a hash code for this RemoveSecurableObject instance. The hash code is based on the
* add securable object.
* added securable object.
*
* @return A hash code value for this add securable object operation.
* @return A hash code value for this adds securable object operation.
*/
@Override
public int hashCode() {
return securableObject.hashCode();
return Objects.hash(roleName, securableObject);
}

/**
Expand All @@ -149,7 +189,101 @@ public int hashCode() {
*/
@Override
public String toString() {
return "REMOVESECURABLEOBJECT " + securableObject;
return "REMOVESECURABLEOBJECT " + roleName + " " + securableObject;
}
}

/**
* A UpdateSecurableObject is to update securable object's privilege from a role. <br>
* The securable object's metadata entity must be the same as new securable object's metadata
* entity. <br>
* The securable object's privilege must be different from new securable object's privilege. <br>
*/
final class UpdateSecurableObject implements RoleChange {
private final String roleName;
private final SecurableObject securableObject;
private final SecurableObject newSecurableObject;

private UpdateSecurableObject(
String roleName, SecurableObject securableObject, SecurableObject newSecurableObject) {
if (!securableObject.fullName().equals(newSecurableObject.fullName())) {
throw new IllegalArgumentException(
"The securable object's metadata entity must be same as new securable object's metadata entity.");
}
if (securableObject.privileges().equals(newSecurableObject.privileges())) {
throw new IllegalArgumentException(
"The securable object's privilege must be different as new securable object's privilege.");
}
this.roleName = roleName;
this.securableObject = securableObject;
this.newSecurableObject = newSecurableObject;
}

/**
* Returns the role name.
*
* @return return a role name.
*/
public String getRoleName() {
return roleName;
}

/**
* Returns the securable object to be updated.
*
* @return return a securable object.
*/
public SecurableObject getSecurableObject() {
return this.securableObject;
}

/**
* Returns the new securable object.
*
* @return return a securable object.
*/
public SecurableObject getNewSecurableObject() {
return this.newSecurableObject;
}

/**
* Compares this UpdateSecurableObject instance with another object for equality. The comparison
* is based on the old securable object and new securable object.
*
* @param o The object to compare with this instance.
* @return true if the given object represents the same update securable object; false
* otherwise.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UpdateSecurableObject that = (UpdateSecurableObject) o;
return roleName.equals(that.roleName)
&& securableObject.equals(that.securableObject)
&& newSecurableObject.equals(that.newSecurableObject);
}

/**
* Generates a hash code for this UpdateSecurableObject instance. The hash code is based on the
* old securable object and new securable object.
*
* @return A hash code value for this update securable object operation.
*/
@Override
public int hashCode() {
return Objects.hash(roleName, securableObject, newSecurableObject);
}

/**
* Returns a string representation of the UpdateSecurableObject instance. This string format
* includes the class name followed by the add securable object operation.
*
* @return A string representation of the RemoveSecurableObject instance.
*/
@Override
public String toString() {
return "UPDATESECURABLEOBJECT " + roleName + " " + securableObject + " " + newSecurableObject;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
/** The helper class for {@link SecurableObject}. */
public class SecurableObjects {

private static final Splitter DOT_SPLITTER = Splitter.on('.');
/** The splitter for splitting the names. */
public static final Splitter DOT_SPLITTER = Splitter.on('.');

/**
* Create the metalake {@link SecurableObject} with the given metalake name and privileges.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.gravitino.exceptions;

import com.google.errorprone.annotations.FormatMethod;
import com.google.errorprone.annotations.FormatString;

/** An exception thrown when an authorization plugin operation failed. */
public class AuthorizationPluginException extends IllegalArgumentException {

/**
* Constructs a new exception with the specified detail message.
*
* @param message the detail message.
* @param args the arguments to the message.
*/
@FormatMethod
public AuthorizationPluginException(@FormatString String message, Object... args) {
super(String.format(message, args));
}

/**
* Constructs a new exception with the specified cause.
*
* @param cause the cause.
*/
public AuthorizationPluginException(Throwable cause) {
super(cause);
}
}
Loading

0 comments on commit a2fec7a

Please sign in to comment.