raghav-reglobe opened a new pull request, #67672:
URL: https://github.com/apache/doris/pull/67672
### What problem does this PR solve?
Issue Number: close #67506
Related PR: #63239 (reserved the `current_roles` / `is_su_user` thrift ids
this PR uses), #67444 (the same identity-in-request pattern for `mysql.user`)
Problem Summary:
A multi-tenant middle tier — an AI or BI gateway, an MCP server, an
embedded-analytics backend — can't make Doris enforce the *end user's*
entitlements, nor attribute the query to that person. Its choices today are one
shared service account (no per-person audit, app-level authz) or holding every
person's password and getting their full role union. What it needs is what
MySQL's `PROXY` privilege and Oracle's `CONNECT THROUGH` give: authenticate as
the service, then run *this session* as a named user, restricted to an explicit
subset of that user's roles.
This adds exactly that:
```sql
GRANT PROXY_PRIV ON *.*.* TO 'svc_gateway'@'%';
-- per end-user session, on the service's connection:
SU 'alice'@'%' WITH ROLES ('tenant_42', 'tenant_42_scoped') [WORKLOAD GROUP
'wg_tenant_42'];
```
- **`PROXY_PRIV`** is a new global privilege in MySQL's vocabulary (bit 15;
`ADMIN_PRIV` implies it; grantable only on `*.*.*` like
`ADMIN_PRIV`/`NODE_PRIV`; shown by `SHOW GRANTS`). It is the only gate on `SU`.
- **The role list is mandatory and only narrows.** It replaces the target's
role union for the session; every role must already be granted to the target,
so the session can never exceed the person's real authority. The person's
direct/default-role grants are not active under the switch. (The dormant-role
property the issue floated is withdrawn — with the list mandatory it isn't
needed.)
- **`current_user()` is the target**, so user-bound row policies and
`current_user()`-keyed predicates evaluate as the person; the audit log records
the person as `user`, and a new **`authenticated_user`** column/field beside it
records who actually logged in (equal to `user` unless switched).
- **Session-only, one-shot.** A second `SU` is refused;
`resetConnection()`/`COM_CHANGE_USER` revert to the authenticated identity,
never to the target's full roles; nothing is persisted.
- **`session_is_narrowed()`** (BOOLEAN, FE-folded like `current_user()`)
lets policies tell a switched session apart.
One choke point: `Auth.getRolesByUserWithLdap` returns the session override
when one is set; privilege checks, row policies and `SHOW GRANTS` follow from
that with no change to the privilege tables. The information_schema/`mysql`
read baseline is kept so clients keep working, and the narrowed session keeps
the person's own workload-group `USAGE` (placement follows the person).
**Carrying the narrowing across the FE/BE boundary.** Two kinds of work
leave the `ConnectContext` behind and were authorized against the target's full
role union: the BE→FE metadata RPCs behind `information_schema`/`mysql` tables,
the metadata table functions and processlist (name and row leaks on the handler
thread), and statements forwarded to the master. The narrowed role set now
travels as `current_roles` on the request structs that #63239 reserved the ids
for (plus `is_su_user` on `TMasterOpRequest` and `current_roles` on the
schema/metadata scan plan nodes). On the FE one helper runs each handler under
a thread-local narrowing keyed by the caller identity; the master installs the
carried set on the proxy session before executing. Fail-closed choices: a
narrowed request that names no caller is refused; a switched forward without a
role list narrows to the empty set; and because an older master would silently
ignore the fields (and a rolling upgrade upgrades the master last
), the origin refuses to forward from a narrowed session unless the master
reports the same build in its heartbeat.
Not in this PR, happy to follow up: a per-target `GRANT PROXY_PRIV ON
'alice'@'%' TO ...` form (needs a new priv table; the global form is MySQL's
`''@''` wildcard case) and a no-list `SU` that behaves like MySQL `PROXY` if
parity is preferred.
### Release note
Add `SU 'user' WITH ROLES (...)` — a session-narrowed identity switch
(MySQL-style proxy authentication with mandatory role narrowing) gated by a new
global `PROXY_PRIV`, plus `session_is_narrowed()` and an `authenticated_user`
audit column.
### Check List (For Author)
- Test
- [x] Regression test: `auth_p0/test_su_session_narrowing.groovy`
- [x] Unit Test: `SuUserNarrowingTest`, `ForwardedSessionNarrowingTest`,
`NarrowedMetadataRpcTest`, `AuditLoaderTest`, `AuditLogHelperTest`
- [x] Manual test: the whole feature has been running in production on a
2-FE / 4-BE cluster behind an MCP gateway for several days (with config
stand-ins for the gate that this PR replaces with `PROXY_PRIV`)
- Behavior changed:
- [x] Yes. New statement `SU`, new privilege `PROXY_PRIV`, new builtin
`session_is_narrowed()`, new `authenticated_user` column on
`__internal_schema.audit_log` (added through the existing schema-upgrade path)
and field in `fe.audit.log`. Existing sessions are unaffected unless they run
`SU`. Wire: new optional thrift fields only, on the reserved ids; no
metadata/editlog format change beyond the new privilege bit (an FE downgraded
below this version ignores bit 15). Rolling-upgrade note in the description
(narrowed forwards fail closed until the master is upgraded).
- Does this need documentation?
- [x] Yes. Will open the doris-website PR once the shape here is agreed
(SU statement, PROXY_PRIV, session_is_narrowed(), audit column).
### Check List (For Reviewer who merge this PR)
- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
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]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]