Andrea Cosentino created CAMEL-26872:
----------------------------------------
Summary: camel-opa - manage security policy evaluators across
context shutdown and restart
Key: CAMEL-26872
URL: https://issues.apache.org/jira/browse/CAMEL-26872
Project: Camel
Issue Type: Bug
Reporter: Andrea Cosentino
Assignee: Andrea Cosentino
Fix For: 4.24.0
OpaSecurityPolicy does not hand its evaluator's cleanup to CamelContext
shutdown, despite the intention documented in beforeWrap().
*Current behavior and cause*
* OpaSecurityPolicy.beforeWrap() creates and caches an OpaPolicyEvaluator, then
calls route.getCamelContext().addService(evaluator).
* OpaPolicyEvaluator does not implement org.apache.camel.Service.
OpaRestEvaluator and OpaWasmEvaluator implement AutoCloseable only.
* AbstractCamelContext.addService() delegates to
InternalServiceManager.doAddService(). Its lifecycle registration and
deferred-start logic run only for objects implementing Service. Passing this
evaluator therefore does not register its close() method.
* The policy-owned REST HTTP transport is not explicitly closed on context
shutdown. The WASM instance pool is not closed either. This is a component
lifecycle/resource-ownership bug; the pool-race fix in CAMEL-26830 / PR #29633
should remain separate.
*Reproduction / regression-test outline*
# Configure an OpaSecurityPolicy with a component-owned REST client (no
injected opaClient), healthCheckEnabled=false, and a local OPA-compatible HTTP
fixture; guard a route with .policy(policy).
# Start the CamelContext and send an allowed exchange.
# Stop the context and verify that the owned evaluator/transport was closed
exactly once. Currently it is not registered as a managed Service and close()
is not called.
# Restart the same CamelContext and policy instance; the route must authorize
again using fresh owned runtime resources.
# Cover the equivalent WASM policy with a valid generated module, checking pool
closure and successful evaluation after restart.
*Restart pitfall*
Simply registering an adapter that calls close() on stop is insufficient.
beforeWrap() only builds the evaluator when evaluator == null, so restart
otherwise retains a closed pool/transport. Clearing only evaluator is also
insufficient in REST mode: buildEvaluator() stores the internally-created
client in the configurable opaClient field. A subsequent build sees opaClient
!= null, reuses that already-owned/closed client, and creates a new
OpaRestEvaluator with no transport ownership. Distinguish injected
configuration from internally-owned runtime state, or reset the owned client
and related state correctly when rebuilding.
*Acceptance criteria*
* Context shutdown releases owned REST transports and WASM pools exactly once;
repeated stop/close remains safe.
* Stop/start of the same context and policy bean rebuilds functional owned
runtime resources, including the cached-owned-REST-client case above.
* A policy shared by multiple routes keeps working when one route stops while
another still uses it; lifecycle ownership does not close shared resources
prematurely.
* Distinct policies/routes have independent ownership: stopping or replacing
one cannot close another policy's runtime.
* An explicitly injected opaClient remains caller-owned and is not closed or
silently replaced by policy shutdown/restart.
* Startup failure cleans up any already-created owned resources; lifecycle
hooks do not accumulate duplicate registrations.
* Tests exercise real route/processor lifecycle with deterministic close
assertions and an in-place context restart, using Awaitility/latches where
needed instead of sleeps.
*Related work*
CAMEL-24751 introduced guarded-processor reference counting for readiness-check
registration. Preserve that behavior. Coordinate this fix with CAMEL-26836:
stopping a reload watcher is not equivalent to closing its owned evaluator and
pool. Reloadable evaluators need the same lifecycle/restart guarantees.
Observed during review of https://github.com/apache/camel/pull/29633. Validated
against the current lifecycle dispatch and policy source; no new runtime
reproduction or Maven run was performed for this follow-up analysis.
_Codex on behalf of oscerd_
Generated by Codex via OSS Helper
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)