yuqi1129 opened a new issue, #12837:
URL: https://github.com/apache/gravitino/issues/12837

   ## Version
   
   main branch. The same problem also affects branch-1.3.
   
   ## Describe what's wrong
   
   The parent-scope list authorization short-circuit falls back to per-object 
authorization whenever the principal has a deny on any privilege used by the 
filter expression.
   
   Table visibility uses independent OR paths:
   
   ```text
   PARENT_OWNER || PARENT_SELECT_TABLE || PARENT_MODIFY_TABLE
   ```
   
   However, the deny gate currently combines the privileges:
   
   ```text
   (parentOwner || parentSelect || parentModify)
       && !hasDenyPolicy({SELECT_TABLE, MODIFY_TABLE})
   ```
   
   For example:
   
   - `SELECT_TABLE` is allowed at the catalog scope.
   - `MODIFY_TABLE` is allowed at the catalog scope.
   - `MODIFY_TABLE` is denied at the listed schema.
   
   Every table remains visible through the `SELECT_TABLE` path, but the 
unrelated `MODIFY_TABLE` deny disables the entire short-circuit. Listing a 
schema with about 10,000 tables then performs authorization for every table.
   
   The short-circuit should evaluate each sufficient access path independently:
   
   ```text
   parentOwner
       || (parentSelect && !hasDenyPolicy({SELECT_TABLE}))
       || (parentModify && !hasDenyPolicy({MODIFY_TABLE}))
   ```
   
   A deny should only invalidate the path using the same privilege.
   
   On the current main branch, Gravitino REST table listing uses
   `LIST_TABLE_LIKE_AUTHORIZATION_EXPRESSION`, while the table short-circuit is 
registered only for
   `FILTER_TABLE_AUTHORIZATION_EXPRESSION`. The table-like expression should 
receive equivalent
   route-aware short-circuit coverage.
   
   ## Error message and/or stacktrace
   
   There is no exception. Requests succeed or time out with severe latency.
   
   In a schema containing about 10,496 tables:
   
   - Authorization disabled: P95 approximately 44–76 ms.
   - Authorization enabled with the policy combination above: P95 approximately 
150–270 seconds.
   - Some five-minute test runs complete with no successful samples.
   
   ## How to reproduce
   
   1. Create a catalog and a schema containing approximately 10,000 tables.
   2. Grant a role `SELECT_TABLE` and `MODIFY_TABLE` at the catalog scope.
   3. Deny `MODIFY_TABLE` on the listed schema.
   4. Enable authorization.
   5. List the tables through Gravitino REST or Iceberg REST.
   
   All tables are visible through the catalog-level `SELECT_TABLE` grant, but 
the schema-level
   `MODIFY_TABLE` deny causes `MetadataAuthzHelper.filterByExpression` to 
evaluate authorization for
   every table.
   
   ## Additional context
   
   This is a follow-up to #11775 and #11778. The original optimization is 
deliberately conservative,
   but it conflates independent authorization paths.
   
   The fix should:
   
   - Model each sufficient parent-scope authorization path separately.
   - Check only the deny privileges associated with that path.
   - Preserve per-object fallback when a deny exists on the selected path.
   - Cover both `FILTER_TABLE_AUTHORIZATION_EXPRESSION` and
     `LIST_TABLE_LIKE_AUTHORIZATION_EXPRESSION`.
   - Add tests proving authorization work remains constant with respect to the 
number of listed
     objects when an unaffected path makes every object visible.
   
   Enterprise reproduction: 
https://github.com/datastrato/gravitino-enterprise/issues/1651
   


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