tiennguyen-onehouse opened a new issue, #11971:
URL: https://github.com/apache/gravitino/issues/11971
### Version
main (also reproduced on 1.3.0). Module:
`authorizations/authorization-ranger`.
### Describe what's wrong
`RangerHelper.getRangerRole(String roleName)` treats a Ranger
**permission-denied** error as **"the role does not exist"**. It does this by
string-matching the Ranger error message:
```java
// RangerHelper.getRangerRole()
} catch (RangerServiceException e) {
// The client will return a error message contains `doesn't have
permission` if the role does
// not exist, then create it.
if (e.getMessage() != null
&& e.getMessage().contains("User doesn't have permissions to get
details")) {
LOG.warn("The role({}) does not exist in the Ranger!, e: {}", roleName,
e);
} else {
throw new AuthorizationPluginException(...);
}
}
return rangerRole; // returns null on the permission error
```
The assumption in the comment ("this message means the role does not exist")
is not safe: Ranger returns the **same** `statusCode=400 / "User doesn't have
permissions to get details for <role>"` when the role **exists but the calling
user lacks role-read permission** on it (Ranger roles have their own RBAC/admin
model). In that case `getRangerRole` returns `null` for a role that actually
exists.
Two callers then act on that wrong `null`:
1. `RangerHelper` (`getRangerRole(...)` → `if (rangerRole == null) {
rangerClient.createRole(...) }`): tries to **create a role that already
exists**, which then fails with `AuthorizationPluginException: Failed to create
the role(...)`.
2. `RangerAuthorizationPlugin#onRoleDeleted` (`if
(rangerHelper.getRangerRole(role.name()) == null) { /* ignore, idempotent */
}`): **silently swallows a real delete failure**, treating it as an idempotent
no-op.
### Observed behavior
With a catalog using `authorization-provider=ranger`, after some role churn
the Ranger admin user configured for Gravitino received a permission-denied
when reading an existing, Gravitino-managed role, producing repeated:
```
WARN RangerHelper.getRangerRole - The role(GRAVITINO_sales_writer) does not
exist in the Ranger!,
e: RangerServiceException: ... statusCode=400, status=Bad Request,
response:{"statusCode":1,"msgDesc":"User doesn't have permissions to get
details for GRAVITINO_sales_writer"}
```
The role **did** exist (visible in Ranger with the expected users/policies),
so subsequent role-sync operations behaved incorrectly (attempted re-create /
masked failures).
### Expected behavior
`getRangerRole` should distinguish **"role not found"** from **"permission
denied"** rather than conflating them via a substring match on the error text.
Concretely, one or more of:
- Inspect the structured error (HTTP status / Ranger error code) instead of
matching `getMessage()`. A permission error should **not** be interpreted as
non-existence.
- Ensure Gravitino registers itself as an admin of the `GRAVITINO_*` roles
it creates, so it can always read them back (avoids the permission-denied path
for its own roles).
- On a genuine permission error, surface it explicitly rather than returning
`null` (which downstream code reads as "absent").
### How to reproduce
1. Configure a catalog with `authorization-provider=ranger` where the Ranger
user Gravitino uses is **not** an admin of the `GRAVITINO_*` roles (i.e., lacks
role-read permission on them).
2. Create a Gravitino role → it is synced to Ranger as `GRAVITINO_<name>`.
3. Trigger any code path that calls `getRangerRole` for that role. Ranger
returns `400 "User doesn't have permissions to get details for <role>"`, and
Gravitino logs `"The role(...) does not exist in the Ranger!"` and proceeds as
if the role is absent (attempts re-create / swallows delete failure).
### Additional context
The fragile part is the semantic conflation of *permission-denied* with
*not-found* (plus reliance on an English substring of a third-party error
message). Happy to help with a PR once the preferred direction
(structured-error check vs. self-registering as role admin) is decided.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]