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 8e6996d51530db365faabb84fcce797168e2210e Author: yangyang zhong <[email protected]> AuthorDate: Thu Apr 24 10:58:05 2025 +0800 [#6841] feat: Introduce an authorization framework. (#6842) ### What changes were proposed in this pull request? It only introduces the authorization framework without including any implementation. ### Why are the changes needed? Fix: #6841 ### Does this PR introduce _any_ user-facing change? none ### How was this patch tested? none --- .../server/authorization/GravitinoAuthorizer.java | 48 +++++++++++++++ .../authorization/GravitinoAuthorizerProvider.java | 58 +++++++++++++++++ .../server/authorization/MetadataFilterHelper.java | 61 ++++++++++++++++++ .../annotations/AuthorizeMetadata.java | 28 +++++++++ .../annotations/ExpressionsAuthorizeApi.java | 31 ++++++++++ .../annotations/MetadataAuthorizeApi.java | 24 ++++++++ .../expression/AuthorizationConverter.java | 41 ++++++++++++ .../AuthorizationExpressionEvaluator.java | 45 ++++++++++++++ .../web/filter/GravitinoInterceptionService.java | 72 ++++++++++++++++++++++ 9 files changed, 408 insertions(+) diff --git a/server-common/src/main/java/org/apache/gravitino/server/authorization/GravitinoAuthorizer.java b/server-common/src/main/java/org/apache/gravitino/server/authorization/GravitinoAuthorizer.java new file mode 100644 index 0000000000..fdadac206a --- /dev/null +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/GravitinoAuthorizer.java @@ -0,0 +1,48 @@ +/* + * 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.authorization; + +import java.io.Closeable; +import java.security.Principal; +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.authorization.Privilege; + +/** Used for metadata authorization. */ +public interface GravitinoAuthorizer extends Closeable { + + /** + * After instantiating the GravitinoAuthorizer, execute the initialize method to perform a series + * of initialization operations, such as loading privilege policies and so on. + */ + void initialize(); + + /** + * Perform authorization and return the authorization result. + * + * @param principal the user principal + * @param metalake the metalake + * @param metadataObject the metadataObject. + * @param privilege for example, CREATE_CATALOG, CREATE_TABLE, etc. + * @return authorization result. + */ + boolean authorize( + Principal principal, + String metalake, + MetadataObject metadataObject, + Privilege.Name privilege); +} diff --git a/server-common/src/main/java/org/apache/gravitino/server/authorization/GravitinoAuthorizerProvider.java b/server-common/src/main/java/org/apache/gravitino/server/authorization/GravitinoAuthorizerProvider.java new file mode 100644 index 0000000000..ad48590feb --- /dev/null +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/GravitinoAuthorizerProvider.java @@ -0,0 +1,58 @@ +/* + * 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.authorization; + +import org.apache.gravitino.server.ServerConfig; + +/** + * Used to initialize and store {@link GravitinoAuthorizer}. When Gravitino Server starts up, it + * initializes GravitinoAuthorizer by reading the ServerConfig through the init method and stores it + * in the GravitinoAuthorizerProvider. The GravitinoAuthorizer instance can then be retrieved using + * the getGravitinoAuthorizer method. + */ +public class GravitinoAuthorizerProvider { + + private static final GravitinoAuthorizerProvider INSTANCE = new GravitinoAuthorizerProvider(); + + private GravitinoAuthorizerProvider() {} + + private GravitinoAuthorizer gravitinoAuthorizer; + + /** + * Instantiate the {@link GravitinoAuthorizer}, and then execute the initialize method in the + * GravitinoAuthorizer. + * + * @param serverConfig Gravitino server config + */ + public void initialize(ServerConfig serverConfig) { + // TODO + } + + public static GravitinoAuthorizerProvider getInstance() { + return INSTANCE; + } + + /** + * Retrieve GravitinoAuthorizer instance. + * + * @return GravitinoAuthorizer instance + */ + public GravitinoAuthorizer getGravitinoAuthorizer() { + return gravitinoAuthorizer; + } +} 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 new file mode 100644 index 0000000000..b88ae3d727 --- /dev/null +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataFilterHelper.java @@ -0,0 +1,61 @@ +/* + * 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.authorization; + +import com.google.errorprone.annotations.DoNotCall; +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.server.authorization.expression.AuthorizationExpressionEvaluator; + +/** + * MetadataFilterHelper performs permission checks on the list data returned by the REST API based + * on expressions or metadata types, and calls {@link GravitinoAuthorizer} for authorization, + * returning only the metadata that the user has permission to access. + */ +public class MetadataFilterHelper { + + private MetadataFilterHelper() {} + + /** + * Call {@link GravitinoAuthorizer} to filter the metadata list + * + * @param metadataType for example, CATALOG, SCHEMA,TABLE, etc. + * @param privilege for example, CREATE_CATALOG, CREATE_TABLE, etc. + * @param metadataList metadata list. + * @return metadata List that the user has permission to access. + */ + @DoNotCall + public static NameIdentifier[] filter( + MetadataObject.Type metadataType, String privilege, NameIdentifier[] metadataList) { + throw new UnsupportedOperationException(); + } + + /** + * Call {@link AuthorizationExpressionEvaluator} to filter the metadata list + * + * @param expression authorization expression + * @param metadataType for example, CATALOG, SCHEMA,TABLE, etc. + * @param nameIdentifiers metaData list. + * @return metadata List that the user has permission to access. + */ + @DoNotCall + public static NameIdentifier[] filterByExpression( + String expression, MetadataObject.Type metadataType, NameIdentifier[] nameIdentifiers) { + throw new UnsupportedOperationException(); + } +} diff --git a/server-common/src/main/java/org/apache/gravitino/server/authorization/annotations/AuthorizeMetadata.java b/server-common/src/main/java/org/apache/gravitino/server/authorization/annotations/AuthorizeMetadata.java new file mode 100644 index 0000000000..9fa04357ba --- /dev/null +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/annotations/AuthorizeMetadata.java @@ -0,0 +1,28 @@ +/* + * 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.authorization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** This annotation identify which parameters in the request are to be used for authorization. */ +@Target({ElementType.PARAMETER, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface AuthorizeMetadata {} diff --git a/server-common/src/main/java/org/apache/gravitino/server/authorization/annotations/ExpressionsAuthorizeApi.java b/server-common/src/main/java/org/apache/gravitino/server/authorization/annotations/ExpressionsAuthorizeApi.java new file mode 100644 index 0000000000..b45cf7707a --- /dev/null +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/annotations/ExpressionsAuthorizeApi.java @@ -0,0 +1,31 @@ +/* + * 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.authorization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation is used to implement unified authentication in AOP. Use Expressions to define the + * required privileges for an API. + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExpressionsAuthorizeApi {} diff --git a/server-common/src/main/java/org/apache/gravitino/server/authorization/annotations/MetadataAuthorizeApi.java b/server-common/src/main/java/org/apache/gravitino/server/authorization/annotations/MetadataAuthorizeApi.java new file mode 100644 index 0000000000..2fae8439fb --- /dev/null +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/annotations/MetadataAuthorizeApi.java @@ -0,0 +1,24 @@ +/* + * 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.authorization.annotations; + +/** + * Defines the annotation for authorizing access to an API. Use the resourceType and privileges + * fields to define the required privileges and resource type for the API. + */ +public @interface MetadataAuthorizeApi {} diff --git a/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationConverter.java b/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationConverter.java new file mode 100644 index 0000000000..f9a8c7bcac --- /dev/null +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationConverter.java @@ -0,0 +1,41 @@ +/* + * 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.authorization.expression; + +import com.google.errorprone.annotations.DoNotCall; +import org.apache.gravitino.server.authorization.MetadataFilterHelper; + +public class AuthorizationConverter { + + private AuthorizationConverter() {} + + /** + * Convert the authorization expression to OGNL expression. <a + * href="https://github.com/orphan-oss/ognl">OGNL</a> stands for Object-Graph Navigation Language; + * It is an expression language for getting and setting properties of Java objects, plus other + * extras such as list projection and selection and lambda expressions. You use the same + * expression for both getting and setting the value of a property. + * + * @param authorizationExpression authorization expression from {@link MetadataFilterHelper} + * @return an OGNL expression used to call GravitinoAuthorizer + */ + @DoNotCall + public static String convertToOgnlExpression(String authorizationExpression) { + throw new UnsupportedOperationException(); + } +} 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 new file mode 100644 index 0000000000..f124ddaa47 --- /dev/null +++ b/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionEvaluator.java @@ -0,0 +1,45 @@ +/* + * 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.authorization.expression; + +import java.util.Map; +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.server.authorization.GravitinoAuthorizer; + +/** Evaluate the runtime result of the AuthorizationExpression.. */ +public class AuthorizationExpressionEvaluator { + + /** + * Use {@link AuthorizationConverter} to convert the authorization expression into an OGNL + * expression, and then call {@link GravitinoAuthorizer} to perform permission verification. + * + * @param expression authorization expression + */ + public AuthorizationExpressionEvaluator(String expression) {} + + /** + * Use OGNL expressions to invoke GravitinoAuthorizer for authorizing multiple types of metadata + * IDs. + * + * @param metadataIds key-metadata type, value-metadata id + * @return authorization result + */ + public boolean evaluate(Map<MetadataObject.Type, Long> metadataIds) { + throw new UnsupportedOperationException(); + } +} 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 new file mode 100644 index 0000000000..823207af5a --- /dev/null +++ b/server/src/main/java/org/apache/gravitino/server/web/filter/GravitinoInterceptionService.java @@ -0,0 +1,72 @@ +/* + * 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.filter; + +import com.google.common.collect.ImmutableList; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import org.aopalliance.intercept.ConstructorInterceptor; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.glassfish.hk2.api.Filter; +import org.glassfish.hk2.api.InterceptionService; + +/** + * GravitinoInterceptionService defines a method interceptor for REST interfaces to create dynamic + * proxies. It implements metadata authorization when invoking REST API methods. It needs to be + * registered in the hk2 bean container when the gravitino server starts. + */ +public class GravitinoInterceptionService implements InterceptionService { + + @Override + public Filter getDescriptorFilter() { + throw new UnsupportedOperationException(); + } + + @Override + public List<MethodInterceptor> getMethodInterceptors(Method method) { + return ImmutableList.of(new MetadataAuthorizationMethodInterceptor()); + } + + @Override + public List<ConstructorInterceptor> getConstructorInterceptors(Constructor<?> constructor) { + return Collections.emptyList(); + } + + /** + * Through dynamic proxy, obtain the annotations on the method and parameter list to perform + * metadata authorization. + */ + private static class MetadataAuthorizationMethodInterceptor implements MethodInterceptor { + + /** + * Determine whether authorization is required and the rules via the authorization annotation , + * and obtain the metadata ID that requires authorization via the authorization annotation. + * + * @param methodInvocation methodInvocation with the Method object + * @return the return result of the original method. + * @throws Throwable throw an exception when authorization fails. + */ + @Override + public Object invoke(MethodInvocation methodInvocation) throws Throwable { + throw new UnsupportedOperationException(); + } + } +}
