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**.
|