Repository navigation
CAMEL-25795: camel-pqc - stopping an endpoint no longer removes the Bouncy Castle providers from the JVM - #28089
Conversation
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
gnodet-bot
left a comment
There was a problem hiding this comment.
Minor test resilience note (low severity).
This review was generated by an AI agent, Hermès on behalf of @gnodet.
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review after new commits: the fix is correct. Removing the doStop() override that was tearing JVM-global Bouncy Castle providers out from under sibling endpoints and other code is the right approach — providers registered by other components or by static initializers should not be evicted on endpoint stop. The test exercises the exact race path described in the bug. One minor Javadoc nit below.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
davsclaus
left a comment
There was a problem hiding this comment.
Thanks @oscerd. Removing doStop() is the right call: Security is JVM-global, and the endpoint removed providers it had not installed, so the pqc:sign + pqc:verify pair of the docs could break itself. The camel-as2 and camel-crypto-pgp precedent and the upgrade-guide entry cover the behaviour change.
One small note, non-blocking: in stoppingOneEndpointLeavesTheOtherUsable the sendBody("direct:b", ...) most likely also succeeds on main, as the signer of endpoint b already holds its Signature instance. The test fails on main through the getProvider assertion, so it still guards the fix, the name just promises a bit more than the send checks.
The gnodet-bot <p/> nit is still open; fine either way, <p/> is common in the code base.
Claude Code on behalf of Claus Ibsen
gnodet-bot
left a comment
There was a problem hiding this comment.
Following up on my earlier review — the route-ID fix (✅) and the test rename (✅) are both in. One nit remains open: the <p/> in the doStart() Javadoc.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
|
Thanks @davsclaus. You are right that the send succeeds on main too — the surviving endpoint already holds its own On the Claude Code on behalf of @oscerd |
davsclaus
left a comment
There was a problem hiding this comment.
Re-reviewed the new commit: the second test is now named for what it pins (the provider stays registered for the other endpoint), and the comment says why. LGTM.
The two gnodet-bot threads on the <p/> in the PQCEndpoint javadoc are still open; <p> would settle them.
Claude Code on behalf of Claus Ibsen
|
🧪 CI tested the following changed modules:
🔬 Scalpel shadow comparison — Scalpel: 8 of 707 tested, 26 compile-only — current: 8 all testedMaveniverse Scalpel detected 8 affected modules (current approach: 8). Skip-tests mode would test 8 modules (2 direct + 7 downstream), skip tests for 26 (generated code, meta-modules) Modules Scalpel would test (8)
Modules with tests skipped (26)
All tested modules (35 modules, 5m 25s total)Total reactor time: 5m 25s
Top 20 slowest modules:
|
…ouncy Castle providers from the JVM PQCEndpoint.doStop() unconditionally removed the BC and BCPQC providers from java.security.Security, which is JVM-global. doStart() only adds a provider when it is absent, so an endpoint routinely removed one it had not installed - tearing it out from under the sibling pqc endpoint of the same route, other CamelContexts, camel-crypto/camel-ssh/camel-xmlsecurity, and all non-Camel code in the same JVM. Per-endpoint ownership tracking does not fix this: endpoint A adds the provider, endpoint B sees it present and skips, then A stops and removes it, breaking B. Since Security records no ownership, the providers are now simply left registered, which is what camel-as2, camel-crypto-pgp and this component's own statically initialised PQCDefault*Material classes already do. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…ycle test Relying on the auto-generated "route1" id would break silently if Camel's default naming scheme ever changed. The routes now carry explicit ids, which also reads better at the stopRoute call. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…it pins The send to the surviving route succeeds on main too, since that endpoint already holds its own Signature. What the test actually guards is the provider still being registered, so the name and a comment now say that. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…g <p/> in the PQCEndpoint javadoc javadoc doclint rejects the self-closing form. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
|
Rebased onto
Verification: camel-pqc on JDK 21 ( Claude Code on behalf of oscerd |
9555d23 to
333577d
Compare
gnodet-bot
left a comment
There was a problem hiding this comment.
✅ LGTM — The fix is correct and well-tested.
The doStop() removal is the right minimal change: since Security.addProvider() is JVM-global, removing providers on endpoint stop would break sibling endpoints sharing the same Bouncy Castle providers. Both test scenarios (stoppingTheContextKeepsTheProvidersRegistered and stoppingOneEndpointLeavesTheProviderForTheOther) correctly validate this behavior. The upgrade guide entry accurately documents the behavioral change.
Minor polish already in place: explicit routeId("a")/routeId("b") pinning prevents test brittleness, and the <p/> → <p> javadoc fix is correct.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
davsclaus
left a comment
There was a problem hiding this comment.
LGTM, thanks. The rebase only moves the upgrade-guide note, and 333577d changes <p/> to <p>.
One thing about merge order: this branch and #28094 (and #28099, which contains #28094's commits) still conflict in the 4.24 upgrade guide, whichever is merged first. The cause is on the #28094 side: two of its paragraphs were left at the end of the camel-pqc - an unknown hybridKdfAlgorithm is rejected section, which is exactly where this note goes. Details are on #28094. Once they are moved there, all of these merge cleanly in any order.
Claude Code on behalf of davsclaus. This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Fixes CAMEL-25795.
Problem
PQCEndpoint.doStop()unconditionally removed theBCandBCPQCproviders fromjava.security.Security:doStart()only adds a provider when it is absent, so an endpoint routinely removed one it had not installed.java.security.Securityis process-global, so this tears the provider out from under:pqcendpoint of the same route — the canonicalpqc:sign+pqc:verifypair in this component's owndocumentation breaks itself, since stopping one de-registers BC for the other;
CamelContextinstances in the same JVM;After the removal, every
Signature.getInstance(..., "BC")fails withNoSuchProviderException. The removal can alsorace with another thread that is mid-operation.
CAMEL-22016 added the null guards but did not address provider ownership.
Fix
The providers are now left registered. Per-endpoint ownership tracking does not solve this — endpoint A adds the
provider, endpoint B sees it present and skips, then A stops and removes it, breaking B.
Securityrecords noownership and there is no reference counting across endpoints or across the JVM.
Leaving them registered is also what the rest of the codebase already does:
camel-as2,camel-crypto-pgpand thiscomponent's own 21 statically-initialised
PQCDefault*Materialclasses all register BouncyCastle and never remove it.PQCEndpointwas the only place in the entire repository that removed a BouncyCastle provider.The now-empty
doStop()override is removed, and the rationale is recorded ondoStart().Tests
New
PQCEndpointProviderLifecycleTest:stoppingTheContextKeepsTheProvidersRegistered— both providers are still registered aftercontext.stop();stoppingOneEndpointLeavesTheOtherUsable— a siblingpqcendpoint still works after the first one is removed.Both tests fail on
mainand pass with this change. Fullcamel-pqcmodule build is green: 241 tests, 0 failures,no regenerated-file drift.
Note for reviewers
Nearly every existing test in this module carries a
Security.addProvider(new BouncyCastleProvider())in@BeforeAll.That workaround exists precisely because of this bug. Those blocks are now redundant, but removing ~90 of them is out
of scope here — it is folded into CAMEL-25802.
Upgrade guide
Added a 4.24 entry: an application that relied on the providers being de-registered on shutdown must now remove them
itself.
Reported, analysed and fixed by Claude Code (AI agent) on behalf of @oscerd.
🤖 Generated with Claude Code