nevzheng commented on PR #12531:
URL: https://github.com/apache/gravitino/pull/12531#issuecomment-5401562078
## Design: HTTP service-identity fallback (`--no-service-identity-fallback`)
### Problem
In HTTP transport, an incoming MCP request **without** an `Authorization`
header does not run as anonymous. It falls back to the **service identity**
configured via OAuth client-credentials or `--token`. That behavior predates
this PR (it was the same with a static `--token`).
OAuth client-credentials makes the risk worse: the service identity
**auto-refreshes** and stays valid for a long time. If the MCP HTTP endpoint is
reachable by more than one caller, anyone who omits `Authorization` is
authenticated to Gravitino as the **service principal** and inherits its grants.
### Current state
| Transport | No `Authorization` header | Service OAuth / `--token`
configured |
|-----------|---------------------------|--------------------------------------|
| **stdio** | Uses service identity (required — no HTTP request exists) |
Yes |
| **HTTP** | Falls back to service identity | Yes |
| **HTTP** | Per-request header present | Caller identity wins |
Implementation: `GravitinoContext.rest_client()` returns `_default_client`
when `_get_request_authorization()` is empty (`context.py`).
### Gap
Docs described fallback but did not **warn** that anonymous-looking HTTP
calls are actually privileged. There was no **opt-in strict mode** for exposed
HTTP deployments (Qi review summary on this PR).
### Mitigation
**Shipped in `3e7a6d4cc` (warnings):**
- Docs security callout under “Per-request identity (HTTP)”
- Startup `WARNING` when HTTP starts with OAuth or `--token` configured
**Implementing next (this comment):**
| Surface | Value |
|---------|--------|
| CLI | `--no-service-identity-fallback` |
| Env | `GRAVITINO_NO_SERVICE_IDENTITY_FALLBACK` (`1` / `true` / `yes`) |
| Default | `false` (backward compatible) |
**Semantics (HTTP only):**
```
IF stdio:
→ flag ignored; service identity still used
ELIF HTTP request AND no Authorization AND flag=true AND (OAuth or --token):
→ reject at MCP (do not use _default_client)
ELSE:
→ existing behavior
```
- **stdio + flag:** ignored (logged at INFO), never an error — Cursor/oauth
env must keep working.
- **HTTP + flag + no service identity:** no-op (nothing to fall back to;
stays anonymous).
- **HTTP + flag + service identity + no header:** fail closed.
**When to enable:** shared or production HTTP endpoints where every caller
must supply its own `Authorization`. **When to leave default:** stdio,
localhost HTTP, single trusted client.
Follow-up commit will reference this comment.
Nevin
Sent from my 🤖 (Cursor)
--
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]