This is an automated email from the ASF dual-hosted git repository. jshao pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/gravitino.git
commit add62dd9bab4d4c0b3e45b1d23f2e93add06f12b Author: Eric Chang <[email protected]> AuthorDate: Mon Jul 14 10:42:50 2025 +0800 [#7545] feat(authz): Support fileset authorization (#7581) <!-- 1. Title: [#<issue>] <type>(<scope>): <subject> Examples: - "[#123] feat(operator): support xxx" - "[#233] fix: check null before access result in xxx" - "[MINOR] refactor: fix typo in variable name" - "[MINOR] docs: fix typo in README" - "[#255] test: fix flaky test NameOfTheTest" Reference: https://www.conventionalcommits.org/en/v1.0.0/ 2. If the PR is unfinished, please mark this PR as draft. --> ### What changes were proposed in this pull request? Support fileset auth with annotation. ### Why are the changes needed? To support fileset auth. Fix: #7545 ### Does this PR introduce _any_ user-facing change? Yes. ### How was this patch tested? FilesetAuthorizationIT --------- Co-authored-by: yangyang zhong <[email protected]> Co-authored-by: [email protected] <[email protected]> --- .../test/authorization/FilesetAuthorizationIT.java | 308 +++++++++++++++++++++ .../server/authorization/MetadataFilterHelper.java | 7 + .../AuthorizationExpressionConverter.java | 6 + .../web/filter/GravitinoInterceptionService.java | 14 +- .../server/web/rest/TestFilesetOperations.java | 3 +- .../TestFilesetAuthorizationExpression.java | 186 +++++++++++++ .../TestModelAuthorizationExpression.java | 8 +- 7 files changed, 523 insertions(+), 9 deletions(-) diff --git a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/FilesetAuthorizationIT.java b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/FilesetAuthorizationIT.java new file mode 100644 index 0000000000..f43e03b540 --- /dev/null +++ b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/FilesetAuthorizationIT.java @@ -0,0 +1,308 @@ +/* + * 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.client.integration.test.authorization; + +import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import org.apache.gravitino.Catalog; +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.MetadataObjects; +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.Namespace; +import org.apache.gravitino.authorization.Owner; +import org.apache.gravitino.authorization.Privileges; +import org.apache.gravitino.authorization.SecurableObject; +import org.apache.gravitino.authorization.SecurableObjects; +import org.apache.gravitino.client.GravitinoMetalake; +import org.apache.gravitino.file.Fileset; +import org.apache.gravitino.file.FilesetCatalog; +import org.apache.gravitino.file.FilesetChange; +import org.apache.gravitino.integration.test.container.ContainerSuite; +import org.apache.gravitino.integration.test.container.HiveContainer; +import org.apache.gravitino.integration.test.util.GravitinoITUtils; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +@Tag("gravitino-docker-test") +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class FilesetAuthorizationIT extends BaseRestApiAuthorizationIT { + + private static final String CATALOG = "catalog"; + private static final String SCHEMA = "schema"; + + private static final ContainerSuite containerSuite = ContainerSuite.getInstance(); + + private String role = "role"; + private String defaultBaseLocation; + + @BeforeAll + public void startIntegrationTest() throws Exception { + containerSuite.startHiveContainer(); + super.startIntegrationTest(); + client + .loadMetalake(METALAKE) + .createCatalog( + CATALOG, Catalog.Type.FILESET, "hadoop", "comment", ImmutableMap.of("k1", "k2")) + .asSchemas() + .createSchema(SCHEMA, "test", new HashMap<>()); + // try to load the schema as normal user, expect failure + assertThrows( + "Can not access metadata {" + CATALOG + "." + SCHEMA + "}.", + RuntimeException.class, + () -> { + normalUserClient + .loadMetalake(METALAKE) + .loadCatalog(CATALOG) + .asSchemas() + .loadSchema(SCHEMA); + }); + // grant tester privilege + List<SecurableObject> securableObjects = new ArrayList<>(); + GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE); + SecurableObject catalogObject = + SecurableObjects.ofCatalog(CATALOG, ImmutableList.of(Privileges.UseCatalog.allow())); + securableObjects.add(catalogObject); + gravitinoMetalake.createRole(role, new HashMap<>(), securableObjects); + gravitinoMetalake.grantRolesToUser(ImmutableList.of(role), NORMAL_USER); + // normal user can load the catalog but not the schema + Catalog catalogLoadByNormalUser = normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG); + assertEquals(CATALOG, catalogLoadByNormalUser.name()); + assertThrows( + "Can not access metadata {" + CATALOG + "." + SCHEMA + "}.", + RuntimeException.class, + () -> { + catalogLoadByNormalUser.asSchemas().loadSchema(SCHEMA); + }); + } + + @Test + @Order(1) + public void testCreateFileset() { + // admin user can create fileset + FilesetCatalog filesetCatalog = + client.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog(); + String filename1 = GravitinoITUtils.genRandomName("FilesetAuthorizationIT_fileset1"); + filesetCatalog.createFileset( + // NameIdentifier.of(SCHEMA, "fileset1"), + NameIdentifier.of(SCHEMA, "fileset1"), + "comment", + Fileset.Type.MANAGED, + storageLocation(filename1), + new HashMap<>()); + // normal use cannot create fileset + FilesetCatalog filesetCatalogNormalUser = + normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog(); + assertThrows( + "Can not access metadata {" + CATALOG + "." + SCHEMA + "}.", + RuntimeException.class, + () -> { + filesetCatalogNormalUser.createFileset( + // NameIdentifier.of(SCHEMA, "fileset2"), + NameIdentifier.of(SCHEMA, "fileset2"), + "comment", + Fileset.Type.MANAGED, + storageLocation(GravitinoITUtils.genRandomName("FilesetAuthorizationIT_fileset2")), + new HashMap<>()); + }); + // grant privileges + GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE); + gravitinoMetalake.grantPrivilegesToRole( + role, + MetadataObjects.of(CATALOG, SCHEMA, MetadataObject.Type.SCHEMA), + ImmutableList.of(Privileges.UseSchema.allow(), Privileges.CreateFileset.allow())); + // normal user can now create fileset + String filename2 = GravitinoITUtils.genRandomName("FilesetAuthorizationIT_fileset2"); + filesetCatalogNormalUser.createFileset( + NameIdentifier.of(SCHEMA, "fileset2"), + "comment", + Fileset.Type.MANAGED, + storageLocation(filename2), + new HashMap<>()); + String filename3 = GravitinoITUtils.genRandomName("FilesetAuthorizationIT_fileset3"); + filesetCatalogNormalUser.createFileset( + NameIdentifier.of(SCHEMA, "fileset3"), + "comment", + Fileset.Type.MANAGED, + storageLocation(filename3), + new HashMap<>()); + } + + @Test + @Order(2) + public void testListFileset() { + FilesetCatalog tableCatalog = + client.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog(); + NameIdentifier[] tablesList = tableCatalog.listFilesets(Namespace.of(SCHEMA)); + assertArrayEquals( + new NameIdentifier[] { + NameIdentifier.of(SCHEMA, "fileset1"), + NameIdentifier.of(SCHEMA, "fileset2"), + NameIdentifier.of(SCHEMA, "fileset3"), + }, + tablesList); + // normal user can only see filesets which they have privilege for + FilesetCatalog tableCatalogNormalUser = + normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog(); + NameIdentifier[] filesetsListNormalUser = + tableCatalogNormalUser.listFilesets(Namespace.of(SCHEMA)); + assertArrayEquals( + new NameIdentifier[] { + NameIdentifier.of(SCHEMA, "fileset2"), NameIdentifier.of(SCHEMA, "fileset3") + }, + filesetsListNormalUser); + } + + @Test + @Order(3) + public void testLoadFileset() { + FilesetCatalog filesetCatalogNormalUser = + normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog(); + // normal user can load fileset2 and fileset3, but not fileset1 + assertThrows( + String.format("Can not access metadata {%s.%s.%s}.", CATALOG, SCHEMA, "fileset1"), + RuntimeException.class, + () -> { + filesetCatalogNormalUser.loadFileset(NameIdentifier.of(CATALOG, SCHEMA, "fileset1")); + }); + Fileset fileset2 = filesetCatalogNormalUser.loadFileset(NameIdentifier.of(SCHEMA, "fileset2")); + assertEquals("fileset2", fileset2.name()); + Fileset fileset3 = filesetCatalogNormalUser.loadFileset(NameIdentifier.of(SCHEMA, "fileset3")); + assertEquals("fileset3", fileset3.name()); + + // grant normal user privilege to use fileset1 + GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE); + gravitinoMetalake.grantPrivilegesToRole( + role, + MetadataObjects.of( + ImmutableList.of(CATALOG, SCHEMA, "fileset1"), MetadataObject.Type.FILESET), + ImmutableList.of(Privileges.ReadFileset.allow())); + Fileset fileset1 = filesetCatalogNormalUser.loadFileset(NameIdentifier.of(SCHEMA, "fileset1")); + assertEquals("fileset1", fileset1.name()); + } + + @Test + @Order(4) + public void testAlterFileset() { + GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE); + FilesetCatalog filesetCatalogNormalUser = + normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog(); + + // normal user cannot alter fileset1 (no privilege) + assertThrows( + String.format("Can not access metadata {%s.%s.%s}.", CATALOG, SCHEMA, "fileset1"), + RuntimeException.class, + () -> { + filesetCatalogNormalUser.alterFileset( + NameIdentifier.of(SCHEMA, "fileset1"), FilesetChange.setProperty("key", "value")); + }); + // grant normal user write privilege on fileset1 + gravitinoMetalake.grantPrivilegesToRole( + role, + MetadataObjects.of( + ImmutableList.of(CATALOG, SCHEMA, "fileset1"), MetadataObject.Type.FILESET), + ImmutableList.of(Privileges.WriteFileset.allow())); + filesetCatalogNormalUser.alterFileset( + NameIdentifier.of(SCHEMA, "fileset1"), FilesetChange.setProperty("key", "value")); + } + + @Test + @Order(5) + public void testGetFileLocation() { + GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE); + FilesetCatalog filesetCatalogNormalUser = + normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog(); + + // normal user cannot alter fileset1 (no privilege) + assertThrows( + String.format("Can not access metadata {%s.%s.%s}.", CATALOG, SCHEMA, "fileset1"), + RuntimeException.class, + () -> { + filesetCatalogNormalUser.getFileLocation( + NameIdentifier.of(METALAKE, CATALOG, SCHEMA, "fileset1"), "/test"); + }); + // grant normal user owner privilege on fileset4 + gravitinoMetalake.setOwner( + MetadataObjects.of( + ImmutableList.of(CATALOG, SCHEMA, "fileset1"), MetadataObject.Type.FILESET), + NORMAL_USER, + Owner.Type.USER); + filesetCatalogNormalUser.getFileLocation(NameIdentifier.of(SCHEMA, "fileset1"), "/test"); + } + + @Test + @Order(6) + public void testDropFileset() { + GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE); + FilesetCatalog filesetCatalogNormalUser = + normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog(); + // reset owner + gravitinoMetalake.setOwner( + MetadataObjects.of( + ImmutableList.of(CATALOG, SCHEMA, "fileset1"), MetadataObject.Type.FILESET), + USER, + Owner.Type.USER); + // normal user cannot drop fileset1 + assertThrows( + String.format("Can not access metadata {%s.%s.%s}.", CATALOG, SCHEMA, "fileset1"), + RuntimeException.class, + () -> { + filesetCatalogNormalUser.dropFileset(NameIdentifier.of(SCHEMA, "fileset1")); + }); + // normal user can drop fileset2 and fileset3 (they created them) + filesetCatalogNormalUser.dropFileset(NameIdentifier.of(SCHEMA, "fileset2")); + filesetCatalogNormalUser.dropFileset(NameIdentifier.of(SCHEMA, "fileset3")); + + // owner can drop fileset1 + FilesetCatalog filesetCatalog = + client.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog(); + filesetCatalog.dropFileset(NameIdentifier.of(SCHEMA, "fileset1")); + // check filesets are dropped + NameIdentifier[] filesetsList = filesetCatalog.listFilesets(Namespace.of(SCHEMA)); + assertArrayEquals(new NameIdentifier[] {}, filesetsList); + NameIdentifier[] filesetsListNormalUser = + filesetCatalogNormalUser.listFilesets(Namespace.of(SCHEMA)); + assertArrayEquals(new NameIdentifier[] {}, filesetsListNormalUser); + } + + private String defaultBaseLocation() { + if (defaultBaseLocation == null) { + defaultBaseLocation = + String.format( + "hdfs://%s:%d/user/hive/%s", + containerSuite.getHiveContainer().getContainerIpAddress(), + HiveContainer.HDFS_DEFAULTFS_PORT, + SCHEMA.toLowerCase()); + } + return defaultBaseLocation; + } + + private String storageLocation(String filesetName) { + return defaultBaseLocation() + "/" + filesetName; + } +} 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 2655b98a05..066c550c40 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 @@ -144,6 +144,13 @@ public class MetadataFilterHelper { nameIdentifierMap.put( Entity.EntityType.CATALOG, NameIdentifierUtil.getCatalogIdentifier(nameIdentifier)); break; + case FILESET: + nameIdentifierMap.put(Entity.EntityType.FILESET, nameIdentifier); + nameIdentifierMap.put( + Entity.EntityType.SCHEMA, NameIdentifierUtil.getSchemaIdentifier(nameIdentifier)); + nameIdentifierMap.put( + Entity.EntityType.CATALOG, NameIdentifierUtil.getCatalogIdentifier(nameIdentifier)); + break; default: break; } diff --git a/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionConverter.java b/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionConverter.java index 0ec8ef18a1..694dafbf6d 100644 --- a/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionConverter.java +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionConverter.java @@ -163,6 +163,12 @@ public class AuthorizationExpressionConverter { expression = expression.replaceAll( "ANY_CONSUME_TOPIC", "(ANY(CONSUME_TOPIC, METALAKE, CATALOG, SCHEMA, TOPIC))"); + expression = + expression.replaceAll( + "ANY_READ_FILESET", "(ANY(READ_FILESET, METALAKE, CATALOG, SCHEMA, FILESET))"); + expression = + expression.replaceAll( + "ANY_WRITE_FILESET", "(ANY(WRITE_FILESET, METALAKE, CATALOG, SCHEMA, FILESET))"); return expression; } } diff --git a/server/src/main/java/org/apache/gravitino/server/web/filter/GravitinoInterceptionService.java b/server/src/main/java/org/apache/gravitino/server/web/filter/GravitinoInterceptionService.java index d39faf0ad8..7d26113aaf 100644 --- a/server/src/main/java/org/apache/gravitino/server/web/filter/GravitinoInterceptionService.java +++ b/server/src/main/java/org/apache/gravitino/server/web/filter/GravitinoInterceptionService.java @@ -40,6 +40,7 @@ import org.apache.gravitino.server.authorization.annotations.AuthorizationMetada import org.apache.gravitino.server.authorization.expression.AuthorizationExpressionEvaluator; import org.apache.gravitino.server.web.Utils; import org.apache.gravitino.server.web.rest.CatalogOperations; +import org.apache.gravitino.server.web.rest.FilesetOperations; import org.apache.gravitino.server.web.rest.ModelOperations; import org.apache.gravitino.server.web.rest.SchemaOperations; import org.apache.gravitino.server.web.rest.TableOperations; @@ -64,7 +65,8 @@ public class GravitinoInterceptionService implements InterceptionService { SchemaOperations.class.getName(), TableOperations.class.getName(), ModelOperations.class.getName(), - TopicOperations.class.getName())); + TopicOperations.class.getName(), + FilesetOperations.class.getName())); } @Override @@ -140,6 +142,7 @@ public class GravitinoInterceptionService implements InterceptionService { String schema = metadatas.get(Entity.EntityType.SCHEMA); String table = metadatas.get(Entity.EntityType.TABLE); String topic = metadatas.get(Entity.EntityType.TOPIC); + String fileset = metadatas.get(Entity.EntityType.FILESET); metadatas.forEach( (type, metadata) -> { switch (type) { @@ -162,9 +165,10 @@ public class GravitinoInterceptionService implements InterceptionService { Entity.EntityType.TOPIC, NameIdentifierUtil.ofTopic(metalake, catalog, schema, topic)); break; - case METALAKE: + case FILESET: nameIdentifierMap.put( - Entity.EntityType.METALAKE, NameIdentifierUtil.ofMetalake(metalake)); + Entity.EntityType.FILESET, + NameIdentifierUtil.ofFileset(metalake, catalog, schema, fileset)); break; case MODEL: String model = metadatas.get(Entity.EntityType.MODEL); @@ -172,6 +176,10 @@ public class GravitinoInterceptionService implements InterceptionService { Entity.EntityType.MODEL, NameIdentifierUtil.ofModel(metadata, catalog, schema, model)); break; + case METALAKE: + nameIdentifierMap.put( + Entity.EntityType.METALAKE, NameIdentifierUtil.ofMetalake(metalake)); + break; default: break; } diff --git a/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java b/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java index f8248bc1d8..56665ae914 100644 --- a/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java +++ b/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java @@ -69,7 +69,6 @@ import org.apache.gravitino.lock.LockManager; import org.apache.gravitino.rest.RESTUtils; import org.glassfish.jersey.internal.inject.AbstractBinder; import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.test.JerseyTest; import org.glassfish.jersey.test.TestProperties; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -77,7 +76,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.mockito.stubbing.Answer; -public class TestFilesetOperations extends JerseyTest { +public class TestFilesetOperations extends BaseOperationsTest { private static class MockServletRequestFactory extends ServletRequestFactoryBase { @Override public HttpServletRequest get() { diff --git a/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestFilesetAuthorizationExpression.java b/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestFilesetAuthorizationExpression.java new file mode 100644 index 0000000000..74f8fd45e5 --- /dev/null +++ b/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestFilesetAuthorizationExpression.java @@ -0,0 +1,186 @@ +/* + * 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.server.web.rest.authorization; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.google.common.collect.ImmutableSet; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import ognl.OgnlException; +import org.apache.gravitino.dto.requests.FilesetCreateRequest; +import org.apache.gravitino.dto.requests.FilesetUpdatesRequest; +import org.apache.gravitino.server.authorization.annotations.AuthorizationExpression; +import org.apache.gravitino.server.web.rest.FilesetOperations; +import org.junit.jupiter.api.Test; + +public class TestFilesetAuthorizationExpression { + + @Test + public void testCreateFileset() throws NoSuchMethodException, OgnlException { + Method method = + FilesetOperations.class.getMethod( + "createFileset", String.class, String.class, String.class, FilesetCreateRequest.class); + AuthorizationExpression authorizationExpressionAnnotation = + method.getAnnotation(AuthorizationExpression.class); + String expression = authorizationExpressionAnnotation.expression(); + MockAuthorizationExpressionEvaluator mockEvaluator = + new MockAuthorizationExpressionEvaluator(expression); + assertFalse(mockEvaluator.getResult(ImmutableSet.of())); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_CATALOG"))); + assertTrue(mockEvaluator.getResult(ImmutableSet.of("METALAKE::OWNER"))); + assertTrue(mockEvaluator.getResult(ImmutableSet.of("CATALOG::OWNER"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER"))); + assertTrue(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER", "CATALOG::USE_CATALOG"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_METALAKE"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::CREATE_CATALOG"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::CREATE_FILESET"))); + assertFalse( + mockEvaluator.getResult(ImmutableSet.of("SCHEMA::CREATE_FILESET", "CATALOG::USE_CATALOG"))); + assertTrue( + mockEvaluator.getResult( + ImmutableSet.of( + "SCHEMA::CREATE_FILESET", "SCHEMA::USE_SCHEMA", "CATALOG::USE_CATALOG"))); + } + + @Test + public void testLoadFileset() throws OgnlException, NoSuchFieldException, IllegalAccessException { + Field loadFilesetAuthorizationExpressionField = + FilesetOperations.class.getDeclaredField("loadFilesetAuthorizationExpression"); + loadFilesetAuthorizationExpressionField.setAccessible(true); + String loadFilesetAuthorizationExpression = + (String) loadFilesetAuthorizationExpressionField.get(null); + MockAuthorizationExpressionEvaluator mockEvaluator = + new MockAuthorizationExpressionEvaluator(loadFilesetAuthorizationExpression); + assertFalse(mockEvaluator.getResult(ImmutableSet.of())); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_CATALOG"))); + assertTrue(mockEvaluator.getResult(ImmutableSet.of("METALAKE::OWNER"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_METALAKE"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::CREATE_CATALOG"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::CREATE_FILESET"))); + assertFalse( + mockEvaluator.getResult( + ImmutableSet.of("SCHEMA::CREATE_FILESET", "CATALOG::CREATE_CATALOG"))); + + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::WRITE_FILESET"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::WRITE_FILESET"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET"))); + assertFalse( + mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET", "CATALOG::USE_CATALOG"))); + assertTrue( + mockEvaluator.getResult( + ImmutableSet.of( + "SCHEMA::WRITE_FILESET", "SCHEMA::USE_SCHEMA", "CATALOG::USE_CATALOG"))); + + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::READ_FILESET"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::READ_FILESET"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::READ_FILESET"))); + assertFalse( + mockEvaluator.getResult(ImmutableSet.of("SCHEMA::READ_FILESET", "CATALOG::USE_CATALOG"))); + assertTrue( + mockEvaluator.getResult( + ImmutableSet.of("SCHEMA::READ_FILESET", "SCHEMA::USE_SCHEMA", "CATALOG::USE_CATALOG"))); + + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER"))); + assertTrue(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER", "CATALOG::USE_CATALOG"))); + assertTrue( + mockEvaluator.getResult( + ImmutableSet.of("SCHEMA::OWNER", "SCHEMA::USE_SCHEMA", "CATALOG::USE_CATALOG"))); + } + + @Test + public void testAlterFileset() throws NoSuchMethodException, OgnlException { + Method method = + FilesetOperations.class.getMethod( + "alterFileset", + String.class, + String.class, + String.class, + String.class, + FilesetUpdatesRequest.class); + AuthorizationExpression authorizationExpressionAnnotation = + method.getAnnotation(AuthorizationExpression.class); + String expression = authorizationExpressionAnnotation.expression(); + MockAuthorizationExpressionEvaluator mockEvaluator = + new MockAuthorizationExpressionEvaluator(expression); + assertFalse(mockEvaluator.getResult(ImmutableSet.of())); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_CATALOG"))); + assertTrue(mockEvaluator.getResult(ImmutableSet.of("METALAKE::OWNER"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_METALAKE"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::CREATE_CATALOG"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::CREATE_FILESET"))); + assertFalse( + mockEvaluator.getResult( + ImmutableSet.of("SCHEMA::CREATE_FILESET", "CATALOG::CREATE_CATALOG"))); + + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::WRITE_FILESET"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::WRITE_FILESET"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET"))); + assertFalse( + mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET", "CATALOG::USE_CATALOG"))); + assertTrue( + mockEvaluator.getResult( + ImmutableSet.of( + "SCHEMA::WRITE_FILESET", "SCHEMA::USE_SCHEMA", "CATALOG::USE_CATALOG"))); + + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER"))); + assertTrue(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER", "CATALOG::USE_CATALOG"))); + assertTrue( + mockEvaluator.getResult( + ImmutableSet.of("SCHEMA::OWNER", "SCHEMA::USE_SCHEMA", "CATALOG::USE_CATALOG"))); + } + + @Test + public void testDropFileset() throws NoSuchMethodException, OgnlException { + Method method = + FilesetOperations.class.getMethod( + "dropFileset", String.class, String.class, String.class, String.class); + AuthorizationExpression authorizationExpressionAnnotation = + method.getAnnotation(AuthorizationExpression.class); + String expression = authorizationExpressionAnnotation.expression(); + MockAuthorizationExpressionEvaluator mockEvaluator = + new MockAuthorizationExpressionEvaluator(expression); + assertFalse(mockEvaluator.getResult(ImmutableSet.of())); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_CATALOG"))); + assertTrue(mockEvaluator.getResult(ImmutableSet.of("METALAKE::OWNER"))); + + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_METALAKE"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::CREATE_CATALOG"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::CREATE_FILESET"))); + assertFalse( + mockEvaluator.getResult( + ImmutableSet.of("SCHEMA::CREATE_FILESET", "CATALOG::CREATE_CATALOG"))); + + assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::WRITE_FILESET"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::WRITE_FILESET"))); + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET"))); + assertFalse( + mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET", "CATALOG::USE_CATALOG"))); + assertFalse( + mockEvaluator.getResult( + ImmutableSet.of( + "SCHEMA::WRITE_FILESET", "SCHEMA::USE_SCHEMA", "CATALOG::USE_CATALOG"))); + + assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER"))); + assertTrue(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER", "CATALOG::USE_CATALOG"))); + assertTrue( + mockEvaluator.getResult( + ImmutableSet.of("SCHEMA::OWNER", "SCHEMA::USE_SCHEMA", "CATALOG::USE_CATALOG"))); + } +} diff --git a/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestModelAuthorizationExpression.java b/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestModelAuthorizationExpression.java index b2a97ffe7e..53b1e91536 100644 --- a/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestModelAuthorizationExpression.java +++ b/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestModelAuthorizationExpression.java @@ -68,12 +68,12 @@ public class TestModelAuthorizationExpression { @Test public void testLoadModel() throws OgnlException, NoSuchFieldException, IllegalAccessException { - Field loadTableAuthorizationExpressionField = + Field loadModelAuthorizationExpressionField = ModelOperations.class.getDeclaredField("loadModelAuthorizationExpression"); - loadTableAuthorizationExpressionField.setAccessible(true); - String loadTableAuthExpression = (String) loadTableAuthorizationExpressionField.get(null); + loadModelAuthorizationExpressionField.setAccessible(true); + String loadModelAuthExpression = (String) loadModelAuthorizationExpressionField.get(null); MockAuthorizationExpressionEvaluator mockEvaluator = - new MockAuthorizationExpressionEvaluator(loadTableAuthExpression); + new MockAuthorizationExpressionEvaluator(loadModelAuthExpression); assertFalse(mockEvaluator.getResult(ImmutableSet.of())); assertTrue(mockEvaluator.getResult(ImmutableSet.of("METALAKE::OWNER"))); assertTrue(mockEvaluator.getResult(ImmutableSet.of("CATALOG::OWNER")));
