Skip to content

Commit

Permalink
[#5106] improve(auth-ranger): Filter Catalog securiable object in the…
Browse files Browse the repository at this point in the history
… onOwnerSet
  • Loading branch information
xunliu committed Oct 16, 2024
1 parent b7f4e34 commit b2cb8f2
Show file tree
Hide file tree
Showing 16 changed files with 2,662 additions and 586 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 -PskipTests -PtestMode=embedded -PjdbcBackend=h2 -PjdkVersion=${{ matrix.java-version }} -PskipDockerTests=false :authorizations:authorization-ranger:test --tests "org.apache.gravitino.authorization.ranger.integration.test.**"
./gradlew -PskipTests -PtestMode=deploy -PjdbcBackend=mysql -PjdkVersion=${{ matrix.java-version }} -PskipDockerTests=false :authorizations:authorization-ranger:test --tests "org.apache.gravitino.authorization.ranger.integration.test.**"
./gradlew -PskipTests -PtestMode=deploy -PjdbcBackend=postgresql -PjdkVersion=${{ matrix.java-version }} -PskipDockerTests=false :authorizations:authorization-ranger:test --tests "org.apache.gravitino.authorization.ranger.integration.test.**"
./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.**"
- name: Upload integrate tests reports
uses: actions/upload-artifact@v3
Expand Down
8 changes: 7 additions & 1 deletion api/src/main/java/org/apache/gravitino/MetadataObjects.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,13 @@ public static MetadataObject parse(String fullName, MetadataObject.Type type) {
return MetadataObjects.of(parts, type);
}

private static String getParentFullName(List<String> names) {
/**
* Get the parent full name of the given full name.
*
* @param names The names of the metadata object
* @return The parent full name if it exists, otherwise null
*/
public static String getParentFullName(List<String> names) {
if (names.size() <= 1) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,26 @@
*/
package org.apache.gravitino.authorization.ranger;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.gravitino.MetadataObject;
import org.apache.gravitino.authorization.Privilege;
import org.apache.gravitino.authorization.ranger.RangerPrivilege.RangerHivePrivilege;
import org.apache.gravitino.authorization.SecurableObject;
import org.apache.gravitino.authorization.SecurableObjects;
import org.apache.gravitino.authorization.ranger.RangerPrivileges.RangerHivePrivilege;
import org.apache.gravitino.authorization.ranger.reference.RangerDefines.PolicyResource;
import org.apache.gravitino.exceptions.AuthorizationPluginException;

public class RangerAuthorizationHivePlugin extends RangerAuthorizationPlugin {
private static volatile RangerAuthorizationHivePlugin instance = null;
Expand All @@ -46,6 +57,7 @@ public static synchronized RangerAuthorizationHivePlugin getInstance(Map<String,
return instance;
}

@Override
/** Set the default mapping Gravitino privilege name to the Ranger rule */
public Map<Privilege.Name, Set<RangerPrivilege>> privilegesMappingRule() {
return ImmutableMap.of(
Expand All @@ -60,16 +72,235 @@ public Map<Privilege.Name, Set<RangerPrivilege>> privilegesMappingRule() {
ImmutableSet.of(RangerHivePrivilege.READ, RangerHivePrivilege.SELECT));
}

@Override
/** Set the default owner rule. */
public Set<RangerPrivilege> ownerMappingRule() {
return ImmutableSet.of(RangerHivePrivilege.ALL);
}

@Override
/** Set Ranger policy resource rule. */
public List<String> policyResourceDefinesRule() {
return ImmutableList.of(
PolicyResource.DATABASE.getName(),
PolicyResource.TABLE.getName(),
PolicyResource.COLUMN.getName());
}

@Override
/** Allow privilege operation defines rule. */
public Set<Privilege.Name> allowPrivilegesRule() {
return ImmutableSet.of(
Privilege.Name.CREATE_CATALOG,
Privilege.Name.CREATE_SCHEMA,
Privilege.Name.CREATE_TABLE,
Privilege.Name.MODIFY_TABLE,
Privilege.Name.SELECT_TABLE);
}

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

switch (metadataObject.type()) {
case METALAKE:
case CATALOG:
// Add `*` for the SCHEMA permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(RangerHelper.RESOURCE_STAR),
MetadataObject.Type.SCHEMA,
ownerMappingRule()));
// Add `*.*` for the TABLE permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(RangerHelper.RESOURCE_STAR, RangerHelper.RESOURCE_STAR),
MetadataObject.Type.TABLE,
ownerMappingRule()));
// Add `*.*.*` for the COLUMN permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(
RangerHelper.RESOURCE_STAR,
RangerHelper.RESOURCE_STAR,
RangerHelper.RESOURCE_STAR),
MetadataObject.Type.COLUMN,
ownerMappingRule()));
break;
case SCHEMA:
// Add `{schema}` for the SCHEMA permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(metadataObject.name() /*Schema name*/),
MetadataObject.Type.SCHEMA,
ownerMappingRule()));
// Add `{schema}.*` for the TABLE permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(metadataObject.name() /*Schema name*/, RangerHelper.RESOURCE_STAR),
MetadataObject.Type.TABLE,
ownerMappingRule()));
// Add `{schema}.*.*` for the COLUMN permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(
metadataObject.name() /*Schema name*/,
RangerHelper.RESOURCE_STAR,
RangerHelper.RESOURCE_STAR),
MetadataObject.Type.COLUMN,
ownerMappingRule()));
break;
case TABLE:
// Add `{schema}.{table}` for the TABLE permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
convertToRangerMetadataObject(metadataObject),
MetadataObject.Type.TABLE,
ownerMappingRule()));
// Add `{schema}.{table}.*` for the COLUMN permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
Stream.concat(
convertToRangerMetadataObject(metadataObject).stream(),
Stream.of(RangerHelper.RESOURCE_STAR))
.collect(Collectors.toList()),
MetadataObject.Type.COLUMN,
ownerMappingRule()));
break;
default:
throw new AuthorizationPluginException(
"The owner privilege is not supported for the securable object: %s",
metadataObject.type());
}

