[ 
https://issues.apache.org/jira/browse/CAMEL-24634?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18112558#comment-18112558
 ] 

Andrea Cosentino commented on CAMEL-24634:
------------------------------------------

Follow-ups filed from the post-merge review of this component:

* CAMEL-24643 - allow exchange properties in the OPA input document. 
{{camel-keycloak}} stores verified identity in exchange properties and prefers 
them over headers, so {{keycloak -> opa}} currently cannot be composed without 
copying trusted identity into the untrusted channel.
* CAMEL-24644 - add a producer health check for the OPA server, so an 
unreachable policy decision point is visible before it fails every exchange.
* CAMEL-24645 - cover the {{bearerToken}} option with an integration test; it 
is currently exercised by no test at all.

_Claude Code on behalf of oscerd_

> camel-opa - new component to evaluate Open Policy Agent (Rego) policies 
> against an Exchange
> -------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24634
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24634
>             Project: Camel
>          Issue Type: New Feature
>            Reporter: Andrea Cosentino
>            Assignee: Andrea Cosentino
>            Priority: Major
>             Fix For: 4.23.0
>
>
> h2. Background
> {{camel-spiffe}} (CAMEL-23305 / CAMEL-24571) gave Camel a way to *obtain and 
> verify workload identity* - X.509-SVIDs, JWT-SVIDs and SPIFFE-backed mTLS. It 
> answers "who is this caller?".
> What Camel still lacks is the next step: "is this caller allowed to do 
> this?". There is no policy decision component, so authorization logic ends up 
> hand-coded in {{.process()}} / {{.bean()}} blocks - scattered across routes, 
> hard to test in isolation, and impossible to change without redeploying the 
> integration.
> Camel does ship two authorization integrations - {{camel-shiro}} 
> ({{ShiroSecurityPolicy}}) and {{camel-keycloak}} ({{KeycloakSecurityPolicy}}) 
> - but both are tied to a specific identity provider and to coarse 
> role/permission checks. Neither supports externalised, declarative, 
> attribute-based policy.
> h2. Proposal
> Add a {{camel-opa}} component that acts as a Policy Enforcement Point (PEP) 
> delegating decisions to [Open Policy Agent|https://www.openpolicyagent.org/], 
> the CNCF-graduated policy engine whose policies are written in Rego. Camel 
> supplies the {{input}} document built from the Exchange; OPA evaluates the 
> Rego policy and returns the decision.
> Two complementary usage modes:
> *1. Producer endpoint* - {{opa:<decisionPath>}}
> Builds an OPA {{input}} document from the Exchange (headers, and optionally 
> the body), POSTs it to the OPA Data API, and sets the decision back on the 
> Exchange as headers:
> * {{CamelOpaDecisionAllow}} (Boolean) - the allow/deny verdict
> * {{CamelOpaDecision}} - the full raw decision document, for policies 
> returning more than a boolean (obligations, row filters, deny reasons)
> That makes it directly usable in a {{filter}} or {{choice}} predicate:
> {code:java}
> from("platform-http:/orders")
>     .to("opa:authz/orders/allow")
>     .filter(header(OpaConstants.DECISION_ALLOW).isEqualTo(true))
>         .to("direct:handleOrder");
> {code}
> *2. {{OpaSecurityPolicy implements 
> org.apache.camel.spi.AuthorizationPolicy}}* - the interceptor style, 
> mirroring {{ShiroSecurityPolicy}} / {{KeycloakSecurityPolicy}}:
> {code:java}
> from("platform-http:/orders")
>     .policy(opaPolicy)
>         .to("direct:handleOrder");
> {code}
> A deny throws {{CamelAuthorizationException}}, so it composes with the 
> existing {{onException}} machinery and never silently continues down the 
> route.
> h2. Design notes
> * *Library*: {{com.styra:opa}} (the official OPA Java SDK, 
> {{styrainc/opa-java}}) - Apache-2.0 and published on Maven Central, so it 
> clears the new-component dependency gate. It wraps OPA's REST Data API, which 
> is the standard OPA deployment model (OPA running as a sidecar/daemon next to 
> the application).
> * *Input shaping must be opt-in and bounded.* Sending the whole message body 
> to the PDP is wrong as a default - bodies can be large, streaming, or carry 
> data the PDP has no business seeing. Default to headers plus a configurable 
> header allow-list; body inclusion behind an explicit {{includeBody}} option, 
> with the stream-caching implications documented.
> * *Fail-closed by default.* If OPA is unreachable, times out, or returns a 
> malformed or absent decision, the default must be *deny*. A {{failOpen}} 
> option may exist but must default to {{false}}. See CAMEL-24281 and the 
> keycloak fail-open finding, where an authorization component that failed open 
> was treated as a security defect.
> * *Header hygiene.* The decision headers are Camel-internal. The component 
> must not let an external sender pre-set {{CamelOpaDecisionAllow}} and have it 
> survive into the route - overwrite unconditionally, and document 
> {{removeHeaders("CamelOpa*")}} for untrusted ingress.
> * *In-process evaluation* ({{com.styra.opa:opa-java-wasm}}, Rego compiled to 
> WASM) is deliberately out of scope for this first increment - that artifact 
> is still at 0.0.6, and the REST/sidecar model covers the mainstream 
> deployment. It can follow later.
> h2. Scope of this issue
> First increment, {{main}} only (new component, so no backport):
> * new module {{components/camel-opa}} - component, endpoint, producer, 
> configuration, constants
> * {{OpaSecurityPolicy}} + {{OpaSecurityProcessor}} implementing 
> {{AuthorizationPolicy}}
> * unit tests covering allow, deny, unreachable PDP (fail-closed), non-boolean 
> decision documents, and the security-policy path
> * component documentation ({{src/main/docs/opa-component.adoc}})



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to