Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#5124][#5146] feat(auth-ranger): Ranger plugin should support rename operation #5375

Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading