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 7944f4ff92 [#9036] feat(authz): add document and api for tag access 
control (#9035)
7944f4ff92 is described below

commit 7944f4ff92006ed49ed609276150ee376ea67670
Author: yangyang zhong <[email protected]>
AuthorDate: Wed Nov 12 15:01:51 2025 +0800

    [#9036] feat(authz): add document and api for tag access control (#9035)
    
    ### What changes were proposed in this pull request?
    
    add document for tag access control
    
    ### Why are the changes needed?
    
    Fix: #9036
    
    ### 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  |  4 +-
 .../java/org/apache/gravitino/MetadataObjects.java |  8 ++-
 .../apache/gravitino/authorization/Privilege.java  |  6 +-
 .../apache/gravitino/authorization/Privileges.java | 81 +++++++++++++++++++++-
 .../authorization/TestSecurableObjects.java        | 15 ++++
 docs/security/access-control.md                    | 21 +++++-
 6 files changed, 127 insertions(+), 8 deletions(-)

diff --git a/api/src/main/java/org/apache/gravitino/MetadataObject.java 
b/api/src/main/java/org/apache/gravitino/MetadataObject.java
index 05beafe9d9..09824eaefe 100644
--- a/api/src/main/java/org/apache/gravitino/MetadataObject.java
+++ b/api/src/main/java/org/apache/gravitino/MetadataObject.java
@@ -61,7 +61,9 @@ public interface MetadataObject {
     /** A role is an object contains specific securable objects with 
privileges */
     ROLE,
     /** A model is mapped to the model artifact in ML. */
-    MODEL
+    MODEL,
+    /** A tag is used to help manage other metadata object. */
+    TAG;
   }
 
   /**
diff --git a/api/src/main/java/org/apache/gravitino/MetadataObjects.java 
b/api/src/main/java/org/apache/gravitino/MetadataObjects.java
index e96b6e7e4a..7400e37a1c 100644
--- a/api/src/main/java/org/apache/gravitino/MetadataObjects.java
+++ b/api/src/main/java/org/apache/gravitino/MetadataObjects.java
@@ -73,8 +73,9 @@ public class MetadataObjects {
         names.size() != 1
             || type == MetadataObject.Type.CATALOG
             || type == MetadataObject.Type.METALAKE
-            || type == MetadataObject.Type.ROLE,
-        "If the length of names is 1, it must be the CATALOG, METALAKE, or 
ROLE type");
+            || type == MetadataObject.Type.ROLE
+            || type == MetadataObject.Type.TAG,
+        "If the length of names is 1, it must be the CATALOG, METALAKE,TAG, or 
ROLE type");
 
     Preconditions.checkArgument(
         names.size() != 2 || type == MetadataObject.Type.SCHEMA,
@@ -156,6 +157,9 @@ public class MetadataObjects {
     if (type == MetadataObject.Type.ROLE) {
       return MetadataObjects.of(Collections.singletonList(fullName), 
MetadataObject.Type.ROLE);
     }
+    if (type == MetadataObject.Type.TAG) {
+      return MetadataObjects.of(Collections.singletonList(fullName), 
MetadataObject.Type.TAG);
+    }
 
     return MetadataObjects.of(parts, type);
   }
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 540c0aa7fa..2a53505eb1 100644
--- a/api/src/main/java/org/apache/gravitino/authorization/Privilege.java
+++ b/api/src/main/java/org/apache/gravitino/authorization/Privilege.java
@@ -94,7 +94,11 @@ public interface Privilege {
     /** The privilege to create a model version */
     CREATE_MODEL_VERSION(0L, 1L << 19),
     /** The privilege to view the metadata of the model and download all the 
model versions */
-    USE_MODEL(0L, 1L << 20);
+    USE_MODEL(0L, 1L << 20),
+    /** The privilege to create a tag */
+    CREATE_TAG(0L, 1L << 21),
+    /** The privilege to apply a tag */
+    APPLY_TAG(0L, 1L << 22);
 
     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 8c736fa69a..b92383a027 100644
--- a/api/src/main/java/org/apache/gravitino/authorization/Privileges.java
+++ b/api/src/main/java/org/apache/gravitino/authorization/Privileges.java
@@ -133,7 +133,10 @@ public class Privileges {
         return CreateModelVersion.allow();
       case USE_MODEL:
         return UseModel.allow();
-
+      case CREATE_TAG:
+        return CreateTag.allow();
+      case APPLY_TAG:
+        return ApplyTag.allow();
       default:
         throw new IllegalArgumentException("Doesn't support the privilege: " + 
name);
     }
@@ -215,7 +218,10 @@ public class Privileges {
         return CreateModelVersion.deny();
       case USE_MODEL:
         return UseModel.deny();
-
+      case CREATE_TAG:
+        return CreateTag.deny();
+      case APPLY_TAG:
+        return ApplyTag.deny();
       default:
         throw new IllegalArgumentException("Doesn't support the privilege: " + 
name);
     }
@@ -886,4 +892,75 @@ public class Privileges {
       return MODEL_SUPPORTED_TYPES.contains(type);
     }
   }
+
+  /** The privilege to create a tag */
+  public static class CreateTag extends GenericPrivilege<CreateTag> {
+    private static final CreateTag ALLOW_INSTANCE = new 
CreateTag(Condition.ALLOW, Name.CREATE_TAG);
+    private static final CreateTag DENY_INSTANCE = new 
CreateTag(Condition.DENY, Name.CREATE_TAG);
+
+    /**
+     * Constructor for GenericPrivilege.
+     *
+     * @param condition the condition of the privilege
+     * @param name the name of the privilege
+     */
+    protected CreateTag(Condition condition, Name name) {
+      super(condition, name);
+    }
+
+    /**
+     * @return The instance with allow condition of the privilege.
+     */
+    public static CreateTag allow() {
+      return ALLOW_INSTANCE;
+    }
+
+    /**
+     * @return The instance with deny condition of the privilege.
+     */
+    public static CreateTag deny() {
+      return DENY_INSTANCE;
+    }
+
+    @Override
+    public boolean canBindTo(MetadataObject.Type type) {
+      return type == MetadataObject.Type.METALAKE;
+    }
+  }
+
+  /** The privilege to apply tag to object. */
+  public static final class ApplyTag extends GenericPrivilege<ApplyTag> {
+
+    private static final ApplyTag ALLOW_INSTANCE = new 
ApplyTag(Condition.ALLOW, Name.CREATE_TAG);
+    private static final ApplyTag DENY_INSTANCE = new ApplyTag(Condition.DENY, 
Name.CREATE_TAG);
+
+    /**
+     * Constructor for GenericPrivilege.
+     *
+     * @param condition the condition of the privilege
+     * @param name the name of the privilege
+     */
+    ApplyTag(Condition condition, Name name) {
+      super(condition, name);
+    }
+
+    /**
+     * @return The instance with allow condition of the privilege.
+     */
+    public static ApplyTag allow() {
+      return ALLOW_INSTANCE;
+    }
+
+    /**
+     * @return The instance with deny condition of the privilege.
+     */
+    public static ApplyTag deny() {
+      return DENY_INSTANCE;
+    }
+
+    @Override
+    public boolean canBindTo(MetadataObject.Type type) {
+      return type == MetadataObject.Type.METALAKE || type == 
MetadataObject.Type.TAG;
+    }
+  }
 }
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 4283dd53cf..7fad26f0e3 100644
--- 
a/api/src/test/java/org/apache/gravitino/authorization/TestSecurableObjects.java
+++ 
b/api/src/test/java/org/apache/gravitino/authorization/TestSecurableObjects.java
@@ -180,6 +180,8 @@ public class TestSecurableObjects {
     Privilege createModel = Privileges.CreateModel.allow();
     Privilege createModelVersion = Privileges.CreateModelVersion.allow();
     Privilege useModel = Privileges.UseModel.allow();
+    Privilege createTag = Privileges.CreateTag.allow();
+    Privilege applyTag = Privileges.ApplyTag.allow();
 
     // Test create catalog
     
Assertions.assertTrue(createCatalog.canBindTo(MetadataObject.Type.METALAKE));
@@ -382,5 +384,18 @@ public class TestSecurableObjects {
     Assertions.assertFalse(useModel.canBindTo(MetadataObject.Type.ROLE));
     Assertions.assertFalse(useModel.canBindTo(MetadataObject.Type.COLUMN));
     Assertions.assertTrue(useModel.canBindTo(MetadataObject.Type.MODEL));
+
+    Assertions.assertTrue(createTag.canBindTo(MetadataObject.Type.METALAKE));
+    Assertions.assertFalse(createTag.canBindTo(MetadataObject.Type.CATALOG));
+
+    Assertions.assertTrue(applyTag.canBindTo(MetadataObject.Type.METALAKE));
+    Assertions.assertTrue(applyTag.canBindTo(MetadataObject.Type.TAG));
+    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 cb1d7a960e..2f7de2c562 100644
--- a/docs/security/access-control.md
+++ b/docs/security/access-control.md
@@ -115,7 +115,7 @@ If a securable object needs to be managed by more than one 
person at the same ti
 The metadata object that supports ownership is as follows:
 
 | Metadata Object Type |
-|----------------------|
+| -------------------- |
 | Metalake             |
 | Catalog              |
 | Schema               |
@@ -124,6 +124,7 @@ The metadata object that supports ownership is as follows:
 | Fileset              |
 | Role                 |
 | Model                |
+| Tag                  |
 
 ### User
 Users are generally granted one or multiple Roles, and users have different 
operating privileges depending on their Role.
@@ -264,6 +265,13 @@ DENY `WRITE_FILESET` won‘t deny the `READ_FILESET` 
operation if the user has t
 | CREATE_MODEL_VERSION | Metalake, Catalog, Schema, Model | Create a model 
version                                             |
 | USE_MODEL            | Metalake, Catalog, Schema, Model | View the metadata 
of the model and download all the model versions |
 
+### Tag privileges
+
+| Name       | Supports Securable Object | Operation                           
  |
+|------------|---------------------------|---------------------------------------|
+| CREATE_TAG | Metalake                  | Create a tag                        
  |
+| APPLY_TAG  | Metalake, Tag             | Associate tags with metadata 
objects. |
+
 ## Inheritance Model
 
 Securable objects in Gravitino are hierarchical and privileges are inherited 
downward.
@@ -963,7 +971,7 @@ The following table lists the required privileges for each 
API.
 | create metalake                   | The user must be the service admins, 
configured in the server configurations.                                        
                                                                                
                                         |
 | load metalake                     | The user is in the metalake              
                                                                                
                                                                                
                                     |
 | alter metalake                    | The owner of the metalake                
                                                                                
                                                                                
                                     |
-| drop metalake                     | The owner of the metalake                
                                                                                
                                                                                
                                     | 
+| drop metalake                     | The owner of the metalake                
                                                                                
                                                                                
                                     |
 | create catalog                    | `CREATE_CATALOG` on the metalake or the 
owner of the metalake                                                           
                                                                                
                                      |
 | alter catalog                     | The owner of the catalog, metalake       
                                                                                
                                                                                
                                     |
 | drop catalog                      | The owner of the catalog, metalake       
                                                                                
                                                                                
                                     |
@@ -1025,4 +1033,13 @@ The following table lists the required privileges for 
each API.
 | grant privilege                   | `MANAGE_GRANTS` on the metalake or the 
owner of the securable object                                                   
                                                                                
                                       |
 | revoke privilege                  | `MANAGE_GRANTS` on the metalake or the 
owner of the securable object                                                   
                                                                                
                                       |
 | set owner                         | The owner of the securable object        
                                                                                
                                                                                
                                     |
+| list tags                         | The owner of the metalake can see all 
the tags, others can see the tags which they can load.                          
                                                                                
                                        |
+| create tag                        | `CREATE_TAG` on the metalake or the 
owner of the metalake.                                                          
                                                                                
                                          |
+| get tag                           | `APPLY_TAG` on the metalake or tag, the 
owner of the metalake or the tag.                                               
                                                                                
                                      |
+| alter tag                         | Must be the owner of the metalake or the 
tag.                                                                            
                                                                                
                                     |
+| delete tag                        | Must be the owner of the metalake or the 
tag.                                                                            
                                                                                
                                     |
+| list objects for tag              | Requires both permission to **get the 
tag** and permission to **load metadata objects**.                              
                                                                                
                                        |
+| 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**.                                        
                                                                                
                                     |
 

Reply via email to