[Subtask] Do not run anonymous Lance REST requests as the service user when authorization is enabled
- Dominant language
- Java
- Stars
- 3.2k
- Forks
- 935
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 298
Description
### Describe the subtask
In auxiliary mode, `LanceServiceIdentityFilter` (registered only when `auxMode` is true, `LanceRESTService.java:147`) replaces an `anonymous` principal with the configured service user (`gravitino.lance-rest.gravitino-simple.user-name`, default `lance-rest-server`) before the request reaches the in-process dispatchers.
An `anonymous` principal can only be produced by the `simple` authenticator: `SimpleAuthenticator.supportsToken` accepts a missing header and `authenticateToken` returns `ANONYMOUS_PRINCIPAL` for a missing, blank, non-Basic or malformed header instead of `null`, so `AuthenticationFilter` never returns 401 under `simple`. Every other authenticator (`oauth2`, `kerberos`, idp-basic) rejects a missing credential with 401 and the filter's branch is never reached.
With `gravitino.authenticators = simple` and `gravitino.authorization.enable = true`, the combination is a privilege escalation: without the filter, `BaseMetadataAuthorizationMethodInterceptor` would reject `anonymous` with 403 at `checkCurrentUser` (anonymous is not a metalake user); with it, the unauthenticated request runs with whatever privileges `lance-rest-server` holds. #12954 documents that the fallback user needs the privileges the operation requires, but not that the fallback turns an unauthenticated request into an authorized one.
The standalone side of this was closed by #12984: `LanceCallerTokenProvider` rejects `anonymous` with 401 in the default `caller` mode. The auxiliary filter is untouched by that PR and is a separate code path.
### How should we improve?
The filter exists so an auxiliary deployment that has not configured authentication still works. That intent is compatible with two fixes; either is enough:
1. Only install `LanceServiceIdentityFilter` when `gravitino.authorization.enable` is false. When authorization is on, an anonymous request should be denied like any other unknown user, matching what the interceptor would do on its own.
2. Keep the filter but make the fallback opt-in (for example `gravitino.lance-rest.anonymous-fallback = false` by default), so a deployment has to state that it wants unauthenticated requests to run as the service user.
Option 1 is smaller and needs no new configuration key. Either way, the documentation in `docs/lance-rest-service.md` should state plainly that `simple` performs no authentication, that `anonymous` is its artifact, and what the fallback does when authorization is enabled.
### Parent issue
#13090
Contributor guide
Research direction
Start with LanceRESTService.java:147 and the LanceServiceIdentityFilter path, then trace how authorization.enable and the simple authenticator handle anonymous requests. Update the behavior so authorization-enabled requests are denied rather than mapped to the service user, and revise docs/lance-rest-service.md to explain simple authentication and the fallback. Verify both authorization-enabled denial and the existing auxiliary behavior when authorization is disabled.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- authorization, backend-api-design, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100