diff --git a/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataFilterHelper.java b/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataFilterHelper.java index e435bac4a1c..874424feb27 100644 --- a/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataFilterHelper.java +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataFilterHelper.java @@ -156,6 +156,35 @@ public static E[] filterByExpression( Entity.EntityType entityType, E[] entities, Function toNameIdentifier) { + GravitinoAuthorizer authorizer = + GravitinoAuthorizerProvider.getInstance().getGravitinoAuthorizer(); + Principal currentPrincipal = PrincipalUtils.getCurrentPrincipal(); + return filterByExpression( + metalake, expression, entityType, entities, toNameIdentifier, currentPrincipal, authorizer); + } + + /** + * Call {@link AuthorizationExpressionEvaluator} and use specified Principal and + * GravitinoAuthorizer to filter the metadata list + * + * @param metalake metalake name + * @param expression authorization expression + * @param entityType entity type + * @param entities metadata entities + * @param toNameIdentifier function to convert entity to NameIdentifier + * @param currentPrincipal current principal + * @param authorizer authorizer to filter metadata + * @return Filtered Metadata Entity + * @param Entity class + */ + public static E[] filterByExpression( + String metalake, + String expression, + Entity.EntityType entityType, + E[] entities, + Function toNameIdentifier, + Principal currentPrincipal, + GravitinoAuthorizer authorizer) { if (!enableAuthorization()) { return entities; } @@ -163,7 +192,6 @@ public static E[] filterByExpression( AuthorizationRequestContext authorizationRequestContext = new AuthorizationRequestContext(); List> futures = new ArrayList<>(); for (E entity : entities) { - Principal currentPrincipal = PrincipalUtils.getCurrentPrincipal(); futures.add( CompletableFuture.supplyAsync( () -> { @@ -172,7 +200,7 @@ public static E[] filterByExpression( currentPrincipal, () -> { AuthorizationExpressionEvaluator authorizationExpressionEvaluator = - new AuthorizationExpressionEvaluator(expression); + new AuthorizationExpressionEvaluator(expression, authorizer); NameIdentifier nameIdentifier = toNameIdentifier.apply(entity); Map nameIdentifierMap = spiltMetadataNames(metalake, entityType, nameIdentifier); diff --git a/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionEvaluator.java b/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionEvaluator.java index 78ddf58d44d..02c455e887b 100644 --- a/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionEvaluator.java +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionEvaluator.java @@ -39,6 +39,7 @@ public class AuthorizationExpressionEvaluator { private final String ognlAuthorizationExpression; + private final GravitinoAuthorizer authorizer; /** * Use {@link AuthorizationExpressionConverter} to convert the authorization expression into an @@ -47,8 +48,19 @@ public class AuthorizationExpressionEvaluator { * @param expression authorization expression */ public AuthorizationExpressionEvaluator(String expression) { + this(expression, GravitinoAuthorizerProvider.getInstance().getGravitinoAuthorizer()); + } + + /** + * Constructor of AuthorizationExpressionEvaluator + * + * @param expression authorization expression + * @param authorizer GravitinoAuthorizer instance + */ + public AuthorizationExpressionEvaluator(String expression, GravitinoAuthorizer authorizer) { this.ognlAuthorizationExpression = AuthorizationExpressionConverter.convertToOgnlExpression(expression); + this.authorizer = authorizer; } /** @@ -61,7 +73,24 @@ public AuthorizationExpressionEvaluator(String expression) { public boolean evaluate( Map metadataNames, AuthorizationRequestContext requestContext) { - return evaluate(metadataNames, new HashMap<>(), requestContext); + Principal currentPrincipal = PrincipalUtils.getCurrentPrincipal(); + return evaluate(metadataNames, new HashMap<>(), requestContext, currentPrincipal); + } + + /** + * Use OGNL expressions to invoke GravitinoAuthorizer for authorizing multiple types of metadata + * IDs. + * + * @param metadataNames key-metadata type, value-metadata NameIdentifier + * @param requestContext authorization request context + * @param principal current principal + * @return authorization result + */ + public boolean evaluate( + Map metadataNames, + AuthorizationRequestContext requestContext, + Principal principal) { + return evaluate(metadataNames, new HashMap<>(), requestContext, principal); } /** @@ -77,11 +106,27 @@ public boolean evaluate( Map pathParams, AuthorizationRequestContext requestContext) { Principal currentPrincipal = PrincipalUtils.getCurrentPrincipal(); - GravitinoAuthorizer gravitinoAuthorizer = - GravitinoAuthorizerProvider.getInstance().getGravitinoAuthorizer(); + return evaluate(metadataNames, pathParams, requestContext, currentPrincipal); + } + + /** + * Use OGNL expressions to invoke GravitinoAuthorizer for authorizing multiple types of metadata + * IDs. + * + * @param metadataNames key-metadata type, value-metadata NameIdentifier + * @param pathParams params from request path + * @param requestContext authorization request context + * @param currentPrincipal current principal + * @return authorization result + */ + private boolean evaluate( + Map metadataNames, + Map pathParams, + AuthorizationRequestContext requestContext, + Principal currentPrincipal) { OgnlContext ognlContext = Ognl.createDefaultContext(null); ognlContext.put("principal", currentPrincipal); - ognlContext.put("authorizer", gravitinoAuthorizer); + ognlContext.put("authorizer", authorizer); ognlContext.put("authorizationContext", requestContext); ognlContext.putAll(pathParams); metadataNames.forEach( diff --git a/server-common/src/test/java/org/apache/gravitino/server/authorization/expression/TestAuthorizationExpressionEvaluator.java b/server-common/src/test/java/org/apache/gravitino/server/authorization/expression/TestAuthorizationExpressionEvaluator.java index 59def1e5365..ed3f291dc87 100644 --- a/server-common/src/test/java/org/apache/gravitino/server/authorization/expression/TestAuthorizationExpressionEvaluator.java +++ b/server-common/src/test/java/org/apache/gravitino/server/authorization/expression/TestAuthorizationExpressionEvaluator.java @@ -42,8 +42,6 @@ public class TestAuthorizationExpressionEvaluator { public void testEvaluator() { String expression = "CATALOG::USE_CATALOG && SCHEMA::USE_SCHEMA && (TABLE::SELECT_TABLE || TABLE::MODIFY_TABLE)"; - AuthorizationExpressionEvaluator authorizationExpressionEvaluator = - new AuthorizationExpressionEvaluator(expression); try (MockedStatic principalUtilsMocked = mockStatic(PrincipalUtils.class); MockedStatic mockStatic = mockStatic(GravitinoAuthorizerProvider.class)) { @@ -53,6 +51,9 @@ public void testEvaluator() { GravitinoAuthorizerProvider mockedProvider = mock(GravitinoAuthorizerProvider.class); mockStatic.when(GravitinoAuthorizerProvider::getInstance).thenReturn(mockedProvider); when(mockedProvider.getGravitinoAuthorizer()).thenReturn(new MockGravitinoAuthorizer()); + AuthorizationExpressionEvaluator authorizationExpressionEvaluator = + new AuthorizationExpressionEvaluator(expression); + Map metadataNames = new HashMap<>(); metadataNames.put(Entity.EntityType.METALAKE, NameIdentifierUtil.ofMetalake("testMetalake")); metadataNames.put( @@ -79,17 +80,19 @@ public void testEvaluator() { @Test public void testEvaluatorWithOwner() { String expression = "METALAKE::OWNER || CATALOG::CREATE_CATALOG"; - AuthorizationExpressionEvaluator authorizationExpressionEvaluator = - new AuthorizationExpressionEvaluator(expression); try (MockedStatic principalUtilsMocked = mockStatic(PrincipalUtils.class); MockedStatic mockStatic = mockStatic(GravitinoAuthorizerProvider.class)) { - principalUtilsMocked - .when(PrincipalUtils::getCurrentPrincipal) - .thenReturn(new UserPrincipal("tester")); GravitinoAuthorizerProvider mockedProvider = mock(GravitinoAuthorizerProvider.class); mockStatic.when(GravitinoAuthorizerProvider::getInstance).thenReturn(mockedProvider); when(mockedProvider.getGravitinoAuthorizer()).thenReturn(new MockGravitinoAuthorizer()); + + AuthorizationExpressionEvaluator authorizationExpressionEvaluator = + new AuthorizationExpressionEvaluator(expression); + principalUtilsMocked + .when(PrincipalUtils::getCurrentPrincipal) + .thenReturn(new UserPrincipal("tester")); + Map metadataNames = new HashMap<>(); metadataNames.put( Entity.EntityType.METALAKE, NameIdentifierUtil.ofMetalake("metalakeWithOutOwner"));