Skip to content

Commit

Permalink
[#5124][#5146] feat(auth-ranger): Ranger plugin should support rename…
Browse files Browse the repository at this point in the history
… operation (#5375)

### What changes were proposed in this pull request?

Add rename a securable object in the RoleChange.

### Why are the changes needed?

Fix: #5124 #5146

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

N/A

### How was this patch tested?

Add ITs.

Co-authored-by: Xun <[email protected]>
  • Loading branch information
github-actions[bot] and xunliu authored Oct 31, 2024
1 parent de27d58 commit b913e98
Show file tree
Hide file tree
Showing 15 changed files with 1,079 additions and 113 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/access-control-integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ jobs:
- name: Authorization Integration Test (JDK${{ matrix.java-version }})
id: integrationTest
run: |
./gradlew -PtestMode=embedded -PjdbcBackend=h2 -PjdkVersion=${{ matrix.java-version }} -PskipDockerTests=false :authorizations:authorization-ranger:test --tests "org.apache.gravitino.authorization.ranger.**"
./gradlew -PtestMode=deploy -PjdbcBackend=mysql -PjdkVersion=${{ matrix.java-version }} -PskipDockerTests=false :authorizations:authorization-ranger:test --tests "org.apache.gravitino.authorization.ranger.**"
./gradlew -PtestMode=deploy -PjdbcBackend=postgresql -PjdkVersion=${{ matrix.java-version }} -PskipDockerTests=false :authorizations:authorization-ranger:test --tests "org.apache.gravitino.authorization.ranger.**"
./gradlew -PtestMode=embedded -PjdbcBackend=h2 -PjdkVersion=${{ matrix.java-version }} -PskipDockerTests=false :authorizations:authorization-ranger:test
./gradlew -PtestMode=deploy -PjdbcBackend=mysql -PjdkVersion=${{ matrix.java-version }} -PskipDockerTests=false :authorizations:authorization-ranger:test
./gradlew -PtestMode=deploy -PjdbcBackend=postgresql -PjdkVersion=${{ matrix.java-version }} -PskipDockerTests=false :authorizations:authorization-ranger:test
- name: Upload integrate tests reports
uses: actions/upload-artifact@v3
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* 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.authorization;

import com.google.common.base.Preconditions;
import java.util.Objects;
import org.apache.gravitino.MetadataObject;
import org.apache.gravitino.annotation.Evolving;

/**
* The MetadataObjectChange interface defines the public API for managing roles in an authorization.
*/
@Evolving
public interface MetadataObjectChange {
/**
* Rename a metadata entity MetadataObjectChange.
*
* @param metadataObject The metadata object.
* @param newMetadataObject The new metadata object.
* @return return a MetadataObjectChange for the rename metadata object.
*/
static MetadataObjectChange rename(
MetadataObject metadataObject, MetadataObject newMetadataObject) {
return new RenameMetadataObject(metadataObject, newMetadataObject);
}

/**
* Remove a metadata entity MetadataObjectChange.
*
* @param metadataObject The metadata object.
* @return return a MetadataObjectChange for the remove metadata object.
*/
static MetadataObjectChange remove(MetadataObject metadataObject) {
return new RemoveMetadataObject(metadataObject);
}

/** A RenameMetadataObject is to rename securable object's metadata entity. */
final class RenameMetadataObject implements MetadataObjectChange {
private final MetadataObject metadataObject;
private final MetadataObject newMetadataObject;

private RenameMetadataObject(MetadataObject metadataObject, MetadataObject newMetadataObject) {
Preconditions.checkArgument(
!metadataObject.fullName().equals(newMetadataObject.fullName()),
"The metadata object must be different!");
Preconditions.checkArgument(
metadataObject.type().equals(newMetadataObject.type()),
"The metadata object type must be same!");

this.metadataObject = metadataObject;
this.newMetadataObject = newMetadataObject;
}

/**
* Returns the metadataObject to be renamed.
*
* @return return a metadataObject.
*/
public MetadataObject metadataObject() {
return metadataObject;
}

/**
* Returns the new metadataObject object.
*
* @return return a metadataObject object.
*/
public MetadataObject newMetadataObject() {
return newMetadataObject;
}

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

/**
* Generates a hash code for this RenameMetadataObject instance. The hash code is based on the
* old metadata entity and new metadata entity.
*
* @return A hash code value for this update metadata entity operation.
*/
@Override
public int hashCode() {
return Objects.hash(metadataObject, newMetadataObject);
}

/**
* Returns a string representation of the RenameMetadataObject instance. This string format
* includes the class name followed by the update metadata entity object operation.
*
* @return A string representation of the RenameMetadataObject instance.
*/
@Override
public String toString() {
return "RENAMEMETADATAOBJECT " + metadataObject + " " + newMetadataObject;
}
}

/** A RemoveMetadataObject is to remove securable object's metadata entity. */
final class RemoveMetadataObject implements MetadataObjectChange {
private final MetadataObject metadataObject;

private RemoveMetadataObject(MetadataObject metadataObject) {
this.metadataObject = metadataObject;
}

/**
* Returns the metadataObject to be renamed.
*
* @return return a metadataObject.
*/
public MetadataObject metadataObject() {
return metadataObject;
}

/**
* Compares this RemoveMetadataObject instance with another object for equality. The comparison
* is based on the old metadata entity.
*
* @param o The object to compare with this instance.
* @return true if the given object represents the same rename metadata entity; false otherwise.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RenameMetadataObject that = (RenameMetadataObject) o;
return metadataObject.equals(that.metadataObject);
}

/**
* Generates a hash code for this RemoveMetadataObject instance. The hash code is based on the
* old metadata entity.
*
* @return A hash code value for this update metadata entity operation.
*/
@Override
public int hashCode() {
return Objects.hash(metadataObject);
}

/**
* Returns a string representation of the RemoveMetadataObject instance. This string format
* includes the class name followed by the remove metadata entity object operation.
*
* @return A string representation of the RemoveMetadataObject instance.
*/
@Override
public String toString() {
return "REMOVEMETADATAOBJECT " + metadataObject;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,23 @@ public Set<Privilege.Name> allowPrivilegesRule() {
Privilege.Name.SELECT_TABLE);
}

/**
* Allow Gravitino MetadataObject type defines rule.
*
* @return The allow Gravitino MetadataObject type defines rule.
*/
@Override
public Set<MetadataObject.Type> allowMetadataObjectTypesRule() {
return ImmutableSet.of(
MetadataObject.Type.METALAKE,
MetadataObject.Type.CATALOG,
MetadataObject.Type.SCHEMA,
MetadataObject.Type.TABLE,
MetadataObject.Type.COLUMN);
}

/** Translate the Gravitino securable object to the Ranger owner securable object. */
@Override
public List<RangerSecurableObject> translateOwner(MetadataObject gravitinoMetadataObject) {
List<RangerSecurableObject> rangerSecurableObjects = new ArrayList<>();

Expand Down Expand Up @@ -195,14 +211,14 @@ public List<RangerSecurableObject> translateOwner(MetadataObject gravitinoMetada
// Add `{schema}.{table}` for the TABLE permission
rangerSecurableObjects.add(
generateRangerSecurableObject(
convertToRangerMetadataObject(gravitinoMetadataObject),
translateMetadataObject(gravitinoMetadataObject).names(),
RangerMetadataObject.Type.TABLE,
ownerMappingRule()));
// Add `{schema}.{table}.*` for the COLUMN permission
rangerSecurableObjects.add(
generateRangerSecurableObject(
Stream.concat(
convertToRangerMetadataObject(gravitinoMetadataObject).stream(),
translateMetadataObject(gravitinoMetadataObject).names().stream(),
Stream.of(RangerHelper.RESOURCE_ALL))
.collect(Collectors.toList()),
RangerMetadataObject.Type.COLUMN,
Expand All @@ -218,6 +234,7 @@ public List<RangerSecurableObject> translateOwner(MetadataObject gravitinoMetada
}

/** Translate the Gravitino securable object to the Ranger securable object. */
@Override
public List<RangerSecurableObject> translatePrivilege(SecurableObject securableObject) {
List<RangerSecurableObject> rangerSecurableObjects = new ArrayList<>();

Expand Down Expand Up @@ -352,14 +369,14 @@ public List<RangerSecurableObject> translatePrivilege(SecurableObject securableO
// Add `{schema}.{table}` for the TABLE permission
rangerSecurableObjects.add(
generateRangerSecurableObject(
convertToRangerMetadataObject(securableObject),
translateMetadataObject(securableObject).names(),
RangerMetadataObject.Type.TABLE,
rangerPrivileges));
// Add `{schema}.{table}.*` for the COLUMN permission
rangerSecurableObjects.add(
generateRangerSecurableObject(
Stream.concat(
convertToRangerMetadataObject(securableObject).stream(),
translateMetadataObject(securableObject).names().stream(),
Stream.of(RangerHelper.RESOURCE_ALL))
.collect(Collectors.toList()),
RangerMetadataObject.Type.COLUMN,
Expand All @@ -385,16 +402,39 @@ public List<RangerSecurableObject> translatePrivilege(SecurableObject securableO
}

/**
* Because the Ranger securable object is different from the Gravitino securable object, we need
* to convert the Gravitino securable object to the Ranger securable object.
* Because the Ranger metadata object is different from the Gravitino metadata object, we need to
* convert the Gravitino metadata object to the Ranger metadata object.
*/
List<String> convertToRangerMetadataObject(MetadataObject metadataObject) {
@Override
public RangerMetadataObject translateMetadataObject(MetadataObject metadataObject) {
Preconditions.checkArgument(
allowMetadataObjectTypesRule().contains(metadataObject.type()),
String.format(
"The metadata object type %s is not supported in the RangerAuthorizationHivePlugin",
metadataObject.type()));
Preconditions.checkArgument(
!(metadataObject instanceof RangerPrivileges),
"The metadata object must be not a RangerPrivileges object.");
List<String> nsMetadataObject =
Lists.newArrayList(SecurableObjects.DOT_SPLITTER.splitToList(metadataObject.fullName()));
nsMetadataObject.remove(0); // remove the catalog name
return nsMetadataObject;
Preconditions.checkArgument(
nsMetadataObject.size() > 0, "The metadata object must have at least one name.");

RangerMetadataObject.Type type;
if (metadataObject.type() == MetadataObject.Type.METALAKE
|| metadataObject.type() == MetadataObject.Type.CATALOG) {
nsMetadataObject.clear();
nsMetadataObject.add(RangerHelper.RESOURCE_ALL);
type = RangerMetadataObject.Type.SCHEMA;
} else {
nsMetadataObject.remove(0); // Remove the catalog name
type = RangerMetadataObject.Type.fromMetadataType(metadataObject.type());
}

validateRangerMetadataObject(nsMetadataObject, type);
return new RangerMetadataObjects.RangerMetadataObjectImpl(
RangerMetadataObjects.getParentFullName(nsMetadataObject),
RangerMetadataObjects.getLastName(nsMetadataObject),
type);
}
}
Loading

0 comments on commit b913e98

Please sign in to comment.