oscerd opened a new pull request, #27073:
URL: https://github.com/apache/camel/pull/27073
## What
With `failOpen=true`, camel-opa let an exchange through on **every** failure
to evaluate the policy. The option promises less: it should apply only when
*"the policy cannot be evaluated at all, for example because the OPA server is
unreachable"*.
The OPA Java SDK (`com.styra:opa` 2.1.1, checked in the bytecode) reports
these cases through `OPAClient.evaluate`:
| OPA's answer | how the SDK reports it | before, under `failOpen` |
|---|---|---|
| undefined decision (rule has no default and does not match) |
`OPAException` with no cause | **allow** |
| `400` | `OPAException` ← `ClientError` | **allow** |
| `401` / `403` (wrong or expired `bearerToken`), `404`, other `4xx` |
`OPAException` ← `SDKError(code)` | **allow** |
| `500`, how OPA reports an error evaluating the policy against this input |
`OPAException` ← `ServerError` | **allow** |
| connection refused / timeout | `OPAException` ← `IOException` | allow |
| `502` / `503` / `504` / `429` from a gateway | `OPAException` ←
`SDKError(code)` | allow |
The undefined case is the sharpest. It is how Rego behaves for
`opa:authz/allow` against a policy without `default allow := false`, so with
`failOpen` every input the rule does *not* match was allowed. The WASM engine
throws on an undefined rule the same way, deliberately, to match REST, so it
had the same gap. Input documents are built from the message, so a sender can
shape most of these answers.
`failOpen` is `insecure:dev` and documented as not for production, and
camel-opa is not released yet (4.23.0). So this is a bug fix before release,
not a vulnerability. It is the same class as the finding in the camel-openfga
review (#26974), where a `4xx` was also read as "no verdict" under `failOpen`.
## How
`failOpen` now applies only when the decision point was **unavailable**.
Everything else fails closed even with `failOpen` set.
- `OpaPolicyEvaluator.isDecisionPointUnavailable(Exception)`: the default is
`false`, so an engine fails closed unless it recognises its own unavailability.
It is used by single evaluation, whole-batch failure and per-element batch
failure. The fail-closed path is unchanged: every failure still fails closed
without `failOpen`.
- `OpaRestEvaluator` walks the cause chain. It returns `true` for an
`IOException` (including connect and request timeouts) and for `SDKError`
429/502/503/504. It returns `false` for `ClientError`, `ServerError`,
`AuthException`, any other `SDKError`, a cause-less `OPAException` (an
undefined decision), and a Jackson exception, which is an `IOException` of its
own and would otherwise pass for a transport failure.
- `OpaWasmEvaluator` returns `true` only for a pool `TimeoutException` (busy
past `borrowTimeout`). An undefined rule, a trap and a serialization failure
fail closed.
- The docs are updated in the option javadocs (`failOpen`, `batch`;
regenerated metadata) and in the component's *Failure handling* section, which
now lists what `failOpen` covers and what it never covers.
`CamelOpaDecisionFailedOpen` still marks every exchange that proceeds
through `failOpen`.
## Tests
- `OpaSdkFailures` (new test helper) builds each failure exactly the way the
SDK does. The existing tests stubbed "unreachable" as `new
OPAException("connection refused")`, which is the SDK's shape for an *undefined
decision*. They now use the real one.
- `OpaProducerTest` (unit tests):
- fails open on a timeout and on 429/502/503/504;
- fails closed under `failOpen` on an undefined decision, a 400, a
401/403/404/413, a 500 evaluation error, and an input the SDK cannot serialize.
- `OpaBatchEvaluationTest`:
- an element that OPA evaluated with an error, or that came back
undefined, is denied under `failOpen`;
- an element whose server was unreachable (the SDK's per-element fallback)
is still allowed;
- a whole batch rejected with 401 fails closed.
- `OpaSecurityPolicyTest`: the fail-open policy refuses an undefined
decision.
- ITs against a real OPA server and real WASM bundles:
- `OpaIT`: an undefined decision under `failOpen` fails closed, and an
unreachable server still fails open through the real SDK's wrapping;
- `OpaWasmIT`: an undefined rule under `failOpen` fails closed;
- `OpaBearerTokenIT`: a wrong token under `failOpen` fails closed.
- Revert check: with the old evaluators and the new tests, all 14
fail-closed-under-`failOpen` tests fail, including the three real-server ITs,
and the fail-open tests still pass.
- `mvn clean install` in `components/camel-opa`: 108 unit tests and 30 ITs
green. Full reactor `mvn clean install -DskipTests -DskipITs`: green, with no
generated-file drift beyond the opa catalog and DSL entries this change
regenerates.
## Scope
Main only, since camel-opa is new in 4.23.0. No upgrade-guide entry: there
is no earlier release to migrate from.
JIRA: https://issues.apache.org/jira/browse/CAMEL-25139
_Claude Code on behalf of @oscerd_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]