ryuan-cw opened a new issue, #4573:
URL: https://github.com/apache/polaris/issues/4573

   ### Is your feature request related to a problem? Please describe.
   
   `GET /api/management/v1/catalogs` (`listCatalogs`) is authorized by 
`CATALOG_LIST` on the **root container** — effectively a `service_admin` 
capability — and it is all-or-nothing: a principal lacking that root privilege 
gets a hard `403`, not a filtered list. A least-privilege principal therefore 
cannot *discover* catalogs even for catalogs it has been explicitly granted 
access to.
   
   Concretely, with a principal whose catalog role grants 
`CATALOG_READ_PROPERTIES` / `NAMESPACE_LIST` / `TABLE_LIST` / `TABLE_READ_DATA` 
on specific catalogs:
   
   - `GET /api/management/v1/catalogs` → `403` (`Principal '…' … is not 
authorized for op LIST_CATALOGS`)
   - `GET /api/management/v1/catalogs/{name}` (`getCatalog`) → `200`
   - Iceberg catalog API (list namespaces/tables, read data) → works
   
   So the principal can read everything in the catalogs it is granted, but 
cannot enumerate them. This makes the **polaris-console** catalog browser 
(which calls `listCatalogs`) and any read-only "viewer" persona unusable for 
non-admins — the catalog list is empty/forbidden.
   
   And there is no narrower fix: `CATALOG_LIST` must sit on the root container, 
the only code path that places a privilege there 
(`PolarisAdminService.grantPrivilegeOnRootContainerToPrincipalRole`, op 
`ADD_ROOT_GRANT_TO_PRINCIPAL_ROLE`, itself requiring `SERVICE_MANAGE_ACCESS`) 
is **not exposed via the management REST API**, so the only API-reachable way 
to make `listCatalogs` succeed is to grant `service_admin` (full administrative 
access: create/drop catalogs, manage all principals/roles/grants) — the 
opposite of least privilege.
   
   Relevant code (`apache-polaris-1.3.0-incubating`; authorization path 
unchanged on `main`):
   
   - `PolarisAdminService.listCatalogs()` → 
`authorizeBasicRootOperationOrThrow(LIST_CATALOGS)`, then 
`listCatalogsUnsafe()` returns **all** catalogs (no filtering).
   - `authorizeBasicRootOperationOrThrow(...)` resolves the **root container** 
as the authorization target.
   - `RbacOperationSemantics`: `register(LIST_CATALOGS, CATALOG_LIST)`.
   - `PolarisAuthorizerImpl`: `CATALOG_LIST` is satisfied by 
`SERVICE_MANAGE_ACCESS` (or catalog-level `CATALOG_READ_PROPERTIES`, etc.) **on 
the same securable** — i.e. on the root container, which a non-admin never 
holds.
   
   ### Describe the solution you'd like
   
   When the caller does not hold `CATALOG_LIST` on the root container, 
`listCatalogs` should return the **subset of catalogs the caller is authorized 
on** (holds any catalog-role grant / `CATALOG_READ_PROPERTIES`), instead of 
throwing `403`. Callers with root `CATALOG_LIST` / `SERVICE_MANAGE_ACCESS` 
continue to see all catalogs.
   
   This reuses the same per-securable check `getCatalog` already performs, 
mirrors how `listNamespaces` / `listTables` are scoped within a catalog, and 
matches how object stores filter list results by ACL. Because each catalog is 
itself a securable with grants (unlike principal-roles in #363), filtering the 
catalog list by the caller's effective grants is straightforward. Result: 
non-admins discover exactly the catalogs they can use, the console works for 
read-only personas, and no `service_admin` grant or root-container grant API is 
required.
   
   ### Describe alternatives you've considered
   
   - **Expose root-container grants via REST** so `CATALOG_LIST`-only can be 
granted to a principal role — enables a "list, no write/drop" role, but is 
still all-or-nothing ("see all catalogs") and adds a privilege that is hard to 
reason about; filtering is more useful and least-surprising.
   - **`service_admin`** (current workaround) — over-privileged (can drop 
catalogs, manage all principals); unacceptable for viewer / least-privilege use.
   - **A catalog-scoped discovery endpoint** — cumbersome when a principal has 
access to many catalogs (also noted in #363).
   
   ### Additional context
   
   Sibling issue #363 raises the same class of problem for `listPrincipalRoles` 
under `catalog_admin`. Performance: filtering adds a per-catalog authorization 
check; catalog counts are typically small and this can be batched if needed. 
Observed on Apache Polaris 1.3.0-incubating via polaris-console; authorization 
path verified unchanged on `main`.
   


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