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

roryqi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 751a5e7df9 [#9072] feat(authz): Add document and api for policy access 
control (#9115)
751a5e7df9 is described below

commit 751a5e7df99bf03a22aad2d6a1668f4c4b78528d
Author: yangyang zhong <[email protected]>
AuthorDate: Thu Nov 20 11:19:37 2025 +0800

    [#9072] feat(authz): Add document and api for policy access control (#9115)
    
    ### What changes were proposed in this pull request?
    
    Add document and api for policy access control
    
    ### Why are the changes needed?
    
    Fix: #9072
    
    ### Does this PR introduce _any_ user-facing change?
    
    None
    
    ### How was this patch tested?
    
    org.apache.gravitino.authorization.TestSecurableObjects
---
 .../java/org/apache/gravitino/MetadataObject.java  |  7 +-
 .../java/org/apache/gravitino/MetadataObjects.java |  3 +-
 .../apache/gravitino/authorization/Privilege.java  |  7 +-
 .../apache/gravitino/authorization/Privileges.java | 79 ++++++++++++++++++++++
 .../authorization/TestSecurableObjects.java        | 22 ++++++
 docs/security/access-control.md                    | 17 +++++
 6 files changed, 132 insertions(+), 3 deletions(-)

diff --git a/api/src/main/java/org/apache/gravitino/MetadataObject.java 
b/api/src/main/java/org/apache/gravitino/MetadataObject.java
index 09824eaefe..4df271d049 100644
--- a/api/src/main/java/org/apache/gravitino/MetadataObject.java
+++ b/api/src/main/java/org/apache/gravitino/MetadataObject.java
@@ -63,7 +63,12 @@ public interface MetadataObject {
     /** A model is mapped to the model artifact in ML. */
     MODEL,
     /** A tag is used to help manage other metadata object. */
-    TAG;
+    TAG,
+    /**
+     * A policy can be associated with a metadata object for data governance 
and similar purposes.
+     */
+    POLICY,
+    ;
   }
 
   /**
diff --git a/api/src/main/java/org/apache/gravitino/MetadataObjects.java 
b/api/src/main/java/org/apache/gravitino/MetadataObjects.java
index 7400e37a1c..c3f7e8a7c3 100644
--- a/api/src/main/java/org/apache/gravitino/MetadataObjects.java
+++ b/api/src/main/java/org/apache/gravitino/MetadataObjects.java
@@ -74,7 +74,8 @@ public class MetadataObjects {
             || type == MetadataObject.Type.CATALOG
             || type == MetadataObject.Type.METALAKE
             || type == MetadataObject.Type.ROLE
-            || type == MetadataObject.Type.TAG,
+            || type == MetadataObject.Type.TAG
+            || type == MetadataObject.Type.POLICY,
         "If the length of names is 1, it must be the CATALOG, METALAKE,TAG, or 
ROLE type");
 
     Preconditions.checkArgument(
diff --git 
a/api/src/main/java/org/apache/gravitino/authorization/Privilege.java 
b/api/src/main/java/org/apache/gravitino/authorization/Privilege.java
index 2a53505eb1..23a7c4a2cc 100644
--- a/api/src/main/java/org/apache/gravitino/authorization/Privilege.java
+++ b/api/src/main/java/org/apache/gravitino/authorization/Privilege.java
@@ -98,7 +98,12 @@ public interface Privilege {
     /** The privilege to create a tag */
     CREATE_TAG(0L, 1L << 21),
     /** The privilege to apply a tag */
-    APPLY_TAG(0L, 1L << 22);
+    APPLY_TAG(0L, 1L << 22),
+    /** The privilege to create a policy */
+    CREATE_POLICY(0L, 1L << 23),
+    /** The privilege to apply a policy */
+    APPLY_POLICY(0L, 1L << 24),
+    ;
 
     private final long highBits;
     private final long lowBits;
diff --git 
a/api/src/main/java/org/apache/gravitino/authorization/Privileges.java 
b/api/src/main/java/org/apache/gravitino/authorization/Privileges.java
index b92383a027..7a85f12237 100644
--- a/api/src/main/java/org/apache/gravitino/authorization/Privileges.java
+++ b/api/src/main/java/org/apache/gravitino/authorization/Privileges.java
@@ -137,6 +137,10 @@ public class Privileges {
         return CreateTag.allow();
       case APPLY_TAG:
         return ApplyTag.allow();
+      case APPLY_POLICY:
+        return ApplyPolicy.allow();
+      case CREATE_POLICY:
+        return CreatePolicy.allow();
       default:
         throw new IllegalArgumentException("Doesn't support the privilege: " + 
name);
     }
@@ -963,4 +967,79 @@ public class Privileges {
       return type == MetadataObject.Type.METALAKE || type == 
MetadataObject.Type.TAG;
     }
   }
+
+  /** The privilege to create a tag */
+  public static class CreatePolicy extends GenericPrivilege<CreatePolicy> {
+    private static final CreatePolicy ALLOW_INSTANCE =
+        new CreatePolicy(Condition.ALLOW, Name.CREATE_POLICY);
+    private static final CreatePolicy DENY_INSTANCE =
+        new CreatePolicy(Condition.DENY, Name.CREATE_POLICY);
+
+    /**
+     * Constructor for GenericPrivilege.
+     *
+     * @param condition the condition of the privilege
+     * @param name the name of the privilege
+     */
+    protected CreatePolicy(Condition condition, Name name) {
+      super(condition, name);
+    }
+
+    /**
+     * @return The instance with allow condition of the privilege.
+     */
+    public static CreatePolicy allow() {
+      return ALLOW_INSTANCE;
+    }
+
+    /**
+     * @return The instance with deny condition of the privilege.
+     */
+    public static CreatePolicy deny() {
+      return DENY_INSTANCE;
+    }
+
+    @Override
+    public boolean canBindTo(MetadataObject.Type type) {
+      return type == MetadataObject.Type.METALAKE;
+    }
+  }
+
+  /** The privilege to apply policy to object. */
+  public static final class ApplyPolicy extends GenericPrivilege<ApplyPolicy> {
+
+    private static final ApplyPolicy ALLOW_INSTANCE =
+        new ApplyPolicy(Condition.ALLOW, Name.APPLY_POLICY);
+    private static final ApplyPolicy DENY_INSTANCE =
+        new ApplyPolicy(Condition.DENY, Name.APPLY_POLICY);
+
+    /**
+     * Constructor for GenericPrivilege.
+     *
+     * @param condition the condition of the privilege
+     * @param name the name of the privilege
+     */
+    ApplyPolicy(Condition condition, Name name) {
+      super(condition, name);
+    }
+
+    /**
+     * @return The instance with allow condition of the privilege.
+     */
+    public static ApplyPolicy allow() {
+      return ALLOW_INSTANCE;
+    }
+
+    /**
+     * @return The instance with deny condition of the privilege.
+     */
+    public static ApplyPolicy deny() {
+      return DENY_INSTANCE;
+    }
+
+    @Override
+    public boolean canBindTo(MetadataObject.Type type) {
+      return type == MetadataObject.Type.METALAKE || type == 
MetadataObject.Type.POLICY;
+    }
+  }
 }
diff --git 
a/api/src/test/java/org/apache/gravitino/authorization/TestSecurableObjects.java
 
b/api/src/test/java/org/apache/gravitino/authorization/TestSecurableObjects.java
index 7fad26f0e3..813ac9f4b2 100644
--- 
a/api/src/test/java/org/apache/gravitino/authorization/TestSecurableObjects.java
+++ 
b/api/src/test/java/org/apache/gravitino/authorization/TestSecurableObjects.java
@@ -182,6 +182,8 @@ public class TestSecurableObjects {
     Privilege useModel = Privileges.UseModel.allow();
     Privilege createTag = Privileges.CreateTag.allow();
     Privilege applyTag = Privileges.ApplyTag.allow();
+    Privilege createPolicy = Privileges.CreatePolicy.allow();
+    Privilege applyPolicy = Privileges.ApplyPolicy.allow();
 
     // Test create catalog
     
Assertions.assertTrue(createCatalog.canBindTo(MetadataObject.Type.METALAKE));
@@ -397,5 +399,25 @@ public class TestSecurableObjects {
     Assertions.assertFalse(useModel.canBindTo(MetadataObject.Type.TOPIC));
     Assertions.assertFalse(useModel.canBindTo(MetadataObject.Type.FILESET));
     Assertions.assertFalse(useModel.canBindTo(MetadataObject.Type.ROLE));
+
+    
Assertions.assertTrue(createPolicy.canBindTo(MetadataObject.Type.METALAKE));
+    Assertions.assertFalse(createPolicy.canBindTo(MetadataObject.Type.POLICY));
+    
Assertions.assertFalse(createPolicy.canBindTo(MetadataObject.Type.CATALOG));
+    Assertions.assertFalse(createPolicy.canBindTo(MetadataObject.Type.SCHEMA));
+    Assertions.assertFalse(createPolicy.canBindTo(MetadataObject.Type.TABLE));
+    Assertions.assertFalse(createPolicy.canBindTo(MetadataObject.Type.MODEL));
+    Assertions.assertFalse(createPolicy.canBindTo(MetadataObject.Type.TOPIC));
+    
Assertions.assertFalse(createPolicy.canBindTo(MetadataObject.Type.FILESET));
+    Assertions.assertFalse(createPolicy.canBindTo(MetadataObject.Type.ROLE));
+
+    Assertions.assertTrue(applyPolicy.canBindTo(MetadataObject.Type.METALAKE));
+    Assertions.assertTrue(applyPolicy.canBindTo(MetadataObject.Type.POLICY));
+    Assertions.assertFalse(applyTag.canBindTo(MetadataObject.Type.CATALOG));
+    Assertions.assertFalse(applyTag.canBindTo(MetadataObject.Type.SCHEMA));
+    Assertions.assertFalse(applyTag.canBindTo(MetadataObject.Type.TABLE));
+    Assertions.assertFalse(applyTag.canBindTo(MetadataObject.Type.MODEL));
+    Assertions.assertFalse(useModel.canBindTo(MetadataObject.Type.TOPIC));
+    Assertions.assertFalse(useModel.canBindTo(MetadataObject.Type.FILESET));
+    Assertions.assertFalse(useModel.canBindTo(MetadataObject.Type.ROLE));
   }
 }
diff --git a/docs/security/access-control.md b/docs/security/access-control.md
index 1a6d9a28a0..23d1a0c8f1 100644
--- a/docs/security/access-control.md
+++ b/docs/security/access-control.md
@@ -272,6 +272,13 @@ DENY `WRITE_FILESET` won‘t deny the `READ_FILESET` 
operation if the user has t
 | CREATE_TAG | Metalake                  | Create a tag                        
  |
 | APPLY_TAG  | Metalake, Tag             | Associate tags with metadata 
objects. |
 
+### Policy privileges
+
+| Name          | Supports Securable Object | Operation                        
         |
+|---------------|---------------------------|-------------------------------------------|
+| CREATE_POLICY | Metalake                  | Create a policy                  
         |
+| APPLY_POLICY  | Metalake, Policy          | Associate policies with metadata 
objects. |
+
 ## Inheritance Model
 
 Securable objects in Gravitino are hierarchical and privileges are inherited 
downward.
@@ -1042,4 +1049,14 @@ The following table lists the required privileges for 
each API.
 | list tags for object              | Permission to both list tags Requires 
both permission to **list tags** and permission to **load metadata objects**. 
load metadata objects is required.                                              
                                          |
 | get tag for object                | Requires both permission to **get the 
tag** and permission to **load metadata objects**.                              
                                                                                
                                        |
 | associate object tags             | Requires both `APPLY_TAG` permission and 
permission to **load metadata objects**.                                        
                                                                                
                                     |
+| list policies for object          | The owner of the metalake can see all 
the policies, others can see the policies which they can load.                  
                                                                                
                                        |
+| create policy                     | `CREATE_POLICY` on the metalake or the 
owner of the metalake.                                                          
                                                                                
                                       |
+| get policy                        | `APPLY_POLICY` on the metalake or 
policy, the owner of the metalake or the policy.                                
                                                                                
                                            |
+| alter policy                      | Must be the owner of the metalake or the 
policy.                                                                         
                                                                                
                                     |
+| set policy                        | Must be the owner of the metalake or the 
policy.                                                                         
                                                                                
                                     |
+| delete policy                     | Must be the owner of the metalake or the 
policy.                                                                         
                                                                                
                                     |
+| list objects for policy           | Requires both permission to **get the 
policy** and permission to **load metadata objects**.                           
                                                                                
                                        |
+| associate-object-policies         | Requires both `APPLY_POLICY` permission 
and permission to **load metadata objects**.                                    
                                                                                
                                      |
+| list policies for object          | Requires both permission to **get the 
policy** and permission to **load metadata objects**.                           
                                                                                
                                        |
+| get policy for object             | Requires both permission to **get the 
policy** and permission to **load metadata objects**.                           
                                                                                
                                        |
 

Reply via email to