oscerd opened a new pull request, #26187:
URL: https://github.com/apache/camel/pull/26187

   ## What
   
   Adds an `includeProperties` option to `camel-opa`, so a policy can be handed 
an identity that an earlier step stored as an exchange property.
   
   ## Why
   
   `camel-opa` built its OPA `input` document from message headers only:
   
   ```java
   for (Map.Entry<String, Object> entry : 
exchange.getMessage().getHeaders().entrySet()) {
   ```
   
   But that is not where Camel's authentication components keep the identity 
they verified. `KeycloakSecurityProcessor` stores the access token and its 
subject as **exchange properties** (`ACCESS_TOKEN_PROPERTY`, 
`TOKEN_SUBJECT_PROPERTY`, `TOKEN_THUMBPRINT_PROPERTY`), and defaults 
`preferPropertyOverHeader` to `true` — documented there as preventing 
"header-based token override attacks".
   
   So the two halves could not be composed. Authorizing an identity that 
`KeycloakSecurityPolicy` had just verified meant copying it from an exchange 
property into a message header so `camel-opa` could see it — moving trusted 
identity into the exact channel the authentication step treats as untrusted, 
and making the safe composition the awkward one.
   
   ## What changed
   
   `includeProperties` mirrors `includeHeaders` — a comma-separated allow-list, 
or `*`, matched case-insensitively — and contributes a `properties` object to 
the input document:
   
   ```json
   {
     "headers":    { "user": "alice" },
     "properties": { "CamelKeycloakTokenSubject": "alice" },
     "exchangeId": "...",
     "routeId":    "orders"
   }
   ```
   
   Available on the endpoint and on `OpaSecurityPolicy` 
(`setIncludeProperties`).
   
   Three deliberate choices:
   
   - **Defaults to empty, not `*`** — the opposite of `includeHeaders`. Headers 
are mostly business data, so `*` is the useful default there; exchange 
properties mostly carry state between processors, so sending them all would be 
noise the policy has to wade through. The two empty-semantics share one parser 
(`parseNameFilter(names, emptyMeansAll)`) rather than duplicating the matching 
logic.
   - **The `properties` key is omitted entirely when nothing is selected**, so 
the document an existing route sends is byte-identical to before this change.
   - **Sourced from `exchange.getProperties()`, not `getAllProperties()`** — 
custom properties only, so Camel's internal bookkeeping never reaches the 
policy. That is also what keeps `includeProperties=*` usable rather than noise.
   
   ## Testing
   
   32 unit tests (was 25). New coverage: nothing sent by default; allow-list 
narrowing; `*`; case-insensitive matching; non-JSON-native values converted; 
headers and properties with the *same name* staying in separate objects; and an 
`OpaSecurityPolicy` test proving an identity stored as an exchange property 
reaches the policy.
   
   Full reactor build green.
   
   ## Docs
   
   New `Authorizing an identity` section spelling out the keycloak → opa 
composition and why passing the identity as a property beats copying it into a 
header. The existing Security-notes bullet now points at it instead of 
repeating it.
   
   `main` only — additive option, no behaviour change for existing routes.
   
   _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]

Reply via email to