This is an automated email from the ASF dual-hosted git repository.

oscerd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-website.git


The following commit(s) were added to refs/heads/main by this push:
     new 6ac5f067 Blog post: SPIFFE post, add the authorization with Open 
Policy Agent section (#1751)
6ac5f067 is described below

commit 6ac5f067ae52cf04f161b66fde2ca37db7a4a0c1
Author: Andrea Cosentino <[email protected]>
AuthorDate: Mon Sep 14 11:30:18 2026 +0200

    Blog post: SPIFFE post, add the authorization with Open Policy Agent 
section (#1751)
    
    The camel-spiffe example now decides authorization with camel-opa and
    Rego policies instead of an allow-list in the properties. Update the
    example section accordingly and add a section on the component.
---
 .../09/camel-spiffe-workload-identity/index.md     | 69 ++++++++++++++++++----
 1 file changed, 56 insertions(+), 13 deletions(-)

diff --git a/content/blog/2026/09/camel-spiffe-workload-identity/index.md 
b/content/blog/2026/09/camel-spiffe-workload-identity/index.md
index 885e135e..0d91185a 100644
--- a/content/blog/2026/09/camel-spiffe-workload-identity/index.md
+++ b/content/blog/2026/09/camel-spiffe-workload-identity/index.md
@@ -5,7 +5,7 @@ draft: false
 authors: [oscerd]
 categories: ["Security", "Camel"]
 keywords: ["apache camel", "spiffe", "spire", "workload identity", "zero 
trust", "mtls", "jwt-svid", "x509-svid", "camel 4.23", "security", 
"camel-spiffe"]
-preview: "Camel 4.23 adds camel-spiffe. Routes can fetch and validate SPIFFE 
identity documents from the local Workload API, and an SSLContextParameters 
backed by SPIFFE gives rotating mutual TLS to the components that already 
support TLS. There is an example in camel-examples that runs the whole thing 
with Docker Compose."
+preview: "Camel 4.23 adds camel-spiffe. Routes can fetch and validate SPIFFE 
identity documents from the local Workload API, and an SSLContextParameters 
backed by SPIFFE gives rotating mutual TLS to the components that already 
support TLS. There is an example in camel-examples that runs the whole thing 
with Docker Compose, with Open Policy Agent deciding what each identity may do."
 ---
 
 Camel 4.23 is planned for [October](/blog/2026/08/camel422-whatsnew/) and it 
adds a new component,
@@ -153,19 +153,29 @@ and shares the Workload API socket with them. The 
applications never see a crede
 that connects to the socket and issues the identity registered for it.
 
 The backend exposes the orders and an audit trail, the inventory exposes stock 
levels. Both use the same policy, a
-Camel route configuration whose `interceptFrom` validates the JWT-SVID, checks 
the caller against a per-route
-allow-list in `application.properties`, and records the decision, all before 
the route itself runs. The routes
-contain business logic only. Who may do what is three lines:
-
-```properties
-backend.allow.orders = spiffe://example.org/frontend
-backend.allow.audit = spiffe://example.org/auditor
-inventory.allow.stock = spiffe://example.org/backend
+Camel route configuration whose `interceptFrom` validates the JWT-SVID, asks 
Open Policy Agent whether the caller
+may use the route, and records the decision, all before the route itself runs. 
The routes contain business logic
+only. Who may do what is a Rego policy per service in the `opa` directory. 
This is the one of the backend:
+
+```rego
+package camel.spiffe.backend
+
+default allow := false
+
+permissions := {
+       "orders": {"spiffe://example.org/frontend"},
+       "audit": {"spiffe://example.org/auditor"},
+}
+
+allow if {
+       input.headers.CamelSpiffeSpiffeId in permissions[input.routeId]
+}
 ```
 
 Serving the orders takes a second hop. The backend mints a JWT-SVID with the 
inventory as audience and calls it,
-passing the original caller along in a header for the audit trail of the 
inventory. The inventory trusts that header
-because the backend is authenticated and on its allow-list.
+passing the original caller along in a header for the audit trail of the 
inventory. The policy of the inventory
+accepts the backend, and only on behalf of a caller who may read the orders, 
which it checks against the
+permissions of the backend in the same OPA server.
 
 The frontend reads the orders every ten seconds (HTTP 200) and is turned away 
from the audit trail (403). The
 auditor runs the same code and the same image, but as another Unix user, so it 
gets another identity with the
@@ -177,8 +187,40 @@ certificates ten minutes, so you can watch the serial 
number change while the SP
 
 Build it with Maven, start it with `docker compose up --build`, and read the 
logs. The README lists a few things to
 try, like calling the services yourself (you have no identity, so you get a 
401) or letting the auditor read the
-orders by changing one property. The unit tests run without SPIRE: they mock 
the Workload API client and drive the
-two HTTP services over a real embedded server.
+orders by editing one line of Rego, which OPA reloads on the fly. The unit 
tests run without SPIRE and without OPA:
+they mock the Workload API client and the OPA client, and drive the two HTTP 
services over a real embedded server.
+
+## Authorization with Open Policy Agent
+
+*Added on 14 September, after the example moved its authorization to 
camel-opa.*
+
+SPIFFE answers one question, who is calling. What that caller may do is a 
separate question, and it is a bad idea
+to answer it with `if` statements in the route. Camel 4.23 also adds 
`camel-opa`
+([CAMEL-24634](https://issues.apache.org/jira/browse/CAMEL-24634)), a 
component that sends an input document built
+from the exchange to [Open Policy Agent](https://www.openpolicyagent.org/) and 
records the verdict on the exchange.
+The rules live in Rego, next to the deployment, and change without touching 
the application.
+
+In the example the policy of each service calls OPA right after the token is 
validated. It only sends the two
+headers the policy needs, so the bearer token never leaves the application:
+
+```java
+.to("spiffe:backend?operation=validateJwtSvid&audience={{backend.audience}}")
+.to("opa:camel/spiffe/backend/allow?serverUrl={{opa.url}}&includeHeaders=CamelSpiffeSpiffeId,X-On-Behalf-Of")
+.choice()
+    .when(header(OpaConstants.DECISION_ALLOW).isEqualTo(true))
+```
+
+OPA receives this and evaluates the `allow` rule shown above:
+
+```json
+{"headers": {"CamelSpiffeSpiffeId": "spiffe://example.org/frontend"}, 
"routeId": "orders", "exchangeId": "..."}
+```
+
+The verdict comes back in the `CamelOpaDecisionAllow` header, and a deny 
becomes an HTTP 403. The component fails
+closed: if OPA cannot be reached or cannot evaluate the policy, it throws 
instead of answering, and the example turns
+that into an HTTP 503. Stop the OPA container and nobody gets in until it is 
back. The Rego files have unit tests of
+their own, run with `opa test`, and the OPA container watches the directory, 
so editing a policy takes effect
+without a rebuild or a restart.
 
 ## What is next
 
@@ -197,4 +239,5 @@ If you use SPIFFE and have a use case, or something in the 
Preview does not work
 * [The example in 
camel-examples](https://github.com/apache/camel-examples/tree/main/spiffe)
 * [CAMEL-23305](https://issues.apache.org/jira/browse/CAMEL-23305), the 
component
 * [CAMEL-24571](https://issues.apache.org/jira/browse/CAMEL-24571), the 
SSLContextParameters backed by the Workload API
+* [camel-opa component documentation](/components/next/opa-component.html) and 
[CAMEL-24634](https://issues.apache.org/jira/browse/CAMEL-24634)
 * [SPIFFE](https://spiffe.io/), 
[SPIRE](https://spiffe.io/docs/latest/spire-about/) and 
[java-spiffe](https://github.com/spiffe/java-spiffe)

Reply via email to