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.git
The following commit(s) were added to refs/heads/main by this push:
new 563609bc1384 CAMEL-24732: camel-opa - withhold credential headers from
the includeHeaders wildcard (#26430)
563609bc1384 is described below
commit 563609bc1384098420f6a46ec127f5c5c8b8f636
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue Sep 15 12:27:53 2026 +0200
CAMEL-24732: camel-opa - withhold credential headers from the
includeHeaders wildcard (#26430)
Do not forward credential/authorization headers to the OPA decision request
when includeHeaders uses a wildcard.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
---
.../org/apache/camel/catalog/components/opa.json | 4 +--
.../apache/camel/catalog/docs/opa-component.adoc | 17 +++++++++---
.../org/apache/camel/component/opa/opa.json | 4 +--
.../camel-opa/src/main/docs/opa-component.adoc | 17 +++++++++---
.../camel/component/opa/OpaConfiguration.java | 6 ++--
.../camel/component/opa/OpaPolicyEvaluator.java | 26 +++++++++++++++++-
.../camel/component/opa/OpaInputDocumentTest.java | 32 ++++++++++++++++++++++
.../component/dsl/OpaComponentBuilderFactory.java | 10 +++++--
.../endpoint/dsl/OpaEndpointBuilderFactory.java | 10 +++++--
9 files changed, 105 insertions(+), 21 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opa.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opa.json
index 23cf528871da..02e9044ba20b 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opa.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opa.json
@@ -27,7 +27,7 @@
"allowKey": { "index": 0, "kind": "property", "displayName": "Allow Key",
"group": "producer", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "allow", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "The key to read the allow\/deny verdict from
when the policy returns an object rather than a plain b [...]
"configuration": { "index": 1, "kind": "property", "displayName":
"Configuration", "group": "producer", "label": "", "required": false, "type":
"object", "javaType": "org.apache.camel.component.opa.OpaConfiguration",
"deprecated": false, "autowired": false, "secret": false, "description": "The
component configuration." },
"includeBody": { "index": 2, "kind": "property", "displayName": "Include
Body", "group": "producer", "label": "", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Whether to send the message body to OPA as
part of the input document. Disabled by default: bodies can b [...]
- "includeHeaders": { "index": 3, "kind": "property", "displayName":
"Include Headers", "group": "producer", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "*", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of message header names
to send to OPA in the input document. The defau [...]
+ "includeHeaders": { "index": 3, "kind": "property", "displayName":
"Include Headers", "group": "producer", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "*", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of message header names
to send to OPA in the input document. The defau [...]
"includeProperties": { "index": 4, "kind": "property", "displayName":
"Include Properties", "group": "producer", "label": "", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of exchange property
names to send to OPA in the input document, or {code } for all of [...]
"lazyStartProducer": { "index": 5, "kind": "property", "displayName":
"Lazy Start Producer", "group": "producer", "label": "producer", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false, "description":
"Whether the producer should be started lazy (on the first message). By
starting lazy you can use this to allow CamelContext and routes to startup in
situations where a producer may otherwise fail [...]
"serverUrl": { "index": 6, "kind": "property", "displayName": "Server
Url", "group": "producer", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "http:\/\/localhost:8181",
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "The base URL of the OPA
server, without the {code \/v1\/data} suffix. The defaul [...]
@@ -47,7 +47,7 @@
"policyPath": { "index": 0, "kind": "path", "displayName": "Policy Path",
"group": "producer", "label": "", "required": true, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Path of the Rego rule head
to evaluate, relative to the OPA data document. For a rule named allow in a
policy declaring package authz.orders, this is authz\/orders\/allow. The path
is taken from the endpoint only: i [...]
"allowKey": { "index": 1, "kind": "parameter", "displayName": "Allow Key",
"group": "producer", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "allow", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "The key to read the allow\/deny verdict from
when the policy returns an object rather than a plain [...]
"includeBody": { "index": 2, "kind": "parameter", "displayName": "Include
Body", "group": "producer", "label": "", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Whether to send the message body to OPA as
part of the input document. Disabled by default: bodies can [...]
- "includeHeaders": { "index": 3, "kind": "parameter", "displayName":
"Include Headers", "group": "producer", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "*", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of message header names
to send to OPA in the input document. The defa [...]
+ "includeHeaders": { "index": 3, "kind": "parameter", "displayName":
"Include Headers", "group": "producer", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "*", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of message header names
to send to OPA in the input document. The defa [...]
"includeProperties": { "index": 4, "kind": "parameter", "displayName":
"Include Properties", "group": "producer", "label": "", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of exchange property
names to send to OPA in the input document, or {code } for all o [...]
"serverUrl": { "index": 5, "kind": "parameter", "displayName": "Server
Url", "group": "producer", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "http:\/\/localhost:8181",
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "The base URL of the OPA
server, without the {code \/v1\/data} suffix. The defau [...]
"lazyStartProducer": { "index": 6, "kind": "parameter", "displayName":
"Lazy Start Producer", "group": "producer (advanced)", "label":
"producer,advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Whether the producer should be started
lazy (on the first message). By starting lazy you can use this to allow
CamelContext and routes to startup in situations where a produc [...]
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/opa-component.adoc
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/opa-component.adoc
index b20e097915a9..eaf35efdf89d 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/opa-component.adoc
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/opa-component.adoc
@@ -120,10 +120,19 @@
https://github.com/apache/camel/blob/main/components/camel-opa/src/test/resource
which is a worked example of both a plain boolean rule and a decision object
with deny reasons; `OpaIT`
alongside it shows the matching routes end to end.
-`headers` carries every message header by default. Set `includeHeaders` to a
comma-separated list of names
-(matched case-insensitively) when the policy only needs a few of them. `body`
is *not* sent unless `includeBody`
-is enabled: bodies can be large or streaming, and most authorization decisions
do not need them. When you do
-enable it on a streaming body, enable stream caching so the body is still
readable by the rest of the route.
+`headers` carries every message header by default, with one exception: the
headers that carry a caller credential
+verbatim — `Authorization`, `Proxy-Authorization`, `Cookie` and `Set-Cookie` —
are *withheld* from the wildcard.
+OPA's decision logging ships the whole `input` document, frequently to a
remote collector, so the wildcard should
+not quietly export credentials off the box. A policy that genuinely needs one
can still have it by naming the
+header: `includeHeaders=Authorization,user` sends it. Matching is
case-insensitive, so `authorization` is withheld
+too. Set `includeHeaders` to a comma-separated list of names when the policy
only needs a few of them.
+
+Prefer `includeProperties` for identity: a token that an earlier step has
already *verified* belongs there, as
+<<authorizing-an-identity>> describes, rather than handing the raw credential
to the policy to re-check.
+
+`body` is *not* sent unless `includeBody` is enabled: bodies can be large or
streaming, and most authorization
+decisions do not need them. When you do enable it on a streaming body, enable
stream caching so the body is still
+readable by the rest of the route.
`properties` is empty unless you ask for it — see <<authorizing-an-identity>>
below.
diff --git
a/components/camel-opa/src/generated/resources/META-INF/org/apache/camel/component/opa/opa.json
b/components/camel-opa/src/generated/resources/META-INF/org/apache/camel/component/opa/opa.json
index 23cf528871da..02e9044ba20b 100644
---
a/components/camel-opa/src/generated/resources/META-INF/org/apache/camel/component/opa/opa.json
+++
b/components/camel-opa/src/generated/resources/META-INF/org/apache/camel/component/opa/opa.json
@@ -27,7 +27,7 @@
"allowKey": { "index": 0, "kind": "property", "displayName": "Allow Key",
"group": "producer", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "allow", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "The key to read the allow\/deny verdict from
when the policy returns an object rather than a plain b [...]
"configuration": { "index": 1, "kind": "property", "displayName":
"Configuration", "group": "producer", "label": "", "required": false, "type":
"object", "javaType": "org.apache.camel.component.opa.OpaConfiguration",
"deprecated": false, "autowired": false, "secret": false, "description": "The
component configuration." },
"includeBody": { "index": 2, "kind": "property", "displayName": "Include
Body", "group": "producer", "label": "", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Whether to send the message body to OPA as
part of the input document. Disabled by default: bodies can b [...]
- "includeHeaders": { "index": 3, "kind": "property", "displayName":
"Include Headers", "group": "producer", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "*", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of message header names
to send to OPA in the input document. The defau [...]
+ "includeHeaders": { "index": 3, "kind": "property", "displayName":
"Include Headers", "group": "producer", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "*", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of message header names
to send to OPA in the input document. The defau [...]
"includeProperties": { "index": 4, "kind": "property", "displayName":
"Include Properties", "group": "producer", "label": "", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of exchange property
names to send to OPA in the input document, or {code } for all of [...]
"lazyStartProducer": { "index": 5, "kind": "property", "displayName":
"Lazy Start Producer", "group": "producer", "label": "producer", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false, "description":
"Whether the producer should be started lazy (on the first message). By
starting lazy you can use this to allow CamelContext and routes to startup in
situations where a producer may otherwise fail [...]
"serverUrl": { "index": 6, "kind": "property", "displayName": "Server
Url", "group": "producer", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "http:\/\/localhost:8181",
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "The base URL of the OPA
server, without the {code \/v1\/data} suffix. The defaul [...]
@@ -47,7 +47,7 @@
"policyPath": { "index": 0, "kind": "path", "displayName": "Policy Path",
"group": "producer", "label": "", "required": true, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Path of the Rego rule head
to evaluate, relative to the OPA data document. For a rule named allow in a
policy declaring package authz.orders, this is authz\/orders\/allow. The path
is taken from the endpoint only: i [...]
"allowKey": { "index": 1, "kind": "parameter", "displayName": "Allow Key",
"group": "producer", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "allow", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "The key to read the allow\/deny verdict from
when the policy returns an object rather than a plain [...]
"includeBody": { "index": 2, "kind": "parameter", "displayName": "Include
Body", "group": "producer", "label": "", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Whether to send the message body to OPA as
part of the input document. Disabled by default: bodies can [...]
- "includeHeaders": { "index": 3, "kind": "parameter", "displayName":
"Include Headers", "group": "producer", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "*", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of message header names
to send to OPA in the input document. The defa [...]
+ "includeHeaders": { "index": 3, "kind": "parameter", "displayName":
"Include Headers", "group": "producer", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "*", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of message header names
to send to OPA in the input document. The defa [...]
"includeProperties": { "index": 4, "kind": "parameter", "displayName":
"Include Properties", "group": "producer", "label": "", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Comma-separated list of exchange property
names to send to OPA in the input document, or {code } for all o [...]
"serverUrl": { "index": 5, "kind": "parameter", "displayName": "Server
Url", "group": "producer", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "http:\/\/localhost:8181",
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "The base URL of the OPA
server, without the {code \/v1\/data} suffix. The defau [...]
"lazyStartProducer": { "index": 6, "kind": "parameter", "displayName":
"Lazy Start Producer", "group": "producer (advanced)", "label":
"producer,advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Whether the producer should be started
lazy (on the first message). By starting lazy you can use this to allow
CamelContext and routes to startup in situations where a produc [...]
diff --git a/components/camel-opa/src/main/docs/opa-component.adoc
b/components/camel-opa/src/main/docs/opa-component.adoc
index b20e097915a9..eaf35efdf89d 100644
--- a/components/camel-opa/src/main/docs/opa-component.adoc
+++ b/components/camel-opa/src/main/docs/opa-component.adoc
@@ -120,10 +120,19 @@
https://github.com/apache/camel/blob/main/components/camel-opa/src/test/resource
which is a worked example of both a plain boolean rule and a decision object
with deny reasons; `OpaIT`
alongside it shows the matching routes end to end.
-`headers` carries every message header by default. Set `includeHeaders` to a
comma-separated list of names
-(matched case-insensitively) when the policy only needs a few of them. `body`
is *not* sent unless `includeBody`
-is enabled: bodies can be large or streaming, and most authorization decisions
do not need them. When you do
-enable it on a streaming body, enable stream caching so the body is still
readable by the rest of the route.
+`headers` carries every message header by default, with one exception: the
headers that carry a caller credential
+verbatim — `Authorization`, `Proxy-Authorization`, `Cookie` and `Set-Cookie` —
are *withheld* from the wildcard.
+OPA's decision logging ships the whole `input` document, frequently to a
remote collector, so the wildcard should
+not quietly export credentials off the box. A policy that genuinely needs one
can still have it by naming the
+header: `includeHeaders=Authorization,user` sends it. Matching is
case-insensitive, so `authorization` is withheld
+too. Set `includeHeaders` to a comma-separated list of names when the policy
only needs a few of them.
+
+Prefer `includeProperties` for identity: a token that an earlier step has
already *verified* belongs there, as
+<<authorizing-an-identity>> describes, rather than handing the raw credential
to the policy to re-check.
+
+`body` is *not* sent unless `includeBody` is enabled: bodies can be large or
streaming, and most authorization
+decisions do not need them. When you do enable it on a streaming body, enable
stream caching so the body is still
+readable by the rest of the route.
`properties` is empty unless you ask for it — see <<authorizing-an-identity>>
below.
diff --git
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaConfiguration.java
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaConfiguration.java
index bdb98ddda933..d1389c4bd7c1 100644
---
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaConfiguration.java
+++
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaConfiguration.java
@@ -77,8 +77,10 @@ public class OpaConfiguration implements Cloneable {
/**
* Comma-separated list of message header names to send to OPA in the
input document. The default of {@code *} sends
- * every header. Narrow it when the policy only needs a few headers, or
when the message carries headers that should
- * not leave the JVM.
+ * every header <em>except</em> those that carry a caller credential
verbatim - {@code Authorization},
+ * {@code Proxy-Authorization}, {@code Cookie} and {@code Set-Cookie} -
which are withheld because OPA's decision
+ * logging ships the whole input document, often off the box. A policy
that genuinely needs one can still have it by
+ * naming the header here. Narrow the list when the policy only needs a
few headers.
*/
public String getIncludeHeaders() {
return includeHeaders;
diff --git
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaPolicyEvaluator.java
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaPolicyEvaluator.java
index 332ce66dd8ba..79dd9e6ce72c 100644
---
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaPolicyEvaluator.java
+++
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaPolicyEvaluator.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.component.opa;
+import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -40,6 +41,13 @@ public class OpaPolicyEvaluator {
private static final String ALL_NAMES = "*";
+ /**
+ * Headers that carry a caller credential verbatim. They are withheld when
{@code includeHeaders} is the wildcard,
+ * because OPA's decision logging ships the whole input document - often
off the box - and a policy that needs a
+ * credential should say so by naming the header. Listing one explicitly
still sends it.
+ */
+ private static final Set<String> CREDENTIAL_HEADERS = credentialHeaders();
+
private final OPAClient client;
private final String policyPath;
private final String allowKey;
@@ -115,7 +123,7 @@ public class OpaPolicyEvaluator {
String name = entry.getKey();
// never feed our own decision headers back in: a policy must not
be able to read a verdict
// that an inbound message claimed for itself
- if (isDecisionHeader(name) || !isIncluded(includedHeaders, name)) {
+ if (isDecisionHeader(name) || !isIncluded(includedHeaders, name)
|| isWithheldCredential(name)) {
continue;
}
Object value = toJsonSafe(exchange, entry.getValue());
@@ -185,6 +193,22 @@ public class OpaPolicyEvaluator {
return filter == null || !filter.isEmpty();
}
+ /**
+ * A credential header is only sent when the configuration names it, never
through the wildcard.
+ */
+ private boolean isWithheldCredential(String name) {
+ return includedHeaders == null && CREDENTIAL_HEADERS.contains(name);
+ }
+
+ private static Set<String> credentialHeaders() {
+ Set<String> names = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+ names.add("Authorization");
+ names.add("Proxy-Authorization");
+ names.add("Cookie");
+ names.add("Set-Cookie");
+ return Collections.unmodifiableSet(names);
+ }
+
private static boolean isDecisionHeader(String name) {
return OpaConstants.DECISION_ALLOW.equalsIgnoreCase(name)
|| OpaConstants.DECISION.equalsIgnoreCase(name)
diff --git
a/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaInputDocumentTest.java
b/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaInputDocumentTest.java
index c39ccb5d0693..5b2af0a28676 100644
---
a/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaInputDocumentTest.java
+++
b/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaInputDocumentTest.java
@@ -90,6 +90,38 @@ class OpaInputDocumentTest extends CamelTestSupport {
assertThat(input).containsEntry("body", "the payload");
}
+ @Test
+ void withholdsCredentialHeadersFromTheWildcard() throws Exception {
+ Map<String, Object> input = inputSentFor(ENDPOINT, e -> {
+ e.getMessage().setHeader("user", "alice");
+ e.getMessage().setHeader("Authorization", "Bearer s3cr3t");
+ e.getMessage().setHeader("Cookie", "session=s3cr3t");
+ e.getMessage().setHeader("Proxy-Authorization", "Basic s3cr3t");
+ e.getMessage().setHeader("Set-Cookie", "session=abc; Path=/");
+ });
+
+ assertThat(headersOf(input)).containsOnlyKeys("user");
+ }
+
+ @Test
+ void matchesWithheldCredentialHeadersCaseInsensitively() throws Exception {
+ Map<String, Object> input = inputSentFor(ENDPOINT,
+ e -> e.getMessage().setHeader("authorization", "Bearer
s3cr3t"));
+
+ assertThat(headersOf(input)).doesNotContainKey("authorization");
+ }
+
+ @Test
+ void sendsACredentialHeaderWhenItIsNamedExplicitly() throws Exception {
+ Map<String, Object> input = inputSentFor(ENDPOINT +
"&includeHeaders=Authorization,user", e -> {
+ e.getMessage().setHeader("user", "alice");
+ e.getMessage().setHeader("Authorization", "Bearer s3cr3t");
+ });
+
+ // naming it is the opt-in: a policy that must inspect the token can
still get it
+ assertThat(headersOf(input)).containsEntry("Authorization", "Bearer
s3cr3t");
+ }
+
@Test
void sendsOnlyTheListedHeadersWhenNarrowed() throws Exception {
Map<String, Object> input = inputSentFor(ENDPOINT +
"&includeHeaders=user,tenant", e -> {
diff --git
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/OpaComponentBuilderFactory.java
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/OpaComponentBuilderFactory.java
index 366d08d78b22..df6c08ed7cd4 100644
---
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/OpaComponentBuilderFactory.java
+++
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/OpaComponentBuilderFactory.java
@@ -111,9 +111,13 @@ public interface OpaComponentBuilderFactory {
/**
* Comma-separated list of message header names to send to OPA in the
- * input document. The default of {code } sends every header. Narrow it
- * when the policy only needs a few headers, or when the message
carries
- * headers that should not leave the JVM.
+ * input document. The default of {code } sends every header except
+ * those that carry a caller credential verbatim - Authorization, {code
+ * Proxy-Authorization}, Cookie and {code Set-Cookie} - which are
+ * withheld because OPA's decision logging ships the whole input
+ * document, often off the box. A policy that genuinely needs one can
+ * still have it by naming the header here. Narrow the list when the
+ * policy only needs a few headers.
*
* The option is a: <code>java.lang.String</code> type.
*
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpaEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpaEndpointBuilderFactory.java
index 8b3f6f3bc950..65c075956b32 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpaEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpaEndpointBuilderFactory.java
@@ -102,9 +102,13 @@ public interface OpaEndpointBuilderFactory {
}
/**
* Comma-separated list of message header names to send to OPA in the
- * input document. The default of {code } sends every header. Narrow it
- * when the policy only needs a few headers, or when the message
carries
- * headers that should not leave the JVM.
+ * input document. The default of {code } sends every header except
+ * those that carry a caller credential verbatim - Authorization, {code
+ * Proxy-Authorization}, Cookie and {code Set-Cookie} - which are
+ * withheld because OPA's decision logging ships the whole input
+ * document, often off the box. A policy that genuinely needs one can
+ * still have it by naming the header here. Narrow the list when the
+ * policy only needs a few headers.
*
* The option is a: <code>java.lang.String</code> type.
*