Skip to content

Support impersonation via SASL/PLAIN authorization id #3837

Description

@beryllw

Search before asking

  • I searched in the issues and found nothing similar.

Motivation

Middle-tier services (gateways, web consoles, query services) often connect to Fluss with their own service credentials but need to run operations on behalf of end users, so that ACLs are evaluated against the end user rather than the service account. This "impersonation" (a.k.a. doAs / proxy user) capability is standard in comparable systems: Hadoop proxy user, Hive doAs, Pulsar originalPrincipal, Trino impersonation.

The SASL/PLAIN protocol (RFC 4616) already carries this semantic natively via the optional authorization id:

message = [authzid] UTF8NUL authcid UTF8NUL passwd

Fluss currently parses the authorization id in PlainSaslServer.evaluateResponse() but unconditionally rejects any value different from the authenticated username, and the client hard-codes it to null in SaslServerFactory.createSaslClient(). The rest of the plumbing is already in place: SaslServerAuthenticator.createPrincipal() builds the principal from saslServer.getAuthorizationID().

Solution

Enable the RFC 4616 authorization id end-to-end, gated by an explicit server-side allowlist. No wire protocol change, no new SPI.

Client: new config option client.security.sasl.authorization-id (String, no default). When set, it is passed to Sasl.createSaslClient(...) and the JDK PlainClient encodes it per RFC 4616. When unset, the bytes on the wire are identical to today.

Server: allow authzid != authcid only if granted via a JAAS option on PlainLoginModule, consistent with the existing user_<name> style:

security.sasl.plain.jaas.config: |
  org.apache.fluss.security.auth.sasl.plain.PlainLoginModule required
    user_admin="admin-pass"
    user_gateway="gw-pass"
    user_alice="alice-pass"
    impersonate_admin="*"                # admin may impersonate any user
    impersonate_gateway="alice,bob";     # gateway may only impersonate alice/bob
  • If the check passes, the effective principal becomes the authorization id, and an INFO log records the impersonation for auditing. All downstream ACL checks apply to the effective principal, matching the existing createPrincipal() behavior.

  • If impersonate_<authcid> is not configured, the request is rejected exactly as today — fully backward compatible, and impersonation cannot be enabled from the client side alone.

  • The impersonator must still present its own valid password; the authorization id does not weaken authentication. Docs will keep the existing recommendation to use TLS with SASL/PLAIN.

Out of scope (possible follow-ups, would need a FIP): exposing original/effective principal on Session, an IMPERSONATE ACL operation type, and impersonation for future non-PLAIN mechanisms.

Anything else?

No response

Willingness to contribute

  • I'm willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions