markhoerth opened a new issue, #12255:
URL: https://github.com/apache/gravitino/issues/12255
### Version
main branch
### Describe what's wrong
## Describe what's wrong
The Lance REST service constructs its `GravitinoClient` with no
`AuthDataProvider`, so the requests it makes to the Gravitino server carry no
`Authorization` header.
`GravitinoLanceNamespaceWrapper.initialize()`:
```java
this.client =
GravitinoClient.builder(uri)
.withMetalake(metalakeName)
.withClientConfig(clientProperties)
.build();
```
There is no configuration property to change this. `LanceConfig` defines
only `namespace-backend`, `gravitino-metalake`, and `gravitino-uri`.
Two consequences follow, depending on how `gravitino.authenticators` is set
on the Gravitino server.
**With `simple`.** `SimpleAuthenticator.supportsToken(null)` returns `true`
and `authenticateToken(null)` returns `ANONYMOUS_PRINCIPAL`, so the requests
are accepted. Every Lance operation executes in Gravitino as the anonymous user
rather than as any identity attributable to the service.
**With `oauth2` or `kerberos`.** `OAuth2TokenAuthenticator.supportsToken`
requires a Bearer prefix and returns `false` for a null token. No configured
authenticator accepts the request, so `AuthenticationFilter` throws and every
Lance operation fails.
Because `gravitino.authenticators` is a single server-wide list, there is no
per-service override. The only configuration in which the Lance REST service
works alongside OAuth2 is one that also lists `simple`, and in that
configuration any caller of the Gravitino server who omits the `Authorization`
header is likewise accepted as anonymous. The authentication documentation
already identifies that pattern as unsafe for Basic auth, where it states that
`gravitino.authenticators` must include `basic` and must not include `simple`.
| `gravitino.authenticators` | Lance REST service | Other callers of the
Gravitino server |
|----------------------------|---------------------------------|----------------------------------------|
| `simple` | Works, as anonymous |
Authenticated, or anonymous if no header |
| `oauth2` | Every operation fails |
Authenticated |
| `oauth2,simple` | Works, as anonymous | Anonymous
accepted for any caller omitting the header |
The net effect is that the Lance REST service is unusable in a deployment
with authentication enforced, and usable only in a deployment that accepts
anonymous requests.
The Iceberg REST service does not have this problem. It exposes
`gravitino.iceberg-rest.gravitino-auth-type` with `simple` and `oauth2` values
and a service user name defaulting to `iceberg-rest-server`, and as an
auxiliary service it uses internal interfaces rather than HTTP, so it does not
make this call at all.
### Error message and/or stacktrace
With `gravitino.authenticators = oauth`, any Lance REST operation returns a
500 and the server logs:
```
org.apache.gravitino.exceptions.UnauthorizedException: The provided
credentials did not support
at
org.apache.gravitino.server.authentication.AuthenticationFilter.doFilter(AuthenticationFilter.java:...)
```
The relevant code paths:
- `GravitinoLanceNamespaceWrapper.initialize()` builds the client with
`authDataProvider` unset.
- `AuthenticationFilter.doFilter` iterates the configured authenticators and
throws `UnauthorizedException("The provided credentials did not support")` when
none returns a principal.
- `SimpleAuthenticator.supportsToken` returns `true` when `tokenData ==
null`; `authenticateToken(null)` returns `ANONYMOUS_PRINCIPAL`.
- `OAuth2TokenAuthenticator.supportsToken` returns `false` when `tokenData
== null`.
### How to reproduce
Gravitino version: main branch.
1. Configure the Gravitino server for OAuth2 per [How to
authenticate](https://gravitino.apache.org/docs/latest/security/how-to-authenticate),
so that `gravitino.authenticators = oauth` with no `simple` entry.
2. Enable the Lance REST service as an auxiliary service:
```properties
gravitino.auxService.names = lance-rest
gravitino.lance-rest.classpath = lance-rest-server/libs
gravitino.lance-rest.namespace-backend = gravitino
gravitino.lance-rest.gravitino-uri = http://localhost:8090
gravitino.lance-rest.gravitino-metalake = test_metalake
```
3. Start the server and create a metalake named `test_metalake`.
4. Call any Lance REST operation with a valid Bearer token, so that
authentication at the Lance REST service itself succeeds:
```shell
curl -X POST http://localhost:9101/lance/v1/namespace/lance_catalog/create \
-H "Authorization: Bearer ${VALID_TOKEN}" \
-H 'Content-Type: application/json' \
-d '{"id": ["lance_catalog"], "mode": "create"}'
```
The call fails. The service authenticated the caller and then made its own
unauthenticated request to the Gravitino server, which rejected it.
5. Add `simple` to `gravitino.authenticators`, restart, and repeat. The call
now succeeds, and a request to the Gravitino server with no `Authorization`
header at all also succeeds as anonymous.
### Additional context
Two related gaps are out of scope for this issue and worth tracking
separately.
**Caller identity is not forwarded.** Even once the service authenticates to
Gravitino under its own identity, it does not act on behalf of the caller, so
Gravitino privileges cannot be evaluated per caller on the Lance path. The
Iceberg REST service supports access control in auxiliary mode by sending the
authenticated user identity to the Gravitino server for authorization.
Achieving the same for Lance is a larger change of the same shape as the user
forwarding added to the Trino connector.
**Credential vending is not wired into the Lance path.** Storage access is
configured with static `lance.storage.*` properties and the resolved values,
including access keys and secrets, are returned to clients in the
`storageOptions` of `CreateTable` and `DescribeTable` responses. Neither the
Lance REST service nor the Generic Lakehouse catalog requests vended
credentials, so short-lived scoped credentials are not available on either
Lance path.
A fix for the issue described above is prepared and adds
`gravitino.lance-rest.gravitino-auth-type` with `simple` and `oauth2` support,
mirroring the Iceberg REST service properties and defaulting to `simple` with
the user name `lance-rest-server` so that existing deployments are unaffected.
--
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]