Hi David,

One more bit of history that may help scope PIP-489: FIPS / BouncyCastle-FIPS 
support in Pulsar has been partial and handled case by case in the past, rather 
than as a coherent, tested capability -- which is a big part of why a proper 
end-to-end FIPS design is worth doing.

Two concrete examples:

1. Pulsar has never actually used BouncyCastle's JSSE (TLS) provider. A 
pulsar-site correction (https://github.com/apache/pulsar-site/pull/974) removed 
a docs statement that implied otherwise, noting "Pulsar does not implement 
bouncy castle jsse; there is no dependency on bc jsse in Pulsar." So even with 
the BC-FIPS jars on the classpath, the TLS transport did not route through a 
BouncyCastle/FIPS TLS provider -- the FIPS story for the transport itself was 
never wired.

2. On the message-encryption side, https://github.com/apache/pulsar/pull/23122 
switched AES-GCM in MessageCryptoBc from the BouncyCastle provider to SunJCE 
for performance. In reviewing it 
(https://github.com/apache/pulsar/pull/23122#pullrequestreview-2218133922) I 
raised the FIPS concern -- when the FIPS library is enabled, SunJCE should not 
become the default -- and the finding was that the existing code already 
ignored the presence of BouncyCastleFipsProvider. In other words FIPS 
compliance was already a separate, not-fully-handled concern rather than 
something the crypto paths consistently respected.

The takeaway is that FIPS support in Pulsar has been incomplete and piecemeal: 
the TLS transport was never routed through a FIPS provider, and the crypto 
paths didn't consistently honor the FIPS provider when it was present. That's 
exactly the gap worth closing, and it splits naturally: PIP-478 covers the 
TLS-transport slice (a configurable engine plus any JCA provider via 
TlsPolicy.jcaProvider, and the PulsarTlsFactory plugin for HSM-backed / FIPS 
140-3 Level 3 cases), and PIP-489 can cover the broader FIPS-mode concerns -- 
FIPS-approved algorithms in message encryption and authentication, packaging, 
and a fail-fast validation switch -- so the crypto paths consistently respect 
FIPS rather than silently falling back to non-validated providers.

Thanks,

Lari

On 2026/07/06 17:40:16 david kjerrumgaard wrote:
> Hi Pulsar community,
> 
> I'd like to start the discussion on PIP-489: FIPS 140-3 compliance mode for
> Apache Pulsar. PIP PR: https://github.com/apache/pulsar/pull/26155
> 
> Summary:
> 
> Pulsar is already FIPS-capable at the JCA layer — SecurityUtility resolves
> the BouncyCastle vs. BC-FIPS provider reflectively — butthere is no
> supported FIPS deployment path. A full audit of master found the gaps this
> PIP addresses:
> 
> 1. The BC/BC-FIPS swap lost its packaging story in the Gradle migration;
> the server distribution bundles non-FIPS BC and explicitlyexcludes bc-fips.
> 
> 2. The broker binary listener never wires the existing tlsProvider setting,
> so PEM TLS is hardwired to Netty's default, which is
> 
> 
>    -   The BC/BC-FIPS swap lost its packaging story in the Gradle
>    migration; the server distribution bundles non-FIPS BC and explicitly
>    excludes bc-fips.
>    - The broker binary listener never wires the existing tlsProvider
>    setting, so PEM TLS is hardwired to Netty's default, which is BoringSSL
>    (netty-tcnative is an unconditional dependency). The web/websocket/worker
>    listeners have the same gap; the proxy wires it correctly.
>    - Conscrypt (non-FIPS) is the shipped webServiceTlsProvider default.
>    - Several security paths use non-approved algorithms: SHA-1-based
>    RSA-OAEP and ECIES in MessageCryptoBc (ECIES is absent from BC-FIPS
>    entirely, and the class compile-imports org.bouncycastle.jce.* so it
>    fails to load on a FIPS classpath), MD5-crypt/DES-crypt in
>    AuthenticationProviderBasic, and a non-HMAC SHA-512 construction in
>    SaslRoleTokenSigner.
>    - The existing bcfips test module only validates the JCA provider swap,
>    not the TLS transport, and there is no FIPS documentation.
> 
> 
> The proposal defines FIPS mode as a deployment profile, not a fork: TLS
> provider wiring for every listener, a FIPS distribution variant (or
> documented jar-swap with first-class Gradle wiring), a fipsMode fail-fast
> startup validator, a metadata-negotiated migration to RSA_OAEP_SHA256
> key wrapping (with ECDH+KDF+AES-KW replacing ECIES in a later phase),
> SHA-2-crypt support for Basic auth, a dual-verify HMAC migration for the
> SASL role-token signer that survives rolling upgrades, a name-stable fix
> for the SHA-1-derived Kubernetes resource names, and a real FIPS TLS
> integration test group. Implementation is phased; each phase is
> independently shippable, and all shipped defaults are unchanged.
> 
> Three companion quick-win PRs are already open and intentionally outside
> the PIP: #26152 (MD5 NAR/archive checksums to SHA-256), #26153 (SHA-1
> reader subscription names to SHA-256), #26154 (client TLS/crypto helper
> fixes for FIPS-restricted JVMs).
> 
> Two open questions flagged in the document for this thread:
> 
>    - Whether the phase-2 FIPS distribution variant should be published to
>    dist.apache.org or provided as a build recipe only (release-management
>    question).
>    - Whether to eventually revisit the Conscrypt web-TLS default once JDK
>    TLS performance is re-benchmarked on modern JVMs (deferred in this PIP).
> 
> 
>  Looking forward to your feedback.
> 
>   Thanks,
>   David Kjerrumgaard
> 

Reply via email to