[feat][pip] PIP-478: Asynchronous v5 client auth plugin interfaces and TLS material provider plugin interface#25890
Open
lhotari wants to merge 10 commits into
Conversation
… and TLS material provider plugin interface
lhotari
marked this pull request as draft
June 29, 2026 21:16
Member
Author
|
The PIP will be simplified (the PulsarTlsMaterialProvider part). I haven't yet updated the PIP document. |
Updates the PIP-478 design to the current proposal: the async capability-segregated v5 client authentication SPI, the framework-managed PulsarHttpClient SPI, and the purpose-driven PulsarTlsFactory TLS SPI replacing PIP-337 (full config removal + v4-client tlsFactoryClassName successor), plus TlsPolicy.jcaProvider for JCA-provider selection and the FIPS 140-3 TLS-transport coverage.
lhotari
marked this pull request as ready for review
July 6, 2026 23:45
…gn fix) Corrects the v4 sslProvider mapping: the Netty SslProvider engine literals (JDK, OPENSSL, OPENSSL_REFCNT) stay on the engine axis; only other values are treated as a JCA provider name and routed to TlsPolicy.jcaProvider. A valid sslProvider=JDK is no longer misrouted to a non-existent JCA provider named "JDK".
…text provider) + FIPS reframe (BCJSSE) The provider that builds the SSLContext is a JSSE role; a crypto-only provider (BC-FIPS) has no SSLContext.TLS. Renamed TlsPolicy.jcaProvider to jsseProvider and reframed the FIPS story: jsseProvider=BCJSSE with BC-FIPS registered as the crypto provider it delegates to. Also reconciles the ClusterData broker-client model (per-client factory, no minted per-cluster purposes) and the removal break-summary.
…t-async-auth-and-tls-material-provider
Member
Author
|
The vote has passed and this PR PIP is waiting for a review. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
The v4 client authentication surface has five concrete, observable problems, and they are what this
PIP addresses:
ClientCnx.handleAuthChallenge()callsthe plugin synchronously on the I/O thread, so an OAuth2 token-endpoint call or an Athenz ZTS
query stalls every producer, consumer, and lookup multiplexed onto that loop.
AuthenticationDataProvideris a kitchen sink. 13 methods covering three unrelated concerns(TLS material, HTTP request auth, binary-protocol auth); every built-in implementation returns
nullorfalsefrom the methods it does not care about, and which transports a plugin actuallysupports is only discoverable at runtime.
AuthenticationOAuth2builds its ownAsyncHttpClient(and its own SSL factory) because the SPI gives it nowhere to ask the client forone — issue #24795, with PR
#24944 as the workaround.
PulsarSslConfigurationcarries anAuthenticationDataProvider, and the factory interfaceexposes rebuild choreography (
needsUpdate()/update()/createInternalSslContext()/ …) aspublic API. It is also synchronous. Operationally this blocks the deployments that most need a
plugin: those whose policy forbids storing TLS private keys in files at all — keys must stay in an
HSM/KMS or be delivered in-memory by a workload-identity system (SPIFFE/SPIRE). The same
configurability is also what makes a FIPS-compliant TLS transport practical.
ClientCnxinterleaves connect,refresh, and SASL rounds on one synchronous path, and on HTTP there is no generic multi-round
driver at all — the SASL plugin implements the
401→resubmit→200loop itself, and the admin(JAX-RS) client and the HTTP-lookup client each drive it separately, so the loop is effectively
re-implemented per HTTP client API.
Related: PIP-466 (the v5 client API
this builds on) and PIP-337 (the SSL
factory this replaces).
Modifications
Adds the design document
pip/pip-478.md. It builds on PIP-466'spulsar-client-api-v5/pulsar-client-v5and adds two small, dependency-light SPI modules —pulsar-tls-factory-apiandpulsar-http-client-api— so the sibling broker-side PIP can depend on them without importing aclient artifact. In summary, three kitchen-sink surfaces are replaced by three focused SPIs:
Authenticationinterfaceplus four narrow, opt-in capability interfaces, one per cell of a 2×2 matrix (binary vs HTTP
transport × single-pass vs challenge-response). Every credential-producing method returns a
CompletableFuture, so the event loop is never blocked, and challenge-response becomes an explicitcapability driven generically by the framework on both the binary and HTTP paths.
authentication(myAuth), wherethe framework does not call
configure(...)) and string-based (authPluginClassName+authParams, withconfigure(...)theninitializeAsync(ctx)called once — the existingAuthenticationUtil.create(...)semantics).PulsarHttpClientSPI — the framework owns event loops, timers, DNS caches,and TLS refresh; plugins describe what they need via a
PulsarHttpClientConfigand obtain aninstance from
AuthenticationInitContext.httpClientFactory()instead of building parallelinfrastructure.
PulsarTlsFactorySPI, replacing PIP-337 — decoupled from the auth SPI,asynchronous, asking a factory only for a ready-built TLS object for a given purpose, and confining
rotation to a reload callback (rebuild-not-mutate). Key material never crosses a Pulsar API, so
HSM/KMS and workload-identity integrations become first-class instead of requiring a fork of the
SSL layer.
ciphers/protocols, hostname verification, and three orthogonal provider axes: the TLS engine
(JDK vs native OpenSSL),
TlsPolicy.jsseProviderfor the JSSE provider that builds theSSLContextand the key/trust manager factories, andTlsPolicy.jcaProviderfor the JCA providerthat parses and holds the key material (
KeyStore,CertificateFactory,KeyFactory). Togetherwith the engine selection already wired through the client and every server component, that makes a
FIPS-compliant TLS transport configurable for FedRAMP/DoD/PCI-style deployments:
BCJSSE(frombctls-fips) on the JDK engine, withBCFIPS(frombc-fips) as the crypto provider. Both axesare needed — BCJSSE registers no
KeyStoreservice and BCFIPS noSSLContext, so pinning only theJSSE side leaves key material parsed outside the validated module. Deployments that must keep keys
inside a PKCS#11 HSM use a custom
PulsarTlsFactoryinstead.LegacyV4AuthenticationAdapterruns an existing v4plugin as a v5 one with its blocking I/O forced onto
ctx.blockingExecutor()(never the eventloop), and
V5ToV4AuthenticationAdapterlets a v5 plugin back the v4 client API.client API implementation — which is how the event-loop fix reaches existing v4 applications with
no source changes.
Breaking changes in 5.0 (detailed in the document): PIP-337 is removed outright — the
sslFactoryPlugin/sslFactoryPluginParams(andbrokerClient*) config keys, the v4ClientBuilder/PulsarAdminBuildermethods, theClusterDatafields, and thepulsar-admin clusters/pulsar-testclientCLI options — withtlsFactoryClassName/tlsFactoryConfigsuccessors, now on the v4 client and admin builders as well as server config, and a stale non-default
key rejected loudly at startup. TLS also becomes secure by default: hostname verification ON and
SAN-only matching (deprecated CN matching removed) — a documented breaking change, with remediation.
Out of scope: broker-side authentication (
AuthenticationProvider/AuthenticationState),deferred to a sibling PIP with the same design principles; removal of the v4
Authenticationinterface and its deprecated methods, which are retained indefinitely for source compatibility (only
their bodies are re-implemented on top of the v5 SPI — the signatures stay); non-Java SDKs, each via
its own PIP; and the broader FIPS-compliance mode (approved algorithms in message encryption and
authentication, a FIPS distribution/packaging variant, a fail-fast
fipsModeswitch) — this PIPcovers only the TLS-transport slice.
Known gap: the proxy's own broker-client credential I/O still runs inline on the proxy's Netty
loop, because its lookup path uses a bare
ConnectionPooland its data path a hand-rolledDirectProxyHandler, neither of which binds the client auth services — the same behavior as v4, nota regression, and deferred to a follow-up.
This is a documentation-only PR (the design proposal); implementation lands in separate PRs.
Links
Rendered PIP document:
https://github.com/lhotari/pulsar/blob/lh-pip-478-v5-client-async-auth-and-tls-material-provider/pip/pip-478.md
Discuss thread:
https://lists.apache.org/thread/s9n9jksr9vqgn9o982zmnnkcxdcncy3f
Vote thread:
https://lists.apache.org/thread/6n6q014236l4tstrxn9t4jbrp8xty997