This is an automated email from the ASF dual-hosted git repository.
jerryshao 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 b49d895eaf [MINOR] improvement(authz): Add debug logging for
list-authorization short-circuit (#12101)
b49d895eaf is described below
commit b49d895eaf358bdbeafef1ca9e702652514a3055
Author: Qi Yu <[email protected]>
AuthorDate: Mon Jul 20 19:27:43 2026 +0800
[MINOR] improvement(authz): Add debug logging for list-authorization
short-circuit (#12101)
### What changes were proposed in this pull request?
Adds `DEBUG`-level logging around the list-authorization parent-scope
short-circuit (`MetadataAuthzHelper.filterByExpression` /
`allVisibleViaParentScope`, introduced in #11778) so it is possible to
tell, per request and per principal, whether the short-circuit fired and
— when it did not — exactly which condition disqualified it:
- **HIT**: every listed object is returned via a parent-scope grant and
the per-object authorization loop is skipped.
- **MISS / skipped**, with the reason: no short-circuit spec registered
/ filter-expression mismatch, listed objects span multiple parent
namespaces, the principal has no parent-scope grant, or a deny policy
exists on the relevant privileges.
Every log line now includes the current principal, the entity type, and
the metalake.
This is purely diagnostic — no behavior change.
### Why are the changes needed?
When a `list` call (e.g. `list catalogs`) is slow, there is currently no
way to observe whether the #11778 short-circuit applied. The `verbose`
(`details=true`) path and finer-grained or denied grants fall back to
per-object authorization; these logs make that visible and greatly speed
up diagnosing slow-list reports.
Fix: N/A (minor diagnostic improvement)
### Does this PR introduce _any_ user-facing change?
No. Debug logging only.
### How was this patch tested?
No behavior change (only added `LOG.debug` calls and an extracted
`hasDeny` local; control flow is unchanged). Existing tests cover the
short-circuit logic. Verified `:server-common:compileJava` succeeds.
---
.../server/authorization/MetadataAuthzHelper.java | 70 +++++++++++++++++++---
1 file changed, 61 insertions(+), 9 deletions(-)
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataAuthzHelper.java
b/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataAuthzHelper.java
index 6e98f7e455..fc7db7b615 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataAuthzHelper.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataAuthzHelper.java
@@ -206,13 +206,29 @@ public class MetadataAuthzHelper {
String expression,
Entity.EntityType entityType,
NameIdentifier[] nameIdentifiers) {
- if (enableAuthorization()
- && nameIdentifiers.length > 0
- && allVisibleViaParentScope(metalake, expression, entityType,
nameIdentifiers)) {
- // A privilege granted at a parent scope (metalake/catalog/schema) makes
every object in the
- // list visible, and no object-level deny exists, so the per-object
authorization loop is
- // skipped entirely. See
AuthorizationExpressionConstants.*_LIST_PARENT_SCOPE_*.
- return nameIdentifiers;
+ if (enableAuthorization() && nameIdentifiers.length > 0) {
+ String principalName = PrincipalUtils.getCurrentPrincipal().getName();
+ if (allVisibleViaParentScope(metalake, expression, entityType,
nameIdentifiers)) {
+ // A privilege granted at a parent scope (metalake/catalog/schema)
makes every object in
+ // the list visible, and no object-level deny exists, so the
per-object authorization loop
+ // is skipped entirely. See
AuthorizationExpressionConstants.*_LIST_PARENT_SCOPE_*.
+ LOG.debug(
+ "List authorization short-circuit HIT for principal {}, entity
type {} under metalake "
+ + "{}: all {} listed object(s) are visible via a parent-scope
grant; skipping the "
+ + "per-object authorization loop.",
+ principalName,
+ entityType,
+ metalake,
+ nameIdentifiers.length);
+ return nameIdentifiers;
+ }
+ LOG.debug(
+ "List authorization short-circuit MISS for principal {}, entity type
{} under metalake "
+ + "{} ({} object(s)); falling back to the per-object
authorization loop.",
+ principalName,
+ entityType,
+ metalake,
+ nameIdentifiers.length);
}
preloadToCache(entityType, nameIdentifiers);
preloadOwner(entityType, nameIdentifiers);
@@ -230,8 +246,19 @@ public class MetadataAuthzHelper {
String expression,
Entity.EntityType entityType,
NameIdentifier[] nameIdentifiers) {
+ Principal principal = PrincipalUtils.getCurrentPrincipal();
ListShortCircuit spec = LIST_SHORT_CIRCUITS.get(entityType);
if (spec == null || !spec.filterExpression.equals(expression)) {
+ LOG.debug(
+ "Parent-scope short-circuit unavailable for principal {}, entity
type {} under metalake "
+ + "{}: {}.",
+ principal.getName(),
+ entityType,
+ metalake,
+ spec == null
+ ? "no short-circuit spec is registered for this entity type"
+ : "the requested filter expression does not match the registered
short-circuit "
+ + "expression");
return false;
}
@@ -239,11 +266,18 @@ public class MetadataAuthzHelper {
Namespace parent = nameIdentifiers[0].namespace();
for (NameIdentifier ident : nameIdentifiers) {
if (!ident.namespace().equals(parent)) {
+ LOG.debug(
+ "Parent-scope short-circuit skipped for principal {}, entity type
{} under metalake "
+ + "{}: listed objects span multiple parent namespaces (e.g. {}
vs {}).",
+ principal.getName(),
+ entityType,
+ metalake,
+ parent,
+ ident.namespace());
return false;
}
}
- Principal principal = PrincipalUtils.getCurrentPrincipal();
GravitinoAuthorizer authorizer =
GravitinoAuthorizerProvider.getInstance().getGravitinoAuthorizer();
AuthorizationRequestContext requestContext = new
AuthorizationRequestContext();
@@ -255,13 +289,31 @@ public class MetadataAuthzHelper {
new AuthorizationExpressionEvaluator(spec.parentScopeExpression,
authorizer)
.evaluate(metadataNames, requestContext, principal,
Optional.empty());
if (!parentGrantsAccess) {
+ LOG.debug(
+ "Parent-scope short-circuit skipped for entity type {} under
metalake {}: principal {} "
+ + "is not granted access at the parent scope, so per-object
authorization is "
+ + "required.",
+ entityType,
+ metalake,
+ principal.getName());
return false;
}
// Parent scope grants access to every object; the only thing that can
still hide one is a
// deny on these privileges (at the parent scope or on an individual
object), so the
// short-circuit is only safe when no such deny may exist.
- return !authorizer.hasDenyPolicy(principal, metalake, spec.denyPrivileges,
requestContext);
+ boolean hasDeny =
+ authorizer.hasDenyPolicy(principal, metalake, spec.denyPrivileges,
requestContext);
+ if (hasDeny) {
+ LOG.debug(
+ "Parent-scope short-circuit disabled for entity type {} under
metalake {}: principal {} "
+ + "holds a deny policy on {}, so per-object authorization is
required.",
+ entityType,
+ metalake,
+ principal.getName(),
+ spec.denyPrivileges);
+ }
+ return !hasDeny;
}
/**