yuqi1129 opened a new issue, #13089:
URL: https://github.com/apache/gravitino/issues/13089
### What would you like to be improved?
Lance REST enforces authorization in a different place depending on the
deployment mode, so the same request from the same user can be authorized
differently.
- **Auxiliary mode** installs `LanceRESTAuthInterceptionService`, which
checks each Lance endpoint once against an expression written for that
endpoint's Lance semantics (`LanceAuthorizationExpressions`), before any
dispatcher call. Listings are filtered by `LanceAuthorizationMetadataFilter`.
- **Standalone mode** installs neither: `enableMetadataAuthorization` is
`auxMode && gravitino.authorization.enable && metalake configured`, so it is
always false. Every underlying Gravitino REST call is authorized by the
Gravitino server using the rules of that call.
A concrete, reproducible divergence — no race required:
`TableExists` on an **existing** table, caller holds `USE_CATALOG` +
`USE_SCHEMA` + `CREATE_TABLE` and nothing else.
- Auxiliary: `LanceTableOperations.tableExists` is annotated with
`PROBE_TABLE_AUTHORIZATION_EXPRESSION`, which accepts `PROBE_TABLE_LIKE ||
CREATE_TABLE` → **200**.
- Standalone: `GravitinoLanceTableOperations.tableExists` →
`GravitinoClient` → `TableCatalog.tableExists`, whose default is
`loadTable(ident) != null`. The Gravitino server evaluates
`TableOperations.loadTable`: the primary `LOAD_TABLE` expression fails,
`allowCheckExistence` passes, and `LoadTableAuthorizationExecutor` then returns
`!tableExists(ident)` — it only lets the probe through when the table is
**absent** → **403**.
Other differences follow from the same cause: a Lance endpoint that maps to
several Gravitino calls (`CreateNamespace` loads before creating) is checked
once in auxiliary mode and once per underlying call in standalone mode;
overwrite/drop follow Lance's ownership rule in auxiliary mode and the
underlying `alter`/`drop` rule in standalone mode.
#12954 documents these as known limits. This issue tracks removing them.
### How should we improve?
Two options, neither cheap:
1. **Run the Lance interceptor in standalone mode too.** Requires a remote
implementation of the pieces `BaseMetadataAuthorizationMethodInterceptor` uses
in-process today — `AuthorizationUtils.checkCurrentUser`,
`GravitinoAuthorizer.findUnheldRoles`, ownership and privilege lookups behind
`AuthorizationExpressionEvaluator`. Each Lance authorization would cost several
REST round trips. Aligns standalone to Lance's semantics.
2. **Drop the Lance interceptor in auxiliary mode** and rely on
dispatcher-level authorization on both paths. Cheap, but aligns auxiliary to
the *less* precise side: the `TableExists` example above would become 403 in
both modes, and multi-call endpoints would be checked per call everywhere.
A middle path worth evaluating first: give Gravitino a real existence
endpoint (`HEAD .../tables/{table}` with a probe expression, as the Iceberg
REST server already has), so standalone's `tableExists` no longer has to be
modelled as `loadTable`. That removes the most visible divergence without
moving the interceptor.
Whichever direction, the deployment-mode table in
`docs/lance-rest-service.md` ("Authorization differences between deployment
modes") should shrink as differences are closed.
Related: #12984 (forwards the caller's identity in standalone mode; does not
change where authorization runs), #12574.
--
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]