Skip to content

[KYUUBI #7458] Add server-side statement interceptor SPI#7530

Open
wangzhigang1999 wants to merge 7 commits into
apache:masterfrom
wangzhigang1999:kyuubi-statement-interceptors
Open

[KYUUBI #7458] Add server-side statement interceptor SPI#7530
wangzhigang1999 wants to merge 7 commits into
apache:masterfrom
wangzhigang1999:kyuubi-statement-interceptors

Conversation

@wangzhigang1999

Copy link
Copy Markdown
Contributor

Why are the changes needed?

First half of #7458 (the statement hook; the result-set hook is a follow-up PR). Kyuubi lacks a gateway-level, per-statement hook before a statement is routed to the engine (Spark AuthZ is Spark-specific). This adds a server-side StatementInterceptor SPI, invoked for each interactive statement before operation creation and routing, that can inspect / rewrite / reject — one stable hook for authorization, risky-SQL interception, and rewriting.

  • Lives in the dependency-free kyuubi-server-plugin module, JDK types only; does not expose session conf/credentials.
  • kyuubi.operation.statement.interceptors is serverOnly (no session bypass); fail-closed on throw/null; eager init at startup.
  • Context exposes statementId() (the client's operation handle id) to correlate a statement with its later operation/result set.

Interactive path only.

How was this patch tested?

Unit (StatementInterceptionSuite, PluginLoaderSuite) and end-to-end JDBC→server→engine (StatementInterceptorSuite) covering proceed/rewrite/reject, the executeOnServer path, fail-closed, concurrency, and statementId. spotless/scalastyle/AllKyuubiConfiguration pass.

Was this patch authored or co-authored using generative AI tooling?

Assisted-by: Claude Opus 4.8

Add a user-facing English doc for the statement interceptor SPI under
docs/extensions/server and register it in the server extensions toctree.
…ptor

Pre-allocate the operation handle before interception and reuse it for the
operation instead of letting the operation self-generate one, and add
StatementInterceptContext#statementId so an interceptor can correlate the
intercepted statement with its later operation and result set. The id equals
the operation handle the client receives.
…cted statements

Expose StatementInterceptContext#realUser, the authenticated user before any
impersonation, alongside user() which is documented as the effective (proxy)
user the statement runs as, so an interceptor can authorize and audit both the
effective and the real identity.

Throw the REJECT error with SQLState 42000 (access rule violation) so JDBC and
BI clients can tell a policy rejection from a syntax error programmatically
rather than by parsing the message text.

Claude-Session: https://claude.ai/code/session_01Mco2CEWmiF95hJFVy77usj
@wangzhigang1999 wangzhigang1999 changed the title [WIP][KYUUBI #7458] Add server-side statement interceptor SPI [KYUUBI #7458] Add server-side statement interceptor SPI Jun 30, 2026
@wangzhigang1999 wangzhigang1999 marked this pull request as ready for review June 30, 2026 06:02
@wangzhigang1999

Copy link
Copy Markdown
Contributor Author

Design note — statementId

StatementInterceptContext#statementId() is the operation-handle UUID, pre-allocated before interception and reused for the operation (instead of being self-generated afterwards). So one stable id spans intercept time → operation → result set → the handle the client gets. That's the correlation/join key for end-to-end audit and lineage, and for the planned result-set transform hook (second half of #7458). It's threaded down via a defaulted ctor param through AbstractOperation/KyuubiOperation/ExecuteStatement/ExecutedCommandExec, so no engine ripple.

Also manually verified on a Kubernetes deployment: REWRITE/REJECT over Beeline (reject surfaces SQLState 42000), statementId matches the operation handle, and neither batch nor a session-level override bypasses the serverOnly interceptor.

@wangzhigang1999 wangzhigang1999 marked this pull request as draft July 3, 2026 02:42
…ommon unchanged

Inject the pre-allocated operation handle through KyuubiOperation's
`override protected val handle` constructor param and revert the
AbstractOperation constructor in kyuubi-common to its original single-arg
form. The handle stays a constructor paramaccessor so AbstractOperation's
statementId reads it during superclass initialization.

Other refinements:
- Reduce StatementInterceptContextImpl to `override val` constructor params.
- Drop the redundant defensive copies of the already read-only confOverlay
  and server conf maps; normalize null ipAddress/engineType with Option.
- Mark statementInterceptors @volatile.
- Document that engineType() returns the upper-cased kyuubi.engine.type enum
  names such as SPARK_SQL, and that batch and Data Agent REST paths are not
  intercepted.
@wangzhigang1999 wangzhigang1999 marked this pull request as ready for review July 10, 2026 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant