This is an automated email from the ASF dual-hosted git repository. roryqi pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push: new be8e1519f3 [#6695] fix(authz): Fix the error privileges (#6821) be8e1519f3 is described below commit be8e1519f31d1588b0ed96d70739d28e15a13ada Author: roryqi <h...@datastrato.com> AuthorDate: Wed Apr 9 10:08:37 2025 +0800 [#6695] fix(authz): Fix the error privileges (#6821) ### What changes were proposed in this pull request? Fix the error privileges. ### Why are the changes needed? Fix: #6695 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Add UT. --- .../common/PathBasedMetadataObject.java | 15 ++ .../common/PathBasedSecurableObject.java | 3 +- .../ranger/RangerAuthorizationHDFSPlugin.java | 238 ++++++++++++++------- .../ranger/RangerAuthorizationHadoopSQLPlugin.java | 35 +-- .../ranger/RangerAuthorizationPlugin.java | 5 +- .../test/RangerAuthorizationHDFSPluginIT.java | 122 +++++++++-- .../ranger/integration/test/RangerHiveIT.java | 5 +- .../ranger/integration/test/RangerITEnv.java | 4 +- 8 files changed, 296 insertions(+), 131 deletions(-) diff --git a/authorizations/authorization-common/src/main/java/org/apache/gravitino/authorization/common/PathBasedMetadataObject.java b/authorizations/authorization-common/src/main/java/org/apache/gravitino/authorization/common/PathBasedMetadataObject.java index 7b65fbd56f..c3bae05327 100644 --- a/authorizations/authorization-common/src/main/java/org/apache/gravitino/authorization/common/PathBasedMetadataObject.java +++ b/authorizations/authorization-common/src/main/java/org/apache/gravitino/authorization/common/PathBasedMetadataObject.java @@ -92,15 +92,26 @@ public class PathBasedMetadataObject implements AuthorizationMetadataObject { private final String name; private final String parent; private final String path; + private final boolean recursive; private final AuthorizationMetadataObject.Type type; public PathBasedMetadataObject( String parent, String name, String path, AuthorizationMetadataObject.Type type) { + this(parent, name, path, type, true); + } + + public PathBasedMetadataObject( + String parent, + String name, + String path, + AuthorizationMetadataObject.Type type, + boolean recursive) { this.parent = parent; this.name = name; this.path = path; this.type = type; + this.recursive = recursive; } @Override @@ -122,6 +133,10 @@ public class PathBasedMetadataObject implements AuthorizationMetadataObject { return path; } + public boolean recursive() { + return recursive; + } + @Override public AuthorizationMetadataObject.Type type() { return this.type; diff --git a/authorizations/authorization-common/src/main/java/org/apache/gravitino/authorization/common/PathBasedSecurableObject.java b/authorizations/authorization-common/src/main/java/org/apache/gravitino/authorization/common/PathBasedSecurableObject.java index aa2262fb16..5e61e4a701 100644 --- a/authorizations/authorization-common/src/main/java/org/apache/gravitino/authorization/common/PathBasedSecurableObject.java +++ b/authorizations/authorization-common/src/main/java/org/apache/gravitino/authorization/common/PathBasedSecurableObject.java @@ -35,8 +35,9 @@ public class PathBasedSecurableObject extends PathBasedMetadataObject String name, String path, AuthorizationMetadataObject.Type type, + boolean recursive, Set<AuthorizationPrivilege> privileges) { - super(parent, name, path, type); + super(parent, name, path, type, recursive); this.privileges = ImmutableList.copyOf(privileges); } diff --git a/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationHDFSPlugin.java b/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationHDFSPlugin.java index 588e5df18a..ccc7326b8c 100644 --- a/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationHDFSPlugin.java +++ b/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationHDFSPlugin.java @@ -107,6 +107,12 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { RangerPrivileges.RangerHdfsPrivilege.EXECUTE), Privilege.Name.WRITE_FILESET, ImmutableSet.of( + RangerPrivileges.RangerHdfsPrivilege.READ, + RangerPrivileges.RangerHdfsPrivilege.WRITE, + RangerPrivileges.RangerHdfsPrivilege.EXECUTE), + Privilege.Name.CREATE_FILESET, + ImmutableSet.of( + RangerPrivileges.RangerHdfsPrivilege.READ, RangerPrivileges.RangerHdfsPrivilege.WRITE, RangerPrivileges.RangerHdfsPrivilege.EXECUTE)); } @@ -252,11 +258,11 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { */ @Override protected void removeMetadataObject(AuthorizationMetadataObject authzMetadataObject) { - if (authzMetadataObject.type().equals(PathBasedMetadataObject.SCHEMA_PATH)) { + if (authzMetadataObject.metadataObjectType() == MetadataObject.Type.SCHEMA) { removeSchemaMetadataObject(authzMetadataObject); - } else if (authzMetadataObject.type().equals(PathBasedMetadataObject.TABLE_PATH)) { + } else if (authzMetadataObject.metadataObjectType() == MetadataObject.Type.TABLE) { removeTableMetadataObject(authzMetadataObject); - } else if (authzMetadataObject.type().equals(PathBasedMetadataObject.FILESET_PATH)) { + } else if (authzMetadataObject.metadataObjectType() == MetadataObject.Type.FILESET) { removePolicyByMetadataObject(authzMetadataObject); } else if (authzMetadataObject.metadataObjectType() == MetadataObject.Type.METALAKE || authzMetadataObject.metadataObjectType() == MetadataObject.Type.CATALOG) { @@ -305,29 +311,26 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { policy.setName(getAuthorizationPath(pathBasedMetadataObject)); RangerPolicy.RangerPolicyResource policyResource = new RangerPolicy.RangerPolicyResource( - getAuthorizationPath(pathBasedMetadataObject), false, true); + getAuthorizationPath(pathBasedMetadataObject), + false, + pathBasedMetadataObject.recursive()); policy.getResources().put(RangerDefines.PolicyResource.PATH.getName(), policyResource); return policy; } @Override public AuthorizationSecurableObject generateAuthorizationSecurableObject( - List<String> names, - String path, - AuthorizationMetadataObject.Type type, - Set<AuthorizationPrivilege> privileges) { - AuthorizationMetadataObject authMetadataObject = - new PathBasedMetadataObject( - AuthorizationMetadataObject.getParentFullName(names), - AuthorizationMetadataObject.getLastName(names), - path, - type); - authMetadataObject.validateAuthorizationMetadataObject(); + AuthorizationMetadataObject object, Set<AuthorizationPrivilege> privileges) { + object.validateAuthorizationMetadataObject(); + Preconditions.checkArgument( + object instanceof PathBasedMetadataObject, "Object must be a path based metadata object"); + PathBasedMetadataObject metadataObject = (PathBasedMetadataObject) object; return new PathBasedSecurableObject( - authMetadataObject.parent(), - authMetadataObject.name(), - path, - authMetadataObject.type(), + metadataObject.parent(), + metadataObject.name(), + metadataObject.path(), + metadataObject.type(), + metadataObject.recursive(), privileges); } @@ -388,7 +391,11 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { switch (securableObject.type()) { case METALAKE: extractMetalakeLocations( - securableObject, identifier, rangerSecurableObjects, rangerPrivileges); + securableObject, + identifier, + rangerSecurableObjects, + rangerPrivileges, + true); break; case CATALOG: case SCHEMA: @@ -400,7 +407,8 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { securableObject, locationPath, rangerSecurableObjects, - rangerPrivileges); + rangerPrivileges, + true); }); break; default: @@ -414,7 +422,11 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { switch (securableObject.type()) { case METALAKE: extractMetalakeLocations( - securableObject, identifier, rangerSecurableObjects, rangerPrivileges); + securableObject, + identifier, + rangerSecurableObjects, + rangerPrivileges, + false); break; case CATALOG: AuthorizationUtils.getMetadataObjectLocation( @@ -425,7 +437,8 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { securableObject, locationPath, rangerSecurableObjects, - rangerPrivileges)); + rangerPrivileges, + false)); break; default: throw new AuthorizationPluginException( @@ -435,54 +448,36 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { } break; case SELECT_TABLE: - case CREATE_TABLE: case MODIFY_TABLE: - AuthorizationUtils.getMetadataObjectLocation( - identifier, MetadataObjectUtil.toEntityType(securableObject)) - .forEach( - locationPath -> { - PathBasedMetadataObject pathBaseMetadataObject = - new PathBasedMetadataObject( - securableObject.parent(), - securableObject.name(), - locationPath, - PathBasedMetadataObject.PathType.get(securableObject.type())); - pathBaseMetadataObject.validateAuthorizationMetadataObject(); - rangerSecurableObjects.add( - generateAuthorizationSecurableObject( - pathBaseMetadataObject.names(), - locationPath, - PathBasedMetadataObject.PathType.get(securableObject.type()), - rangerPrivileges)); - }); - break; - case CREATE_FILESET: - // Ignore the Gravitino privilege `CREATE_FILESET` in the - // RangerAuthorizationHDFSPlugin - break; case READ_FILESET: case WRITE_FILESET: + if (!gravitinoPrivilege.canBindTo(securableObject.type())) { + throw new AuthorizationPluginException( + ErrorMessages.PRIVILEGE_NOT_SUPPORTED, + gravitinoPrivilege.name(), + securableObject.type()); + } + createSecurableObjects( + securableObject, + rangerSecurableObjects, + identifier, + rangerPrivileges, + true, + new TableOrFilesetPathExtractor()); + break; + case CREATE_TABLE: + case CREATE_FILESET: switch (securableObject.type()) { case METALAKE: case CATALOG: case SCHEMA: - break; - case FILESET: - translateMetadataObject(securableObject) - .forEach( - metadataObject -> { - Preconditions.checkArgument( - metadataObject instanceof PathBasedMetadataObject, - "The metadata object must be a PathBasedMetadataObject"); - PathBasedMetadataObject pathBasedMetadataObject = - (PathBasedMetadataObject) metadataObject; - rangerSecurableObjects.add( - generateAuthorizationSecurableObject( - pathBasedMetadataObject.names(), - getAuthorizationPath(pathBasedMetadataObject), - PathBasedMetadataObject.FILESET_PATH, - rangerPrivileges)); - }); + createSecurableObjects( + securableObject, + rangerSecurableObjects, + identifier, + rangerPrivileges, + false, + new SchemaPathExtractor()); break; default: throw new AuthorizationPluginException( @@ -502,11 +497,50 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { return rangerSecurableObjects; } + private void createSecurableObjects( + SecurableObject securableObject, + List<AuthorizationSecurableObject> rangerSecurableObjects, + NameIdentifier identifier, + Set<AuthorizationPrivilege> rangerPrivileges, + boolean recursive, + PathExtractor pathExtractor) { + Entity.EntityType type = MetadataObjectUtil.toEntityType(securableObject); + List<String> locations = Lists.newArrayList(); + if (type == Entity.EntityType.METALAKE) { + NameIdentifier[] catalogs = + GravitinoEnv.getInstance() + .catalogDispatcher() + .listCatalogs(Namespace.of(identifier.name())); + for (NameIdentifier catalog : catalogs) { + locations.addAll( + AuthorizationUtils.getMetadataObjectLocation(catalog, Entity.EntityType.CATALOG)); + } + } else { + locations.addAll(AuthorizationUtils.getMetadataObjectLocation(identifier, type)); + } + + locations.forEach( + locationPath -> { + PathBasedMetadataObject pathBaseMetadataObject = + new PathBasedMetadataObject( + securableObject.parent(), + securableObject.name(), + pathExtractor.getPath( + MetadataObjectUtil.toEntityType(securableObject), locationPath), + PathBasedMetadataObject.PathType.get(securableObject.type()), + recursive); + pathBaseMetadataObject.validateAuthorizationMetadataObject(); + rangerSecurableObjects.add( + generateAuthorizationSecurableObject(pathBaseMetadataObject, rangerPrivileges)); + }); + } + private void extractMetalakeLocations( SecurableObject securableObject, NameIdentifier identifier, List<AuthorizationSecurableObject> rangerSecurableObjects, - Set<AuthorizationPrivilege> rangerPrivileges) { + Set<AuthorizationPrivilege> rangerPrivileges, + boolean recursive) { NameIdentifier[] catalogs = GravitinoEnv.getInstance() .catalogDispatcher() @@ -516,7 +550,11 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { .forEach( locationPath -> createPathBasedMetadataObject( - securableObject, locationPath, rangerSecurableObjects, rangerPrivileges)); + securableObject, + locationPath, + rangerSecurableObjects, + rangerPrivileges, + recursive)); } } @@ -524,18 +562,18 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { SecurableObject securableObject, String locationPath, List<AuthorizationSecurableObject> rangerSecurableObjects, - Set<AuthorizationPrivilege> rangerPrivileges) { + Set<AuthorizationPrivilege> rangerPrivileges, + boolean recursive) { PathBasedMetadataObject pathBaseMetadataObject = new PathBasedMetadataObject( securableObject.parent(), securableObject.name(), locationPath, - PathBasedMetadataObject.PathType.get(securableObject.type())); + PathBasedMetadataObject.PathType.get(securableObject.type()), + recursive); pathBaseMetadataObject.validateAuthorizationMetadataObject(); rangerSecurableObjects.add( - generateAuthorizationSecurableObject( - pathBaseMetadataObject.names(), locationPath, - PathBasedMetadataObject.PathType.get(securableObject.type()), rangerPrivileges)); + generateAuthorizationSecurableObject(pathBaseMetadataObject, rangerPrivileges)); } @Override @@ -558,10 +596,7 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { (PathBasedMetadataObject) metadataObject; rangerSecurableObjects.add( generateAuthorizationSecurableObject( - pathBasedMetadataObject.names(), - getAuthorizationPath(pathBasedMetadataObject), - pathBasedMetadataObject.type(), - ownerMappingRule())); + pathBasedMetadataObject, ownerMappingRule())); }); break; default: @@ -581,6 +616,7 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { ? NameIdentifier.of(metadataObject.fullName()) : NameIdentifier.parse(String.join(".", metalake, metadataObject.fullName())); List<String> locations = AuthorizationUtils.getMetadataObjectLocation(identifier, entityType); + locations.forEach( locationPath -> { AuthorizationMetadataObject.Type type = @@ -740,4 +776,56 @@ public class RangerAuthorizationHDFSPlugin extends RangerAuthorizationPlugin { RangerAuthorizationProperties.FS_DEFAULT_VALUE)) .build(); } + + private interface PathExtractor { + String getPath(Entity.EntityType type, String location); + } + + /** The extractor will extra the table or fileset level location path for this entity */ + private static class TableOrFilesetPathExtractor implements PathExtractor { + /** + * This method will return table or fileset level path for this entity + * + * @param type The entity type + * @param location The location of this entity + * @return The table or file locations of this entity + */ + @Override + public String getPath(Entity.EntityType type, String location) { + if (type == Entity.EntityType.CATALOG) { + return String.format("%s/*/*/", location); + } else if (type == Entity.EntityType.SCHEMA) { + return String.format("%s/*/", location); + } + if (type == Entity.EntityType.TABLE || type == Entity.EntityType.FILESET) { + return location; + } else { + throw new AuthorizationPluginException( + "It's not allowed to extract table or fileset path from entity %s", type); + } + } + } + + /** The extractor will extra the schema level location path for this entity */ + private static class SchemaPathExtractor implements PathExtractor { + + /** + * This method will return schema level path for this entity + * + * @param type The entity type + * @param location The location of this entity + * @return The schema locations of this entity + */ + @Override + public String getPath(Entity.EntityType type, String location) { + if (type == Entity.EntityType.CATALOG) { + return String.format("%s/*/", location); + } else if (type == Entity.EntityType.SCHEMA) { + return location; + } else { + throw new AuthorizationPluginException( + "It's not allowed to extract table or fileset path from entity %s", type); + } + } + } } diff --git a/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationHadoopSQLPlugin.java b/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationHadoopSQLPlugin.java index d519dd2e52..315febcba7 100644 --- a/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationHadoopSQLPlugin.java +++ b/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationHadoopSQLPlugin.java @@ -396,23 +396,24 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi return policy; } - @Override public AuthorizationSecurableObject generateAuthorizationSecurableObject( List<String> names, - String path, AuthorizationMetadataObject.Type type, Set<AuthorizationPrivilege> privileges) { - AuthorizationMetadataObject authMetadataObject = + RangerHadoopSQLMetadataObject object = new RangerHadoopSQLMetadataObject( AuthorizationMetadataObject.getParentFullName(names), AuthorizationMetadataObject.getLastName(names), type); - authMetadataObject.validateAuthorizationMetadataObject(); + return generateAuthorizationSecurableObject(object, privileges); + } + + @Override + public AuthorizationSecurableObject generateAuthorizationSecurableObject( + AuthorizationMetadataObject object, Set<AuthorizationPrivilege> privileges) { + object.validateAuthorizationMetadataObject(); return new RangerHadoopSQLSecurableObject( - authMetadataObject.parent(), - authMetadataObject.name(), - authMetadataObject.type(), - privileges); + object.parent(), object.name(), object.type(), privileges); } @Override @@ -455,14 +456,12 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi rangerSecurableObjects.add( generateAuthorizationSecurableObject( ImmutableList.of(RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.SCHEMA, ownerMappingRule())); // Add `*.*` for the TABLE permission rangerSecurableObjects.add( generateAuthorizationSecurableObject( ImmutableList.of(RangerHelper.RESOURCE_ALL, RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.TABLE, ownerMappingRule())); // Add `*.*.*` for the COLUMN permission @@ -472,7 +471,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi RangerHelper.RESOURCE_ALL, RangerHelper.RESOURCE_ALL, RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.COLUMN, ownerMappingRule())); break; @@ -481,7 +479,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi rangerSecurableObjects.add( generateAuthorizationSecurableObject( ImmutableList.of(gravitinoMetadataObject.name() /*Schema name*/), - null, RangerHadoopSQLMetadataObject.Type.SCHEMA, ownerMappingRule())); // Add `{schema}.*` for the TABLE permission @@ -489,7 +486,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi generateAuthorizationSecurableObject( ImmutableList.of( gravitinoMetadataObject.name() /*Schema name*/, RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.TABLE, ownerMappingRule())); // Add `{schema}.*.*` for the COLUMN permission @@ -499,7 +495,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi gravitinoMetadataObject.name() /*Schema name*/, RangerHelper.RESOURCE_ALL, RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.COLUMN, ownerMappingRule())); break; @@ -511,7 +506,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi rangerSecurableObjects.add( generateAuthorizationSecurableObject( rangerMetadataObject.names(), - null, RangerHadoopSQLMetadataObject.Type.TABLE, ownerMappingRule())); // Add `{schema}.{table}.*` for the COLUMN permission @@ -521,7 +515,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi rangerMetadataObject.names().stream(), Stream.of(RangerHelper.RESOURCE_ALL)) .collect(Collectors.toList()), - null, RangerHadoopSQLMetadataObject.Type.COLUMN, ownerMappingRule())); }); @@ -568,7 +561,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi rangerSecurableObjects.add( generateAuthorizationSecurableObject( ImmutableList.of(RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.SCHEMA, rangerPrivileges)); break; @@ -587,7 +579,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi rangerSecurableObjects.add( generateAuthorizationSecurableObject( ImmutableList.of(RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.SCHEMA, rangerPrivileges)); break; @@ -606,7 +597,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi rangerSecurableObjects.add( generateAuthorizationSecurableObject( ImmutableList.of(RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.SCHEMA, rangerPrivileges)); break; @@ -615,7 +605,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi rangerSecurableObjects.add( generateAuthorizationSecurableObject( ImmutableList.of(securableObject.name() /*Schema name*/), - null, RangerHadoopSQLMetadataObject.Type.SCHEMA, rangerPrivileges)); break; @@ -637,7 +626,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi generateAuthorizationSecurableObject( ImmutableList.of( RangerHelper.RESOURCE_ALL, RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.TABLE, rangerPrivileges)); // Add `*.*.*` for the COLUMN permission @@ -647,7 +635,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi RangerHelper.RESOURCE_ALL, RangerHelper.RESOURCE_ALL, RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.COLUMN, rangerPrivileges)); break; @@ -658,7 +645,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi ImmutableList.of( securableObject.name() /*Schema name*/, RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.TABLE, rangerPrivileges)); // Add `{schema}.*.*` for the COLUMN permission @@ -668,7 +654,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi securableObject.name() /*Schema name*/, RangerHelper.RESOURCE_ALL, RangerHelper.RESOURCE_ALL), - null, RangerHadoopSQLMetadataObject.Type.COLUMN, rangerPrivileges)); break; @@ -686,7 +671,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi rangerSecurableObjects.add( generateAuthorizationSecurableObject( rangerMetadataObject.names(), - null, RangerHadoopSQLMetadataObject.Type.TABLE, rangerPrivileges)); // Add `{schema}.{table}.*` for the COLUMN permission @@ -696,7 +680,6 @@ public class RangerAuthorizationHadoopSQLPlugin extends RangerAuthorizationPlugi rangerMetadataObject.names().stream(), Stream.of(RangerHelper.RESOURCE_ALL)) .collect(Collectors.toList()), - null, RangerHadoopSQLMetadataObject.Type.COLUMN, rangerPrivileges)); }); diff --git a/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationPlugin.java b/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationPlugin.java index 5007444e10..78a9a25596 100644 --- a/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationPlugin.java +++ b/authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationPlugin.java @@ -1028,10 +1028,7 @@ public abstract class RangerAuthorizationPlugin /** Generate authorization securable object */ public abstract AuthorizationSecurableObject generateAuthorizationSecurableObject( - List<String> names, - String path, - AuthorizationMetadataObject.Type type, - Set<AuthorizationPrivilege> privileges); + AuthorizationMetadataObject object, Set<AuthorizationPrivilege> privileges); public boolean validAuthorizationOperation(List<SecurableObject> securableObjects) { return securableObjects.stream() diff --git a/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerAuthorizationHDFSPluginIT.java b/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerAuthorizationHDFSPluginIT.java index 056f5292b9..a50d677fef 100644 --- a/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerAuthorizationHDFSPluginIT.java +++ b/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerAuthorizationHDFSPluginIT.java @@ -18,10 +18,16 @@ */ package org.apache.gravitino.authorization.ranger.integration.test; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import java.util.List; +import org.apache.commons.lang3.reflect.FieldUtils; import org.apache.gravitino.Entity; +import org.apache.gravitino.GravitinoEnv; import org.apache.gravitino.MetadataObject; import org.apache.gravitino.MetadataObjects; import org.apache.gravitino.NameIdentifier; @@ -33,6 +39,7 @@ import org.apache.gravitino.authorization.SecurableObjects; import org.apache.gravitino.authorization.common.PathBasedMetadataObject; import org.apache.gravitino.authorization.common.PathBasedSecurableObject; import org.apache.gravitino.authorization.ranger.RangerAuthorizationPlugin; +import org.apache.gravitino.catalog.CatalogDispatcher; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -45,11 +52,14 @@ import org.mockito.Mockito; public class RangerAuthorizationHDFSPluginIT { private static RangerAuthorizationPlugin rangerAuthPlugin; + private static final CatalogDispatcher manager = mock(CatalogDispatcher.class); @BeforeAll - public static void setup() { + public static void setup() throws Exception { RangerITEnv.init(RangerITEnv.currentFunName(), true); rangerAuthPlugin = RangerITEnv.rangerAuthHDFSPlugin; + FieldUtils.writeField(GravitinoEnv.getInstance(), "catalogDispatcher", manager, true); + when(manager.listCatalogs(any())).thenReturn(new NameIdentifier[0]); } @AfterAll @@ -162,50 +172,122 @@ public class RangerAuthorizationHDFSPluginIT { rangerAuthPlugin.translatePrivilege(filesetInMetalake); Assertions.assertEquals(0, filesetInMetalake1.size()); - SecurableObject filesetInCatalog = + SecurableObject catalogObject = SecurableObjects.parse( "catalog1", MetadataObject.Type.CATALOG, Lists.newArrayList( Privileges.CreateFileset.allow(), Privileges.ReadFileset.allow(), - Privileges.WriteFileset.allow())); - List<AuthorizationSecurableObject> filesetInCatalog1 = - rangerAuthPlugin.translatePrivilege(filesetInCatalog); - Assertions.assertEquals(0, filesetInCatalog1.size()); + Privileges.WriteFileset.allow(), + Privileges.CreateTable.allow(), + Privileges.SelectTable.allow(), + Privileges.ModifyTable.allow())); + List<AuthorizationSecurableObject> authzCatalogObjects = + rangerAuthPlugin.translatePrivilege(catalogObject); + Assertions.assertEquals(6, authzCatalogObjects.size()); + Assertions.assertEquals( + 4, + (int) + authzCatalogObjects.stream() + .filter( + authorizationSecurableObject -> { + PathBasedMetadataObject pathBasedMetadataObject = + ((PathBasedMetadataObject) authorizationSecurableObject); + return pathBasedMetadataObject.path().equals("/test/*/*/") + && pathBasedMetadataObject.recursive(); + }) + .count()); + + Assertions.assertEquals( + 2, + (int) + authzCatalogObjects.stream() + .filter( + authorizationSecurableObject -> { + PathBasedMetadataObject pathBasedMetadataObject = + ((PathBasedMetadataObject) authorizationSecurableObject); + return pathBasedMetadataObject.path().equals("/test/*/") + && !pathBasedMetadataObject.recursive(); + }) + .count()); - SecurableObject filesetInSchema = + SecurableObject schemaObject = SecurableObjects.parse( "catalog1.schema1", MetadataObject.Type.SCHEMA, Lists.newArrayList( Privileges.CreateFileset.allow(), Privileges.ReadFileset.allow(), - Privileges.WriteFileset.allow())); - List<AuthorizationSecurableObject> filesetInSchema1 = - rangerAuthPlugin.translatePrivilege(filesetInSchema); - Assertions.assertEquals(0, filesetInSchema1.size()); + Privileges.WriteFileset.allow(), + Privileges.CreateTable.allow(), + Privileges.SelectTable.allow(), + Privileges.ModifyTable.allow())); + List<AuthorizationSecurableObject> authzSchemaObjects = + rangerAuthPlugin.translatePrivilege(schemaObject); + Assertions.assertEquals(6, authzSchemaObjects.size()); + Assertions.assertEquals( + 4, + (int) + authzSchemaObjects.stream() + .filter( + authorizationSecurableObject -> { + PathBasedMetadataObject pathBasedMetadataObject = + ((PathBasedMetadataObject) authorizationSecurableObject); + return pathBasedMetadataObject.path().equals("/test/*/") + && pathBasedMetadataObject.recursive(); + }) + .count()); + + Assertions.assertEquals( + 2, + (int) + authzSchemaObjects.stream() + .filter( + authorizationSecurableObject -> { + PathBasedMetadataObject pathBasedMetadataObject = + ((PathBasedMetadataObject) authorizationSecurableObject); + return pathBasedMetadataObject.path().equals("/test") + && !pathBasedMetadataObject.recursive(); + }) + .count()); - SecurableObject filesetInFileset = + SecurableObject filesetObject = SecurableObjects.parse( "catalog1.schema1.fileset1", MetadataObject.Type.FILESET, Lists.newArrayList( - Privileges.CreateFileset.allow(), - Privileges.ReadFileset.allow(), - Privileges.WriteFileset.allow())); - List<AuthorizationSecurableObject> filesetInFileset1 = - rangerAuthPlugin.translatePrivilege(filesetInFileset); - Assertions.assertEquals(2, filesetInFileset1.size()); + Privileges.ReadFileset.allow(), Privileges.WriteFileset.allow())); + List<AuthorizationSecurableObject> filesetObjects = + rangerAuthPlugin.translatePrivilege(filesetObject); + Assertions.assertEquals(2, filesetObjects.size()); - filesetInFileset1.forEach( + filesetObjects.forEach( securableObject -> { PathBasedSecurableObject pathBasedSecurableObject = (PathBasedSecurableObject) securableObject; Assertions.assertEquals( PathBasedMetadataObject.FILESET_PATH, pathBasedSecurableObject.type()); Assertions.assertEquals("/test", pathBasedSecurableObject.path()); - Assertions.assertEquals(2, pathBasedSecurableObject.privileges().size()); + }); + + SecurableObject tableObject = + SecurableObjects.parse( + "catalog1.schema1.table1", + MetadataObject.Type.TABLE, + Lists.newArrayList( + Privileges.SelectTable.allow(), Privileges.ModifyTable.allow())); + List<AuthorizationSecurableObject> authzTableObjects = + rangerAuthPlugin.translatePrivilege(tableObject); + Assertions.assertEquals(2, authzTableObjects.size()); + + authzTableObjects.forEach( + securableObject -> { + PathBasedSecurableObject pathBasedSecurableObject = + (PathBasedSecurableObject) securableObject; + Assertions.assertEquals( + PathBasedMetadataObject.TABLE_PATH, pathBasedSecurableObject.type()); + Assertions.assertEquals("/test", pathBasedSecurableObject.path()); }); }); } diff --git a/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerHiveIT.java b/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerHiveIT.java index 871d4c538b..8857d4e507 100644 --- a/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerHiveIT.java +++ b/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerHiveIT.java @@ -49,7 +49,7 @@ import org.apache.gravitino.authorization.Role; import org.apache.gravitino.authorization.RoleChange; import org.apache.gravitino.authorization.SecurableObject; import org.apache.gravitino.authorization.SecurableObjects; -import org.apache.gravitino.authorization.ranger.RangerAuthorizationPlugin; +import org.apache.gravitino.authorization.ranger.RangerAuthorizationHadoopSQLPlugin; import org.apache.gravitino.authorization.ranger.RangerClientExtension; import org.apache.gravitino.authorization.ranger.RangerHadoopSQLMetadataObject; import org.apache.gravitino.authorization.ranger.RangerHadoopSQLSecurableObject; @@ -81,7 +81,7 @@ import org.slf4j.LoggerFactory; public class RangerHiveIT { private static final Logger LOG = LoggerFactory.getLogger(RangerHiveIT.class); - private static RangerAuthorizationPlugin rangerAuthHivePlugin; + private static RangerAuthorizationHadoopSQLPlugin rangerAuthHivePlugin; private static RangerHelper rangerHelper; private final AuditInfo auditInfo = AuditInfo.builder().withCreator("test").withCreateTime(Instant.now()).build(); @@ -390,7 +390,6 @@ public class RangerHiveIT { AuthorizationSecurableObject rangerSecurableObject = rangerAuthHivePlugin.generateAuthorizationSecurableObject( ImmutableList.of(String.format("%s3", dbName), "tab1"), - "", RangerHadoopSQLMetadataObject.Type.TABLE, ImmutableSet.of( new RangerPrivileges.RangerHivePrivilegeImpl( diff --git a/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerITEnv.java b/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerITEnv.java index 0d00733437..87f579dc44 100644 --- a/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerITEnv.java +++ b/authorizations/authorization-ranger/src/test/java/org/apache/gravitino/authorization/ranger/integration/test/RangerITEnv.java @@ -84,8 +84,8 @@ public class RangerITEnv { public static final String SEARCH_FILTER_COLUMN = SearchFilter.RESOURCE_PREFIX + RESOURCE_COLUMN; // Search filter prefix file path constants public static final String SEARCH_FILTER_PATH = SearchFilter.RESOURCE_PREFIX + RESOURCE_PATH; - public static RangerAuthorizationPlugin rangerAuthHivePlugin; - public static RangerAuthorizationPlugin rangerAuthHDFSPlugin; + public static RangerAuthorizationHadoopSQLPlugin rangerAuthHivePlugin; + public static RangerAuthorizationHDFSPlugin rangerAuthHDFSPlugin; protected static RangerHelper rangerHelper; protected static RangerHelper rangerHDFSHelper; public static String RANGER_ADMIN_URL = null;