return rangerSecurableObjects;
}

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

securableObject.privileges().stream()
.filter(Objects::nonNull)
.forEach(
privilege -> {
Set<RangerPrivilege> rangerPrivileges = new HashSet<>();
privilegesMappingRule().get(privilege.name()).stream()
.forEach(
rangerPrivilege ->
rangerPrivileges.add(
new RangerPrivileges.RangerHivePrivilegeImpl(
rangerPrivilege, privilege.condition())));

switch (privilege.name()) {
case CREATE_SCHEMA:
switch (securableObject.type()) {
case METALAKE:
case CATALOG:
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(RangerHelper.RESOURCE_STAR),
MetadataObject.Type.SCHEMA,
rangerPrivileges));
break;
default:
throw new AuthorizationPluginException(
"The privilege %s is not supported for the securable object: %s",
privilege.name(), securableObject.type());
}
break;
case CREATE_TABLE:
case MODIFY_TABLE:
case SELECT_TABLE:
switch (securableObject.type()) {
case METALAKE:
case CATALOG:
// Add `*.*` for the TABLE permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(
RangerHelper.RESOURCE_STAR, RangerHelper.RESOURCE_STAR),
MetadataObject.Type.TABLE,
rangerPrivileges));
// Add `*.*.*` for the COLUMN permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(
RangerHelper.RESOURCE_STAR,
RangerHelper.RESOURCE_STAR,
RangerHelper.RESOURCE_STAR),
MetadataObject.Type.COLUMN,
rangerPrivileges));
break;
case SCHEMA:
// Add `{schema}.*` for the TABLE permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(
securableObject.name() /*Schema name*/,
RangerHelper.RESOURCE_STAR),
MetadataObject.Type.TABLE,
rangerPrivileges));
// Add `{schema}.*.*` for the COLUMN permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
ImmutableList.of(
securableObject.name() /*Schema name*/,
RangerHelper.RESOURCE_STAR,
RangerHelper.RESOURCE_STAR),
MetadataObject.Type.COLUMN,
rangerPrivileges));
break;
case TABLE:
if (privilege.name() == Privilege.Name.CREATE_TABLE) {
throw new AuthorizationPluginException(
"The privilege %s is not supported for the securable object: %s",
privilege.name(), securableObject.type());
} else {
// Add `{schema}.{table}` for the TABLE permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
convertToRangerMetadataObject(securableObject),
MetadataObject.Type.TABLE,
rangerPrivileges));
// Add `{schema}.{table}.*` for the COLUMN permission
rangerSecurableObjects.add(
RangerSecurableObjects.of(
Stream.concat(
convertToRangerMetadataObject(securableObject).stream(),
Stream.of(RangerHelper.RESOURCE_STAR))
.collect(Collectors.toList()),
MetadataObject.Type.COLUMN,
rangerPrivileges));
}
break;
default:
throw new AuthorizationPluginException(
"The privilege %s is not supported for the securable object: %s",
privilege.name(), securableObject.type());
}
break;
default:
throw new AuthorizationPluginException(
"The privilege %s is not supported for the securable object: %s",
privilege.name(), securableObject.type());
}
});

return rangerSecurableObjects;
}

/**
* 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.
*/
List<String> convertToRangerMetadataObject(MetadataObject metadataObject) {
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;
}
}
Loading

0 comments on commit b2cb8f2

Please sign in to comment.