This is an automated email from the ASF dual-hosted git repository.

jshao pushed a commit to branch branch-metadata-authz
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/branch-metadata-authz by this 
push:
     new 2de1da57c4 [#6841] feat: Introduce an authorization framework. (#6842)
2de1da57c4 is described below

commit 2de1da57c4569d66dae1c9a78f6a514e46dc3acc
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 ++++++++++++++
 .../apache/gravitino/server/GravitinoServer.java   |  3 +
 .../web/filter/GravitinoInterceptionService.java   | 72 ++++++++++++++++++++++
 10 files changed, 411 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/GravitinoServer.java 
b/server/src/main/java/org/apache/gravitino/server/GravitinoServer.java
index 0c730439b1..ab10bcf5dc 100644
--- a/server/src/main/java/org/apache/gravitino/server/GravitinoServer.java
+++ b/server/src/main/java/org/apache/gravitino/server/GravitinoServer.java
@@ -37,6 +37,7 @@ import org.apache.gravitino.metalake.MetalakeDispatcher;
 import org.apache.gravitino.metrics.MetricsSystem;
 import org.apache.gravitino.metrics.source.MetricsSource;
 import org.apache.gravitino.server.authentication.ServerAuthenticator;
+import org.apache.gravitino.server.authorization.GravitinoAuthorizerProvider;
 import org.apache.gravitino.server.web.ConfigServlet;
 import org.apache.gravitino.server.web.HttpServerMetricsSource;
 import org.apache.gravitino.server.web.JettyServer;
@@ -90,6 +91,8 @@ public class GravitinoServer extends ResourceConfig {
 
     ServerAuthenticator.getInstance().initialize(serverConfig);
 
+    GravitinoAuthorizerProvider.getInstance().initialize(serverConfig);
+
     // initialize Jersey REST API resources.
     initializeRestApi();
   }
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();
+    }
+  }
+}

Reply via email to