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();
+ }
+ }
+}