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]

Reply via email to