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

   ### Version
   
   main branch
   
   ### Describe what's wrong
   
   Iceberg REST tables and views carry no Gravitino id in their properties. For 
such objects, the core
   import treats any entity stored under the name as already imported and keeps 
its id
   (`TableOperationDispatcher` and `ViewOperationDispatcher`, the "not created 
by Gravitino" case).
   
   The Iceberg REST create hooks import straight after the backend create and 
never check for a leftover
   entity (`IcebergTableHookDispatcher#importTableAndSetOwner`, 
`IcebergViewHookDispatcher#createView`).
   `IcebergNamespaceHookDispatcher#registerTable` and `#registerView` go 
further: when an entity exists,
   they skip the import and keep it, owner included.
   
   Leftover entities come from normal paths: a drop whose entity cleanup fails 
(logged at WARN and
   ignored), a rename whose entity update fails, a drop and recreate on two 
nodes, or a drop while the
   hooks are not installed.
   
   So a new table or view **inherits the old object's id, and with it the role 
grants, tags, policies and
   statistics bound to it.** Register also keeps the old owner.
   
   A successful backend create, or a register without overwrite, proves that no 
object had the name, so
   any entity under it is stale.
   
   ### Error message and/or stacktrace
   
   None. The create returns 200. The drop that left the entity logs
   `Failed to reconcile Gravitino table entity after the Iceberg backend 
operation succeeded` at WARN.
   
   ### How to reproduce
   
   1. Run the Iceberg REST server in auxiliary mode with 
`gravitino.authorization.enable=true`.
   2. Grant `SELECT_TABLE` on `s1.t1` to a role of user `u1`.
   3. Drop `t1` through Iceberg REST while the entity store delete fails, so 
the entity stays.
   4. As user `u2`, create a new `t1` through Iceberg REST.
   5. As `u1`, load `s1.t1`.
   
   Expected: the new `t1` gets a new id, is owned by `u2`, and `u1` is denied.
   Actual: the new `t1` keeps the old id, so `u1` can read it.
   
   `registerTable` without overwrite, `createView` and `registerView` behave 
the same way.
   
   ### Additional context
   
   Proposed fix: after a successful backend create, staged-create commit, 
register without overwrite, or
   view create or register, delete any entity under the name (this cascades its 
bindings) and remove the
   plugin privileges for the name, then import. Keep register with overwrite as 
today. Keep the drop
   reconcile best-effort, but log a failure at ERROR.
   
   A follow-up in core could store the Iceberg table UUID at import and treat a 
mismatch as "not
   imported".
   


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