[Java][Go] Add first-class external-IdP (Entra ID) token federation

未关闭
#1,069 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 4 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
35/100
Issue 类型
功能
描述清晰度
基本清楚
活跃度
活跃
技术栈
go, java, rust

调研方向

Read the Rust core’s FederatedTokenProvider and IdpTokenSupplier implementation from #760, then trace the Java JNI and Go cgo binding layers. Add callback bridging and supplier identity handling in both bindings, with tests for account and workload federation, caching, invalidation, and callback errors. Done means both SDKs pass those unit tests and include a README section and example; live gRPC validation against a real workspace is also in the testing plan.

由索引模型根据 Issue 内容生成。

描述

SDK

Java and Go

Description

Summary

Follow-up to #740: extend first-class external-IdP (for example Microsoft Entra ID)
token federation to the Java and Go (cgo) SDKs. The feature shipped in Rust
2.11.0 and Python 1.10.0 (#760), and these two SDKs are next by usage. The native
Pure Go SDK (purego/) is out of scope here: it has its own OAuth stack, so it
would need a separate implementation.

Same feature as #740: the caller supplies a callback that returns the current
external IdP token. The SDK exchanges it for a Zerobus-scoped Databricks token
using the RFC 8693 token-exchange grant, then caches and refreshes it the same way
the existing OAuth client-credentials path does. The Zerobus service does not change.

Motivation

Enterprise customers who can't use Databricks-managed OAuth secrets today work
around it on Java and Go by hand-rolling the exchange inside a custom
HeadersProvider. That means each team re-implements the request shaping (the
zerobusDirectWriteApi resource and table-scoped authorization_details), the
caching and the refresh. Rust and Python callers no longer have to do this, and
Java and Go callers shouldn't have to either.

Both modes from #740 are in scope:

  1. Account-level federation:
    no client_id. The subject resolves to the SCIM-synced identity.
  2. Workload identity federation:
    a service principal client_id with no secret, and a federation policy attached.

Design

Both SDKs wrap the Rust core: Java through JNI and Go (cgo) through the C FFI. So
the token exchange, request shaping, token cache, proactive refresh and
invalidate() handling are reused from the Rust core as-is (the
FederatedTokenProvider / IdpTokenSupplier from #760). This work is mostly
binding-layer work:

  • Rust JNI / FFI layers: expose the federated provider, with a language
    callback bridged as the IdP token supplier. Errors raised in the callback
    propagate back as SDK auth errors.
  • Supplier identity: keep the stable identity-string cache key design from
    #760, keyed on (client_id-or-none, table) plus supplier identity. Do not key
    on callback pointers or handles, because addresses can be reused after
    release.
  • Callback, not a bare token (same reasoning as #740): IdP tokens are
    short-lived, so a static token would strand the stream when it expires. Callers
    that hold a static token can wrap it in a trivial callback.

Backward compatibility

Purely additive and opt-in, same as #740.

Testing plan

  • Unit tests in each binding: both modes, the callback is called only on a cache
    miss or refresh, invalidate(), callback-error propagation, and independent
    caching per mode and per service principal.
  • Live end-to-end validation of both modes on gRPC against a real workspace
    (Entra ID), including a run over a full token lifetime to show auto-refresh.
  • README section and an example per SDK.

Related

  • #740 (design and tracking issue for Rust/Python), #760 (implementation)
  • Public docs: Zerobus federation section (already published)

I will proceed to open the PR(s) against this issue.

Proposed Solution

Java: a FederatedToken auth option on the stream builder that takes a
callback (Supplier<String>, plus an async Supplier<CompletableFuture<String>>
variant) and an optional clientId.

Go: an option on stream creation that takes
func(ctx context.Context) (string, error) and an optional client ID.

The existing client-credentials and custom HeadersProvider paths are
unchanged.
The above is open for discussion once the PR is created

Additional Context

No response

主要语言
Rust
星标
95
派生
36
平均合并
4 天 7 小时
30 天内合并 PR
46

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

databricks/zerobus-sdk 的其他 Issue

查看 databricks/zerobus-sdk 的全部 Issue

相似的 Issue

更多 Rust Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。