markhoerth opened a new issue, #12760:
URL: https://github.com/apache/gravitino/issues/12760
# Servlets mounted outside the /api/* pathspec receive no authentication and
no audit
## Summary
`GravitinoServer` binds Jersey and every filter to a single pathspec,
`API_ANY_PATH = "/api/*"`. Servlets registered at root paths fall outside it
and
therefore run with no authentication, no audit, no versioning and no custom
filters. Nothing in the build fails when a servlet is added this way. The
mechanism fails open, in the same manner as the metadata authorization
allowlist
already reported.
## Evidence
From `server/src/main/java/org/apache/gravitino/server/GravitinoServer.java`:
```
server.addServlet(servlet, API_ANY_PATH); // Jersey
server.addServlet(configServlet, "/configs");
server.addServlet(new SecretProvidersConfigServlet(...),
"/configs/secrets/providers");
server.addServlet(new HealthAliasServlet(), "/health/*");
server.addServlet(new HealthAliasServlet(), "/health.html");
server.addFilter(new RequestContextFilter(), API_ANY_PATH);
server.addFilter(new HttpAuditFilter(...), API_ANY_PATH);
server.addCustomFilters(API_ANY_PATH);
server.addFilter(new VersioningFilter(), API_ANY_PATH);
server.addSystemFilters(API_ANY_PATH);
```
Every filter takes `API_ANY_PATH`. None of the four servlet paths is under
it.
## Instances
`ConfigServlet` at `/configs`. Ships today. Public access is intended, but
the
response content is not filtered by any policy and currently includes the
service-admin list. Tracked separately.
`SecretProvidersConfigServlet` at `/configs/secrets/providers`. On main
only, so
it does not ship in 1.3. It returns the name, type and URI of every
configured
secret provider. Its javadoc states that it uses the same auth model as
`ConfigServlet` with no additional privilege check. The comparison is
incomplete:
`ConfigServlet` publishes a set an operator can extend through
`gravitino.server.visibleConfigs`, whereas this servlet publishes the entire
provider registry with no operator control and no way to disable it. On an
install using an external secret manager the URIs identify internal Vault or
OpenBao endpoints, and the request is not audited.
`HealthAliasServlet` at `/health/*` and `/health.html`. Public by intent and
correct as it stands.
## Effect on existing coverage claims
A REST contract probe over the 242 endpoints found by scanning `@Path`
annotations reported no unauthenticated access anywhere. That result was
measured
entirely under `/api/*`. Servlet-registered endpoints carry no `@Path`, so
they
were never in the inventory, and a filter bound to `/api/*` returns 401 for
any
path beneath it whether or not a resource exists there. The earlier finding
should be read as authentication is enforced under `/api/*`, and as saying
nothing about paths outside it.
## Requirement
Filter coverage is enforced structurally rather than by convention. Either
every
servlet is mounted under a pathspec the filter chain covers, or each
root-mounted
servlet declares itself public and a test asserts that every path passed to
`addServlet` is either covered by the filter chain or named in an explicit
public list.
Audit is a compliance requirement for our enterprise customers, so an
endpoint
that answers without appearing in the audit log is a gap independent of what
it
returns.
A test of that shape would have caught both instances above before they were
written, and it is the same control missing from the metadata authorization
allowlist.
## Scope
`apache/gravitino`. The `ConfigServlet` instance ships in 1.3 and the
enterprise
tree inherits it. The secrets servlet is on main and should be corrected
before
it ships.
--
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]