This is an automated email from the ASF dual-hosted git repository.
davsclaus 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 ac28671dfc12 CAMEL-26838: Support bundle-aware server readiness checks
(#29833)
ac28671dfc12 is described below
commit ac28671dfc12fa1a42c91b4414ae258db6fd6711
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri Nov 13 15:54:52 2026 +0100
CAMEL-26838: Support bundle-aware server readiness checks (#29833)
Co-authored-by: Codex <[email protected]>
---
.../camel/catalog/beans/OpaSecurityPolicy.json | 2 +-
.../org/apache/camel/catalog/components/opa.json | 32 ++++-----
.../apache/camel/catalog/docs/opa-component.adoc | 30 +++++++++
.../component/opa/OpaComponentConfigurer.java | 6 ++
.../camel/component/opa/OpaEndpointConfigurer.java | 6 ++
.../camel/component/opa/OpaEndpointUriFactory.java | 3 +-
.../opa/security/OpaSecurityPolicyConfigurer.java | 6 ++
.../org/apache/camel/component/opa/opa.json | 32 ++++-----
.../org/apache/camel/bean/OpaSecurityPolicy.json | 2 +-
.../camel-opa/src/main/docs/opa-component.adoc | 30 +++++++++
.../camel/component/opa/OpaConfiguration.java | 18 ++++++
.../apache/camel/component/opa/OpaEndpoint.java | 3 +
.../apache/camel/component/opa/OpaHealthProbe.java | 23 ++++++-
.../apache/camel/component/opa/OpaProducer.java | 3 +-
.../component/opa/OpaProducerHealthCheck.java | 9 ++-
.../component/opa/security/OpaSecurityPolicy.java | 22 ++++++-
.../opa/security/OpaSecurityPolicyHealthCheck.java | 9 ++-
.../opa/OpaHealthCheckRegistrationTest.java | 55 ++++++++++++++++
.../component/opa/OpaProducerHealthCheckTest.java | 75 ++++++++++++++++++++++
.../security/OpaSecurityPolicyHealthCheckTest.java | 31 ++++++++-
.../component/dsl/OpaComponentBuilderFactory.java | 21 ++++++
.../endpoint/dsl/OpaEndpointBuilderFactory.java | 36 +++++++++++
22 files changed, 414 insertions(+), 40 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/OpaSecurityPolicy.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/OpaSecurityPolicy.json
index aa6c5e6247e8..d1504304e6d2 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/OpaSecurityPolicy.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/OpaSecurityPolicy.json
@@ -10,7 +10,7 @@
"groupId": "org.apache.camel",
"artifactId": "camel-opa",
"version": "4.24.0-SNAPSHOT",
- "properties": { "serverUrl": { "index": 0, "kind": "property",
"displayName": "Server Url", "required": false, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": "http:\/\/localhost:8181", "description": "The base URL of the
OPA server, without the \/v1\/data suffix. Not used in wasm mode." },
"policyPath": { "index": 1, "kind": "property", "displayName": "Policy Path",
"required": true, "type": "string", "javaT [...]
+ "properties": { "serverUrl": { "index": 0, "kind": "property",
"displayName": "Server Url", "required": false, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": "http:\/\/localhost:8181", "description": "The base URL of the
OPA server, without the \/v1\/data suffix. Not used in wasm mode." },
"policyPath": { "index": 1, "kind": "property", "displayName": "Policy Path",
"required": true, "type": "string", "javaT [...]
}
}
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 7eec7e2fdf00..2fcbffcb3426 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
@@ -38,15 +38,16 @@
"autowiredEnabled": { "index": 11, "kind": "property", "displayName":
"Autowired Enabled", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true, "description":
"Whether autowiring is enabled. This is used for automatic autowiring options
(the option must be marked as autowired) by looking up in the registry to find
if there is a single instance of matching [...]
"borrowTimeout": { "index": 12, "kind": "property", "displayName": "Borrow
Timeout", "group": "advanced", "label": "advanced", "required": false, "type":
"duration", "javaType": "long", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long an exchange waits for a free
WebAssembly policy instance in wasm mode before the e [...]
"connectionTimeout": { "index": 13, "kind": "property", "displayName":
"Connection Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "duration", "javaType": "long", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": "10000",
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "How long to wait for the
connection to the OPA server to be established, in rest mo [...]
- "opaClient": { "index": 14, "kind": "property", "displayName": "Opa
Client", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "com.styra.opa.OPAClient", "deprecated": false,
"autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "An existing OPAClient to use. When set,
serverUrl and bearerToken are ignored." },
- "poolSize": { "index": 15, "kind": "property", "displayName": "Pool Size",
"group": "advanced", "label": "advanced", "required": false, "type": "integer",
"javaType": "int", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": 8, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How many WebAssembly policy instances to pool
in wasm mode. An instance carries mutable state and is not thre [...]
- "requestTimeout": { "index": 16, "kind": "property", "displayName":
"Request Timeout", "group": "advanced", "label": "advanced", "required": false,
"type": "duration", "javaType": "long", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long to wait for the decision once
connected, in rest mode. A request that times out [...]
- "healthCheckConsumerEnabled": { "index": 17, "kind": "property",
"displayName": "Health Check Consumer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all consumer based health checks
from this component" },
- "healthCheckProducerEnabled": { "index": 18, "kind": "property",
"displayName": "Health Check Producer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all producer based health checks
from this component. Notice: Camel has by default disabled all producer based
health-checks. You can turn on produce [...]
- "bearerToken": { "index": 19, "kind": "property", "displayName": "Bearer
Token", "group": "security", "label": "security", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Bearer token sent to the OPA server in the
Authorization header, for an OPA instance that [...]
- "failOpen": { "index": 20, "kind": "property", "displayName": "Fail Open",
"group": "security", "label": "security", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "security": "insecure:dev", "defaultValue": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Whether to allow the exchange to proceed when
the policy decision point i [...]
- "sslContextParameters": { "index": 21, "kind": "property", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "TLS configuration for the connection to the
OPA server in [...]
- "useGlobalSslContextParameters": { "index": 22, "kind": "property",
"displayName": "Use Global Ssl Context Parameters", "group": "security",
"label": "security", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Enable usage of global SSL context
parameters." }
+ "healthCheckBundles": { "index": 14, "kind": "property", "displayName":
"Health Check Bundles", "group": "advanced", "label": "advanced", "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 the server
readiness check also requires activation of OPA's configured [...]
+ "opaClient": { "index": 15, "kind": "property", "displayName": "Opa
Client", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "com.styra.opa.OPAClient", "deprecated": false,
"autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "An existing OPAClient to use. When set,
serverUrl and bearerToken are ignored." },
+ "poolSize": { "index": 16, "kind": "property", "displayName": "Pool Size",
"group": "advanced", "label": "advanced", "required": false, "type": "integer",
"javaType": "int", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": 8, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How many WebAssembly policy instances to pool
in wasm mode. An instance carries mutable state and is not thre [...]
+ "requestTimeout": { "index": 17, "kind": "property", "displayName":
"Request Timeout", "group": "advanced", "label": "advanced", "required": false,
"type": "duration", "javaType": "long", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long to wait for the decision once
connected, in rest mode. A request that times out [...]
+ "healthCheckConsumerEnabled": { "index": 18, "kind": "property",
"displayName": "Health Check Consumer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all consumer based health checks
from this component" },
+ "healthCheckProducerEnabled": { "index": 19, "kind": "property",
"displayName": "Health Check Producer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all producer based health checks
from this component. Notice: Camel has by default disabled all producer based
health-checks. You can turn on produce [...]
+ "bearerToken": { "index": 20, "kind": "property", "displayName": "Bearer
Token", "group": "security", "label": "security", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Bearer token sent to the OPA server in the
Authorization header, for an OPA instance that [...]
+ "failOpen": { "index": 21, "kind": "property", "displayName": "Fail Open",
"group": "security", "label": "security", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "security": "insecure:dev", "defaultValue": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Whether to allow the exchange to proceed when
the policy decision point i [...]
+ "sslContextParameters": { "index": 22, "kind": "property", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "TLS configuration for the connection to the
OPA server in [...]
+ "useGlobalSslContextParameters": { "index": 23, "kind": "property",
"displayName": "Use Global Ssl Context Parameters", "group": "security",
"label": "security", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Enable usage of global SSL context
parameters." }
},
"headers": {
"CamelOpaDecisionAllow": { "index": 0, "kind": "header", "displayName":
"", "group": "producer", "label": "producer", "required": false, "javaType":
"Boolean", "deprecated": false, "autowired": false, "secret": false,
"description": "The allow\/deny verdict of the policy evaluation. Always
overwritten by the component, so a value set by an inbound message never
survives into the route.", "constantName":
"org.apache.camel.component.opa.OpaConstants#DECISION_ALLOW" },
@@ -74,11 +75,12 @@
"lazyStartProducer": { "index": 10, "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 produ [...]
"borrowTimeout": { "index": 11, "kind": "parameter", "displayName":
"Borrow Timeout", "group": "advanced", "label": "advanced", "required": false,
"type": "duration", "javaType": "long", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long an exchange waits for a free
WebAssembly policy instance in wasm mode before the [...]
"connectionTimeout": { "index": 12, "kind": "parameter", "displayName":
"Connection Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "duration", "javaType": "long", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": "10000",
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "How long to wait for the
connection to the OPA server to be established, in rest m [...]
- "opaClient": { "index": 13, "kind": "parameter", "displayName": "Opa
Client", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "com.styra.opa.OPAClient", "deprecated": false,
"autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "An existing OPAClient to use. When set,
serverUrl and bearerToken are ignored." },
- "poolSize": { "index": 14, "kind": "parameter", "displayName": "Pool
Size", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 8, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How many WebAssembly policy instances to pool
in wasm mode. An instance carries mutable state and is not thr [...]
- "requestTimeout": { "index": 15, "kind": "parameter", "displayName":
"Request Timeout", "group": "advanced", "label": "advanced", "required": false,
"type": "duration", "javaType": "long", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long to wait for the decision once
connected, in rest mode. A request that times out [...]
- "bearerToken": { "index": 16, "kind": "parameter", "displayName": "Bearer
Token", "group": "security", "label": "security", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Bearer token sent to the OPA server in the
Authorization header, for an OPA instance tha [...]
- "failOpen": { "index": 17, "kind": "parameter", "displayName": "Fail
Open", "group": "security", "label": "security", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "security": "insecure:dev", "defaultValue": false,
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "Whether to allow the
exchange to proceed when the policy decision point [...]
- "sslContextParameters": { "index": 18, "kind": "parameter", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "TLS configuration for the connection to the
OPA server i [...]
+ "healthCheckBundles": { "index": 13, "kind": "parameter", "displayName":
"Health Check Bundles", "group": "advanced", "label": "advanced", "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 the server
readiness check also requires activation of OPA's configured [...]
+ "opaClient": { "index": 14, "kind": "parameter", "displayName": "Opa
Client", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "com.styra.opa.OPAClient", "deprecated": false,
"autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "An existing OPAClient to use. When set,
serverUrl and bearerToken are ignored." },
+ "poolSize": { "index": 15, "kind": "parameter", "displayName": "Pool
Size", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 8, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How many WebAssembly policy instances to pool
in wasm mode. An instance carries mutable state and is not thr [...]
+ "requestTimeout": { "index": 16, "kind": "parameter", "displayName":
"Request Timeout", "group": "advanced", "label": "advanced", "required": false,
"type": "duration", "javaType": "long", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long to wait for the decision once
connected, in rest mode. A request that times out [...]
+ "bearerToken": { "index": 17, "kind": "parameter", "displayName": "Bearer
Token", "group": "security", "label": "security", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Bearer token sent to the OPA server in the
Authorization header, for an OPA instance tha [...]
+ "failOpen": { "index": 18, "kind": "parameter", "displayName": "Fail
Open", "group": "security", "label": "security", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "security": "insecure:dev", "defaultValue": false,
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "Whether to allow the
exchange to proceed when the policy decision point [...]
+ "sslContextParameters": { "index": 19, "kind": "parameter", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "TLS configuration for the connection to the
OPA server i [...]
}
}
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 0c92bf687881..f1d966bed6bc 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
@@ -688,6 +688,36 @@ component with `healthCheckProducerEnabled`. The check
reports DOWN with the und
server and a server answering its health endpoint with an error are reported
differently, so a deny is never
confused with an outage.
+Set `healthCheckBundles=true` on the endpoint or `OpaSecurityPolicy` bean to
request
+`/health?bundles=true`. OPA then includes activation/readiness of its
configured bundles and discovery in the
+server's health result. This is useful when a server starts downloading
bundles after startup: a reachable server
+can otherwise report healthy before it has activated its policy bundle. The
default remains the basic `/health`
+check. This option does not itself enable producer health checks or change
policy evaluation.
+
+For example, with producer checks enabled:
+
+[source,java]
+----
+.to("opa:authz/orders/allow?healthCheckBundles=true")
+----
+
+For a policy bean:
+
+[source,yaml]
+----
+- beans:
+ - name: opaPolicy
+ type: org.apache.camel.component.opa.security.OpaSecurityPolicy
+ properties:
+ serverUrl: http://localhost:8181
+ policyPath: authz/orders/allow
+ healthCheckBundles: true
+----
+
+Bundle-aware readiness follows OPA's health semantics. It does not verify a
particular bundle revision,
+guarantee policy freshness, or validate business permissions for a message. It
is unused in `wasm` mode,
+with an injected `opaClient`, or when the corresponding health check is
disabled.
+
`OpaSecurityPolicy` registers an equivalent check, under an id starting
`security-policy:opa-`. It is arguably the
more important of the two: a denied producer merely records a verdict the
route can inspect, while the policy throws
`CamelAuthorizationException` and stops the exchange, so an unreachable server
there fails every message outright.
diff --git
a/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaComponentConfigurer.java
b/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaComponentConfigurer.java
index dcca3a47a6b3..45ff639df719 100644
---
a/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaComponentConfigurer.java
+++
b/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaComponentConfigurer.java
@@ -48,6 +48,8 @@ public class OpaComponentConfigurer extends
PropertyConfigurerSupport implements
case "evaluationMode":
getOrCreateConfiguration(target).setEvaluationMode(property(camelContext,
java.lang.String.class, value)); return true;
case "failopen":
case "failOpen":
getOrCreateConfiguration(target).setFailOpen(property(camelContext,
boolean.class, value)); return true;
+ case "healthcheckbundles":
+ case "healthCheckBundles":
getOrCreateConfiguration(target).setHealthCheckBundles(property(camelContext,
boolean.class, value)); return true;
case "healthcheckconsumerenabled":
case "healthCheckConsumerEnabled":
target.setHealthCheckConsumerEnabled(property(camelContext, boolean.class,
value)); return true;
case "healthcheckproducerenabled":
@@ -103,6 +105,8 @@ public class OpaComponentConfigurer extends
PropertyConfigurerSupport implements
case "evaluationMode": return java.lang.String.class;
case "failopen":
case "failOpen": return boolean.class;
+ case "healthcheckbundles":
+ case "healthCheckBundles": return boolean.class;
case "healthcheckconsumerenabled":
case "healthCheckConsumerEnabled": return boolean.class;
case "healthcheckproducerenabled":
@@ -154,6 +158,8 @@ public class OpaComponentConfigurer extends
PropertyConfigurerSupport implements
case "evaluationMode": return
getOrCreateConfiguration(target).getEvaluationMode();
case "failopen":
case "failOpen": return getOrCreateConfiguration(target).isFailOpen();
+ case "healthcheckbundles":
+ case "healthCheckBundles": return
getOrCreateConfiguration(target).isHealthCheckBundles();
case "healthcheckconsumerenabled":
case "healthCheckConsumerEnabled": return
target.isHealthCheckConsumerEnabled();
case "healthcheckproducerenabled":
diff --git
a/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaEndpointConfigurer.java
b/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaEndpointConfigurer.java
index 164499d6e7ea..1a18746d109c 100644
---
a/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaEndpointConfigurer.java
+++
b/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaEndpointConfigurer.java
@@ -38,6 +38,8 @@ public class OpaEndpointConfigurer extends
PropertyConfigurerSupport implements
case "evaluationMode":
target.getConfiguration().setEvaluationMode(property(camelContext,
java.lang.String.class, value)); return true;
case "failopen":
case "failOpen":
target.getConfiguration().setFailOpen(property(camelContext, boolean.class,
value)); return true;
+ case "healthcheckbundles":
+ case "healthCheckBundles":
target.getConfiguration().setHealthCheckBundles(property(camelContext,
boolean.class, value)); return true;
case "includebody":
case "includeBody":
target.getConfiguration().setIncludeBody(property(camelContext, boolean.class,
value)); return true;
case "includeheaders":
@@ -84,6 +86,8 @@ public class OpaEndpointConfigurer extends
PropertyConfigurerSupport implements
case "evaluationMode": return java.lang.String.class;
case "failopen":
case "failOpen": return boolean.class;
+ case "healthcheckbundles":
+ case "healthCheckBundles": return boolean.class;
case "includebody":
case "includeBody": return boolean.class;
case "includeheaders":
@@ -126,6 +130,8 @@ public class OpaEndpointConfigurer extends
PropertyConfigurerSupport implements
case "evaluationMode": return
target.getConfiguration().getEvaluationMode();
case "failopen":
case "failOpen": return target.getConfiguration().isFailOpen();
+ case "healthcheckbundles":
+ case "healthCheckBundles": return
target.getConfiguration().isHealthCheckBundles();
case "includebody":
case "includeBody": return target.getConfiguration().isIncludeBody();
case "includeheaders":
diff --git
a/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaEndpointUriFactory.java
b/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaEndpointUriFactory.java
index 4658a482ab99..670b50f9c6b6 100644
---
a/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaEndpointUriFactory.java
+++
b/components/camel-opa/src/generated/java/org/apache/camel/component/opa/OpaEndpointUriFactory.java
@@ -24,7 +24,7 @@ public class OpaEndpointUriFactory extends
org.apache.camel.support.component.En
private static final Set<String> ENDPOINT_IDENTITY_PROPERTY_NAMES;
private static final Map<String, String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(19);
+ Set<String> props = new HashSet<>(20);
props.add("allowKey");
props.add("batch");
props.add("bearerToken");
@@ -33,6 +33,7 @@ public class OpaEndpointUriFactory extends
org.apache.camel.support.component.En
props.add("entrypoint");
props.add("evaluationMode");
props.add("failOpen");
+ props.add("healthCheckBundles");
props.add("includeBody");
props.add("includeHeaders");
props.add("includeProperties");
diff --git
a/components/camel-opa/src/generated/java/org/apache/camel/component/opa/security/OpaSecurityPolicyConfigurer.java
b/components/camel-opa/src/generated/java/org/apache/camel/component/opa/security/OpaSecurityPolicyConfigurer.java
index 422629ed63db..abfe3940d152 100644
---
a/components/camel-opa/src/generated/java/org/apache/camel/component/opa/security/OpaSecurityPolicyConfigurer.java
+++
b/components/camel-opa/src/generated/java/org/apache/camel/component/opa/security/OpaSecurityPolicyConfigurer.java
@@ -37,6 +37,8 @@ public class OpaSecurityPolicyConfigurer extends
org.apache.camel.support.compon
case "evaluationMode": target.setEvaluationMode(property(camelContext,
java.lang.String.class, value)); return true;
case "failopen":
case "failOpen": target.setFailOpen(property(camelContext,
boolean.class, value)); return true;
+ case "healthcheckbundles":
+ case "healthCheckBundles":
target.setHealthCheckBundles(property(camelContext, boolean.class, value));
return true;
case "healthcheckenabled":
case "healthCheckEnabled":
target.setHealthCheckEnabled(property(camelContext, boolean.class, value));
return true;
case "includebody":
@@ -81,6 +83,8 @@ public class OpaSecurityPolicyConfigurer extends
org.apache.camel.support.compon
case "evaluationMode": return java.lang.String.class;
case "failopen":
case "failOpen": return boolean.class;
+ case "healthcheckbundles":
+ case "healthCheckBundles": return boolean.class;
case "healthcheckenabled":
case "healthCheckEnabled": return boolean.class;
case "includebody":
@@ -126,6 +130,8 @@ public class OpaSecurityPolicyConfigurer extends
org.apache.camel.support.compon
case "evaluationMode": return target.getEvaluationMode();
case "failopen":
case "failOpen": return target.isFailOpen();
+ case "healthcheckbundles":
+ case "healthCheckBundles": return target.isHealthCheckBundles();
case "healthcheckenabled":
case "healthCheckEnabled": return target.isHealthCheckEnabled();
case "includebody":
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 7eec7e2fdf00..2fcbffcb3426 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
@@ -38,15 +38,16 @@
"autowiredEnabled": { "index": 11, "kind": "property", "displayName":
"Autowired Enabled", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true, "description":
"Whether autowiring is enabled. This is used for automatic autowiring options
(the option must be marked as autowired) by looking up in the registry to find
if there is a single instance of matching [...]
"borrowTimeout": { "index": 12, "kind": "property", "displayName": "Borrow
Timeout", "group": "advanced", "label": "advanced", "required": false, "type":
"duration", "javaType": "long", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long an exchange waits for a free
WebAssembly policy instance in wasm mode before the e [...]
"connectionTimeout": { "index": 13, "kind": "property", "displayName":
"Connection Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "duration", "javaType": "long", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": "10000",
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "How long to wait for the
connection to the OPA server to be established, in rest mo [...]
- "opaClient": { "index": 14, "kind": "property", "displayName": "Opa
Client", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "com.styra.opa.OPAClient", "deprecated": false,
"autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "An existing OPAClient to use. When set,
serverUrl and bearerToken are ignored." },
- "poolSize": { "index": 15, "kind": "property", "displayName": "Pool Size",
"group": "advanced", "label": "advanced", "required": false, "type": "integer",
"javaType": "int", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": 8, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How many WebAssembly policy instances to pool
in wasm mode. An instance carries mutable state and is not thre [...]
- "requestTimeout": { "index": 16, "kind": "property", "displayName":
"Request Timeout", "group": "advanced", "label": "advanced", "required": false,
"type": "duration", "javaType": "long", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long to wait for the decision once
connected, in rest mode. A request that times out [...]
- "healthCheckConsumerEnabled": { "index": 17, "kind": "property",
"displayName": "Health Check Consumer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all consumer based health checks
from this component" },
- "healthCheckProducerEnabled": { "index": 18, "kind": "property",
"displayName": "Health Check Producer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all producer based health checks
from this component. Notice: Camel has by default disabled all producer based
health-checks. You can turn on produce [...]
- "bearerToken": { "index": 19, "kind": "property", "displayName": "Bearer
Token", "group": "security", "label": "security", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Bearer token sent to the OPA server in the
Authorization header, for an OPA instance that [...]
- "failOpen": { "index": 20, "kind": "property", "displayName": "Fail Open",
"group": "security", "label": "security", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "security": "insecure:dev", "defaultValue": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Whether to allow the exchange to proceed when
the policy decision point i [...]
- "sslContextParameters": { "index": 21, "kind": "property", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "TLS configuration for the connection to the
OPA server in [...]
- "useGlobalSslContextParameters": { "index": 22, "kind": "property",
"displayName": "Use Global Ssl Context Parameters", "group": "security",
"label": "security", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Enable usage of global SSL context
parameters." }
+ "healthCheckBundles": { "index": 14, "kind": "property", "displayName":
"Health Check Bundles", "group": "advanced", "label": "advanced", "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 the server
readiness check also requires activation of OPA's configured [...]
+ "opaClient": { "index": 15, "kind": "property", "displayName": "Opa
Client", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "com.styra.opa.OPAClient", "deprecated": false,
"autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "An existing OPAClient to use. When set,
serverUrl and bearerToken are ignored." },
+ "poolSize": { "index": 16, "kind": "property", "displayName": "Pool Size",
"group": "advanced", "label": "advanced", "required": false, "type": "integer",
"javaType": "int", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": 8, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How many WebAssembly policy instances to pool
in wasm mode. An instance carries mutable state and is not thre [...]
+ "requestTimeout": { "index": 17, "kind": "property", "displayName":
"Request Timeout", "group": "advanced", "label": "advanced", "required": false,
"type": "duration", "javaType": "long", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long to wait for the decision once
connected, in rest mode. A request that times out [...]
+ "healthCheckConsumerEnabled": { "index": 18, "kind": "property",
"displayName": "Health Check Consumer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all consumer based health checks
from this component" },
+ "healthCheckProducerEnabled": { "index": 19, "kind": "property",
"displayName": "Health Check Producer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all producer based health checks
from this component. Notice: Camel has by default disabled all producer based
health-checks. You can turn on produce [...]
+ "bearerToken": { "index": 20, "kind": "property", "displayName": "Bearer
Token", "group": "security", "label": "security", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Bearer token sent to the OPA server in the
Authorization header, for an OPA instance that [...]
+ "failOpen": { "index": 21, "kind": "property", "displayName": "Fail Open",
"group": "security", "label": "security", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "security": "insecure:dev", "defaultValue": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Whether to allow the exchange to proceed when
the policy decision point i [...]
+ "sslContextParameters": { "index": 22, "kind": "property", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "TLS configuration for the connection to the
OPA server in [...]
+ "useGlobalSslContextParameters": { "index": 23, "kind": "property",
"displayName": "Use Global Ssl Context Parameters", "group": "security",
"label": "security", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Enable usage of global SSL context
parameters." }
},
"headers": {
"CamelOpaDecisionAllow": { "index": 0, "kind": "header", "displayName":
"", "group": "producer", "label": "producer", "required": false, "javaType":
"Boolean", "deprecated": false, "autowired": false, "secret": false,
"description": "The allow\/deny verdict of the policy evaluation. Always
overwritten by the component, so a value set by an inbound message never
survives into the route.", "constantName":
"org.apache.camel.component.opa.OpaConstants#DECISION_ALLOW" },
@@ -74,11 +75,12 @@
"lazyStartProducer": { "index": 10, "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 produ [...]
"borrowTimeout": { "index": 11, "kind": "parameter", "displayName":
"Borrow Timeout", "group": "advanced", "label": "advanced", "required": false,
"type": "duration", "javaType": "long", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long an exchange waits for a free
WebAssembly policy instance in wasm mode before the [...]
"connectionTimeout": { "index": 12, "kind": "parameter", "displayName":
"Connection Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "duration", "javaType": "long", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": "10000",
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "How long to wait for the
connection to the OPA server to be established, in rest m [...]
- "opaClient": { "index": 13, "kind": "parameter", "displayName": "Opa
Client", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "com.styra.opa.OPAClient", "deprecated": false,
"autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "An existing OPAClient to use. When set,
serverUrl and bearerToken are ignored." },
- "poolSize": { "index": 14, "kind": "parameter", "displayName": "Pool
Size", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 8, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How many WebAssembly policy instances to pool
in wasm mode. An instance carries mutable state and is not thr [...]
- "requestTimeout": { "index": 15, "kind": "parameter", "displayName":
"Request Timeout", "group": "advanced", "label": "advanced", "required": false,
"type": "duration", "javaType": "long", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long to wait for the decision once
connected, in rest mode. A request that times out [...]
- "bearerToken": { "index": 16, "kind": "parameter", "displayName": "Bearer
Token", "group": "security", "label": "security", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Bearer token sent to the OPA server in the
Authorization header, for an OPA instance tha [...]
- "failOpen": { "index": 17, "kind": "parameter", "displayName": "Fail
Open", "group": "security", "label": "security", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "security": "insecure:dev", "defaultValue": false,
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "Whether to allow the
exchange to proceed when the policy decision point [...]
- "sslContextParameters": { "index": 18, "kind": "parameter", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "TLS configuration for the connection to the
OPA server i [...]
+ "healthCheckBundles": { "index": 13, "kind": "parameter", "displayName":
"Health Check Bundles", "group": "advanced", "label": "advanced", "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 the server
readiness check also requires activation of OPA's configured [...]
+ "opaClient": { "index": 14, "kind": "parameter", "displayName": "Opa
Client", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "com.styra.opa.OPAClient", "deprecated": false,
"autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "An existing OPAClient to use. When set,
serverUrl and bearerToken are ignored." },
+ "poolSize": { "index": 15, "kind": "parameter", "displayName": "Pool
Size", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 8, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How many WebAssembly policy instances to pool
in wasm mode. An instance carries mutable state and is not thr [...]
+ "requestTimeout": { "index": 16, "kind": "parameter", "displayName":
"Request Timeout", "group": "advanced", "label": "advanced", "required": false,
"type": "duration", "javaType": "long", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": "30000", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "How long to wait for the decision once
connected, in rest mode. A request that times out [...]
+ "bearerToken": { "index": 17, "kind": "parameter", "displayName": "Bearer
Token", "group": "security", "label": "security", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "Bearer token sent to the OPA server in the
Authorization header, for an OPA instance tha [...]
+ "failOpen": { "index": 18, "kind": "parameter", "displayName": "Fail
Open", "group": "security", "label": "security", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "security": "insecure:dev", "defaultValue": false,
"configurationClass": "org.apache.camel.component.opa.OpaConfiguration",
"configurationField": "configuration", "description": "Whether to allow the
exchange to proceed when the policy decision point [...]
+ "sslContextParameters": { "index": 19, "kind": "parameter", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.opa.OpaConfiguration", "configurationField":
"configuration", "description": "TLS configuration for the connection to the
OPA server i [...]
}
}
diff --git
a/components/camel-opa/src/generated/resources/META-INF/services/org/apache/camel/bean/OpaSecurityPolicy.json
b/components/camel-opa/src/generated/resources/META-INF/services/org/apache/camel/bean/OpaSecurityPolicy.json
index aa6c5e6247e8..d1504304e6d2 100644
---
a/components/camel-opa/src/generated/resources/META-INF/services/org/apache/camel/bean/OpaSecurityPolicy.json
+++
b/components/camel-opa/src/generated/resources/META-INF/services/org/apache/camel/bean/OpaSecurityPolicy.json
@@ -10,7 +10,7 @@
"groupId": "org.apache.camel",
"artifactId": "camel-opa",
"version": "4.24.0-SNAPSHOT",
- "properties": { "serverUrl": { "index": 0, "kind": "property",
"displayName": "Server Url", "required": false, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": "http:\/\/localhost:8181", "description": "The base URL of the
OPA server, without the \/v1\/data suffix. Not used in wasm mode." },
"policyPath": { "index": 1, "kind": "property", "displayName": "Policy Path",
"required": true, "type": "string", "javaT [...]
+ "properties": { "serverUrl": { "index": 0, "kind": "property",
"displayName": "Server Url", "required": false, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": "http:\/\/localhost:8181", "description": "The base URL of the
OPA server, without the \/v1\/data suffix. Not used in wasm mode." },
"policyPath": { "index": 1, "kind": "property", "displayName": "Policy Path",
"required": true, "type": "string", "javaT [...]
}
}
diff --git a/components/camel-opa/src/main/docs/opa-component.adoc
b/components/camel-opa/src/main/docs/opa-component.adoc
index 0c92bf687881..f1d966bed6bc 100644
--- a/components/camel-opa/src/main/docs/opa-component.adoc
+++ b/components/camel-opa/src/main/docs/opa-component.adoc
@@ -688,6 +688,36 @@ component with `healthCheckProducerEnabled`. The check
reports DOWN with the und
server and a server answering its health endpoint with an error are reported
differently, so a deny is never
confused with an outage.
+Set `healthCheckBundles=true` on the endpoint or `OpaSecurityPolicy` bean to
request
+`/health?bundles=true`. OPA then includes activation/readiness of its
configured bundles and discovery in the
+server's health result. This is useful when a server starts downloading
bundles after startup: a reachable server
+can otherwise report healthy before it has activated its policy bundle. The
default remains the basic `/health`
+check. This option does not itself enable producer health checks or change
policy evaluation.
+
+For example, with producer checks enabled:
+
+[source,java]
+----
+.to("opa:authz/orders/allow?healthCheckBundles=true")
+----
+
+For a policy bean:
+
+[source,yaml]
+----
+- beans:
+ - name: opaPolicy
+ type: org.apache.camel.component.opa.security.OpaSecurityPolicy
+ properties:
+ serverUrl: http://localhost:8181
+ policyPath: authz/orders/allow
+ healthCheckBundles: true
+----
+
+Bundle-aware readiness follows OPA's health semantics. It does not verify a
particular bundle revision,
+guarantee policy freshness, or validate business permissions for a message. It
is unused in `wasm` mode,
+with an injected `opaClient`, or when the corresponding health check is
disabled.
+
`OpaSecurityPolicy` registers an equivalent check, under an id starting
`security-policy:opa-`. It is arguably the
more important of the two: a denied producer merely records a verdict the
route can inspect, while the policy throws
`CamelAuthorizationException` and stops the exchange, so an unreachable server
there fails every message outright.
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 3ec7e5d27174..4d6c8c67d067 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
@@ -74,6 +74,12 @@ public class OpaConfiguration implements Cloneable {
@UriParam(label = "producer")
private boolean batch;
+ @UriParam(label = "advanced", defaultValue = "false",
+ description = "Whether the server readiness check also requires
activation of OPA's configured bundles."
+ + " Sends /health?bundles=true. Does not enable
health checks, change policy evaluation"
+ + " or guarantee a particular policy revision. Not
used in wasm mode or with an injected client.")
+ private boolean healthCheckBundles;
+
@UriParam(label = "advanced",
description = "An existing OPAClient to use. When set, serverUrl
and bearerToken are ignored.")
@Metadata(autowired = true)
@@ -307,6 +313,18 @@ public class OpaConfiguration implements Cloneable {
/**
* An already-configured {@link OPAClient} to use instead of letting the
endpoint create one.
*/
+ public boolean isHealthCheckBundles() {
+ return healthCheckBundles;
+ }
+
+ /**
+ * Whether the server readiness check also requires activation of OPA's
configured bundles. Does not enable health
+ * checks or change policy evaluation. Not used in wasm mode or with an
injected client.
+ */
+ public void setHealthCheckBundles(boolean healthCheckBundles) {
+ this.healthCheckBundles = healthCheckBundles;
+ }
+
public OPAClient getOpaClient() {
return opaClient;
}
diff --git
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaEndpoint.java
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaEndpoint.java
index 434e6473899d..f941042acd8c 100644
---
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaEndpoint.java
+++
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaEndpoint.java
@@ -151,6 +151,9 @@ public class OpaEndpoint extends DefaultEndpoint {
* between the producer and {@code .policy(...)}.
*/
private void warnAboutIgnoredServerOptions() {
+ if (configuration.isHealthCheckBundles()) {
+ LOG.warn("healthCheckBundles is ignored when evaluationMode=wasm:
there is no server to probe");
+ }
if (configuration.getOpaClient() != null) {
LOG.warn("opaClient is ignored when evaluationMode=wasm: the
policy is evaluated in-process");
}
diff --git
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaHealthProbe.java
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaHealthProbe.java
index c1ef4af7618f..a683c42a669c 100644
---
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaHealthProbe.java
+++
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaHealthProbe.java
@@ -117,19 +117,38 @@ public final class OpaHealthProbe implements
AutoCloseable {
public static void probe(
HealthCheckResultBuilder builder, String serverUrl, String
bearerToken, String policyPath,
SSLContext sslContext) {
+ probe(builder, serverUrl, bearerToken, policyPath, sslContext, false);
+ }
+
+ /**
+ * Probes server readiness, optionally requiring activation of OPA's
configured bundles.
+ *
+ * @param healthCheckBundles whether to include OPA's configured bundle
activation in readiness
+ */
+ public static void probe(
+ HealthCheckResultBuilder builder, String serverUrl, String
bearerToken, String policyPath,
+ SSLContext sslContext, boolean healthCheckBundles) {
try (OpaHealthProbe probe = new OpaHealthProbe(sslContext)) {
- probe.probe(builder, serverUrl, bearerToken, policyPath);
+ probe.probe(builder, serverUrl, bearerToken, policyPath,
healthCheckBundles);
}
}
public void probe(HealthCheckResultBuilder builder, String serverUrl,
String bearerToken, String policyPath) {
+ probe(builder, serverUrl, bearerToken, policyPath, false);
+ }
+
+ public void probe(
+ HealthCheckResultBuilder builder, String serverUrl, String
bearerToken, String policyPath,
+ boolean healthCheckBundles) {
builder.detail("opa.serverUrl", URISupport.sanitizeUri(serverUrl));
builder.detail("opa.policyPath", policyPath);
+ builder.detail("opa.healthCheckBundles", healthCheckBundles);
HttpRequest.Builder request = HttpRequest.newBuilder()
// a serverUrl with a trailing slash would build //health,
which OPA's router answers with a
// redirect the client is not configured to follow - reporting
a healthy server DOWN on HTTP 301
- .uri(URI.create(FileUtil.stripTrailingSeparator(serverUrl) +
"/health"))
+ .uri(URI.create(FileUtil.stripTrailingSeparator(serverUrl) +
"/health"
+ + (healthCheckBundles ? "?bundles=true" : "")))
.timeout(TIMEOUT)
.GET();
if (ObjectHelper.isNotEmpty(bearerToken)) {
diff --git
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaProducer.java
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaProducer.java
index d571fe334b73..b0c69da973c4 100644
---
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaProducer.java
+++
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaProducer.java
@@ -61,7 +61,8 @@ public class OpaProducer extends DefaultProducer {
configuration.getServerUrl(),
configuration.getBearerToken(),
// the endpoint URI is unique within the context, so two
endpoints sharing a policy path but
// pointing at different servers get distinct health-check
ids instead of colliding
- getEndpoint().getPolicyPath(),
getEndpoint().getEndpointUri(), getEndpoint().getSslContext());
+ getEndpoint().getPolicyPath(),
getEndpoint().getEndpointUri(), getEndpoint().getSslContext(),
+ configuration.isHealthCheckBundles());
producerHealthCheck.setEnabled(getEndpoint().getComponent().isHealthCheckProducerEnabled());
healthCheckRepository.addHealthCheck(producerHealthCheck);
}
diff --git
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaProducerHealthCheck.java
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaProducerHealthCheck.java
index 91385f25bfc5..2370514b7825 100644
---
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaProducerHealthCheck.java
+++
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/OpaProducerHealthCheck.java
@@ -37,9 +37,15 @@ public class OpaProducerHealthCheck extends
AbstractHealthCheck implements AutoC
private final String bearerToken;
private final String policyPath;
private final OpaHealthProbe probe;
+ private final boolean healthCheckBundles;
public OpaProducerHealthCheck(String serverUrl, String bearerToken, String
policyPath, String id,
SSLContext sslContext) {
+ this(serverUrl, bearerToken, policyPath, id, sslContext, false);
+ }
+
+ public OpaProducerHealthCheck(String serverUrl, String bearerToken, String
policyPath, String id,
+ SSLContext sslContext, boolean
healthCheckBundles) {
// the id is built from the endpoint URI so that two endpoints sharing
a policy path stay distinct, but that
// URI carries the bearerToken in the clear and the id is published in
the health output, so sanitize it
super("camel", "producer:opa-" + URISupport.sanitizeUri(id));
@@ -47,11 +53,12 @@ public class OpaProducerHealthCheck extends
AbstractHealthCheck implements AutoC
this.bearerToken = bearerToken;
this.policyPath = policyPath;
this.probe = new OpaHealthProbe(sslContext);
+ this.healthCheckBundles = healthCheckBundles;
}
@Override
protected void doCall(HealthCheckResultBuilder builder, Map<String,
Object> options) {
- probe.probe(builder, serverUrl, bearerToken, policyPath);
+ probe.probe(builder, serverUrl, bearerToken, policyPath,
healthCheckBundles);
}
@Override
diff --git
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/security/OpaSecurityPolicy.java
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/security/OpaSecurityPolicy.java
index 3dd52eaabdc2..7b21e2aeed4d 100644
---
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/security/OpaSecurityPolicy.java
+++
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/security/OpaSecurityPolicy.java
@@ -137,6 +137,11 @@ public class OpaSecurityPolicy implements
AuthorizationPolicy {
+ " denies every exchange it guards while the
server is unreachable, so a route that cannot"
+ " reach it is not ready.")
private boolean healthCheckEnabled = true;
+ @Metadata(label = "advanced", defaultValue = "false",
+ description = "Whether the server readiness check also requires
activation of OPA's configured bundles."
+ + " Sends /health?bundles=true. Does not enable
health checks, change policy evaluation"
+ + " or guarantee a particular policy revision. Not
used in wasm mode or with an injected client.")
+ private boolean healthCheckBundles;
@Metadata(label = "advanced", defaultValue = "10000",
description = "How long to wait, in milliseconds, for the
connection to the OPA server to be established.")
private long connectionTimeout = 10000;
@@ -234,6 +239,9 @@ public class OpaSecurityPolicy implements
AuthorizationPolicy {
* injected {@code opaClient} address, authenticate to or replace a server
there is none of in {@code wasm} mode.
*/
private void warnIgnoredServerOptions() {
+ if (healthCheckBundles) {
+ LOG.warn("healthCheckBundles is ignored when evaluationMode=wasm:
there is no server to probe");
+ }
if (opaClient != null) {
LOG.warn("opaClient is ignored when evaluationMode=wasm: the
policy is evaluated in-process");
}
@@ -262,7 +270,7 @@ public class OpaSecurityPolicy implements
AuthorizationPolicy {
if (registry == null) {
return;
}
- healthCheck = new OpaSecurityPolicyHealthCheck(serverUrl, bearerToken,
policyPath, sslContext);
+ healthCheck = new OpaSecurityPolicyHealthCheck(serverUrl, bearerToken,
policyPath, sslContext, healthCheckBundles);
registry.register(healthCheck);
}
@@ -557,6 +565,18 @@ public class OpaSecurityPolicy implements
AuthorizationPolicy {
this.healthCheckEnabled = healthCheckEnabled;
}
+ public boolean isHealthCheckBundles() {
+ return healthCheckBundles;
+ }
+
+ /**
+ * Whether the server readiness check also requires activation of OPA's
configured bundles. Does not enable health
+ * checks or change policy evaluation. Not used in wasm mode or with an
injected client.
+ */
+ public void setHealthCheckBundles(boolean healthCheckBundles) {
+ this.healthCheckBundles = healthCheckBundles;
+ }
+
public OPAClient getOpaClient() {
return opaClient;
}
diff --git
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/security/OpaSecurityPolicyHealthCheck.java
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/security/OpaSecurityPolicyHealthCheck.java
index de154182c1c0..7d632b364b24 100644
---
a/components/camel-opa/src/main/java/org/apache/camel/component/opa/security/OpaSecurityPolicyHealthCheck.java
+++
b/components/camel-opa/src/main/java/org/apache/camel/component/opa/security/OpaSecurityPolicyHealthCheck.java
@@ -39,9 +39,15 @@ public class OpaSecurityPolicyHealthCheck extends
AbstractHealthCheck implements
private final String bearerToken;
private final String policyPath;
private final OpaHealthProbe probe;
+ private final boolean healthCheckBundles;
public OpaSecurityPolicyHealthCheck(String serverUrl, String bearerToken,
String policyPath,
SSLContext sslContext) {
+ this(serverUrl, bearerToken, policyPath, sslContext, false);
+ }
+
+ public OpaSecurityPolicyHealthCheck(String serverUrl, String bearerToken,
String policyPath,
+ SSLContext sslContext, boolean
healthCheckBundles) {
// serverUrl and policyPath together identify the decision this policy
enforces, so two policies pointing at
// different servers stay distinct; sanitized because the id is
published in the health output
super("camel", "security-policy:opa-" +
URISupport.sanitizeUri(serverUrl + "/" + policyPath));
@@ -49,11 +55,12 @@ public class OpaSecurityPolicyHealthCheck extends
AbstractHealthCheck implements
this.bearerToken = bearerToken;
this.policyPath = policyPath;
this.probe = new OpaHealthProbe(sslContext);
+ this.healthCheckBundles = healthCheckBundles;
}
@Override
protected void doCall(HealthCheckResultBuilder builder, Map<String,
Object> options) {
- probe.probe(builder, serverUrl, bearerToken, policyPath);
+ probe.probe(builder, serverUrl, bearerToken, policyPath,
healthCheckBundles);
}
@Override
diff --git
a/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaHealthCheckRegistrationTest.java
b/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaHealthCheckRegistrationTest.java
index e62274016043..ef0c86dc6827 100644
---
a/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaHealthCheckRegistrationTest.java
+++
b/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaHealthCheckRegistrationTest.java
@@ -16,8 +16,12 @@
*/
package org.apache.camel.component.opa;
+import java.net.InetSocketAddress;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+import com.sun.net.httpserver.HttpServer;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.health.HealthCheck;
import org.apache.camel.health.HealthCheckHelper;
@@ -74,4 +78,55 @@ public class OpaHealthCheckRegistrationTest extends
CamelTestSupport {
assertThat(ids).anySatisfy(id ->
assertThat(id).contains("opa-primary"));
assertThat(ids).anySatisfy(id ->
assertThat(id).contains("opa-secondary"));
}
+
+ @Test
+ void passesTheEndpointBundleRequirementToItsRegisteredCheck() throws
Exception {
+ HttpServer server = HttpServer.create(new
InetSocketAddress("localhost", 0), 0);
+ AtomicReference<String> query = new AtomicReference<>();
+ server.createContext("/health", exchange -> {
+ query.set(exchange.getRequestURI().getRawQuery());
+ exchange.sendResponseHeaders(200, -1);
+ exchange.close();
+ });
+ server.start();
+ try {
+ OpaEndpoint endpoint = context.getEndpoint(
+ "opa:authz/bundles?serverUrl=http://localhost:" +
server.getAddress().getPort(), OpaEndpoint.class);
+ endpoint.getConfiguration().setHealthCheckBundles(true);
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:bundles").to(endpoint);
+ }
+ });
+ HealthCheck check = registeredChecks().stream()
+ .filter(hc -> hc.getId().contains("authz/bundles"))
+ .findFirst().orElseThrow();
+ check.setEnabled(true);
+
+
assertThat(check.call(Map.of()).getState()).isEqualTo(HealthCheck.State.UP);
+ assertThat(query.get()).isEqualTo("bundles=true");
+ } finally {
+ server.stop(0);
+ }
+ }
+
+ @Test
+ void skipsTheServerProbeInWasmModeEvenWhenBundlesAreRequired() throws
Exception {
+ OpaConfiguration configuration = new OpaConfiguration();
+ configuration.setEvaluationMode("wasm");
+ configuration.setHealthCheckBundles(true);
+ OpaEndpoint endpoint = new OpaEndpoint("opa:authz/wasm", new
OpaComponent(context), configuration);
+ OpaProducer producer = new OpaProducer(endpoint);
+ int previousCount = registeredChecks().size();
+ try {
+ // Exercise the producer's registration independently from loading
a compiled WASM fixture.
+ producer.start();
+
+ assertThat(registeredChecks()).hasSize(previousCount);
+ } finally {
+ producer.stop();
+ }
+ }
+
}
diff --git
a/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaProducerHealthCheckTest.java
b/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaProducerHealthCheckTest.java
index 7e0ee58d1cbb..cca01af3384a 100644
---
a/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaProducerHealthCheckTest.java
+++
b/components/camel-opa/src/test/java/org/apache/camel/component/opa/OpaProducerHealthCheckTest.java
@@ -19,9 +19,18 @@ package org.apache.camel.component.opa;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
+import java.security.KeyStore;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsServer;
import org.apache.camel.health.HealthCheck;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -107,4 +116,70 @@ class OpaProducerHealthCheckTest {
assertThat(result.getMessage()).get().asString().contains("Cannot
reach the OPA server");
assertThat(result.getError()).isPresent();
}
+
+ @Test
+ void includesBundleActivationOnlyWhenEnabled() throws Exception {
+ AtomicBoolean activated = new AtomicBoolean();
+ AtomicReference<String> query = new AtomicReference<>();
+ AtomicReference<String> authorization = new AtomicReference<>();
+ server = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
+ server.createContext("/health", exchange -> {
+ query.set(exchange.getRequestURI().getRawQuery());
+
authorization.set(exchange.getRequestHeaders().getFirst("Authorization"));
+ int status = "bundles=true".equals(query.get()) &&
!activated.get() ? 500 : 200;
+ exchange.sendResponseHeaders(status, -1);
+ exchange.close();
+ });
+ server.start();
+ String serverUrl = "http://localhost:" + server.getAddress().getPort();
+
+ assertThat(call(serverUrl).getState()).isEqualTo(HealthCheck.State.UP);
+ assertThat(query.get()).isNull();
+
+ OpaProducerHealthCheck bundleCheck = new OpaProducerHealthCheck(
+ serverUrl + "/", "test-token", "authz/allow", "bundles", null,
true);
+ bundleCheck.setEnabled(true);
+ HealthCheck.Result notActivated = bundleCheck.call(Map.of());
+
+ assertThat(notActivated.getState()).isEqualTo(HealthCheck.State.DOWN);
+
assertThat(notActivated.getDetails()).containsEntry("opa.healthCheckBundles",
true);
+ assertThat(query.get()).isEqualTo("bundles=true");
+ assertThat(authorization.get()).isEqualTo("Bearer test-token");
+
+ activated.set(true);
+
assertThat(bundleCheck.call(Map.of()).getState()).isEqualTo(HealthCheck.State.UP);
+ }
+
+ @Test
+ void preservesTlsConfigurationWhenCheckingBundles() throws Exception {
+ KeyStore fixture = KeyStore.getInstance("PKCS12");
+ try (var in = getClass().getResourceAsStream("/opa-server.p12")) {
+ fixture.load(in, "changeit".toCharArray());
+ }
+ KeyManagerFactory keys =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ keys.init(fixture, "changeit".toCharArray());
+ SSLContext serverTls = SSLContext.getInstance("TLS");
+ serverTls.init(keys.getKeyManagers(), null, null);
+ TrustManagerFactory trust =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trust.init(fixture);
+ SSLContext clientTls = SSLContext.getInstance("TLS");
+ clientTls.init(null, trust.getTrustManagers(), null);
+ HttpsServer https = HttpsServer.create(new
InetSocketAddress("localhost", 0), 0);
+ https.setHttpsConfigurator(new HttpsConfigurator(serverTls));
+ server = https;
+ AtomicReference<String> query = new AtomicReference<>();
+ https.createContext("/health", exchange -> {
+ query.set(exchange.getRequestURI().getRawQuery());
+ exchange.sendResponseHeaders(200, -1);
+ exchange.close();
+ });
+ https.start();
+ OpaProducerHealthCheck check = new OpaProducerHealthCheck(
+ "https://localhost:" + https.getAddress().getPort(), null,
"authz/allow", "tls-bundles", clientTls, true);
+ check.setEnabled(true);
+
+
assertThat(check.call(Map.of()).getState()).isEqualTo(HealthCheck.State.UP);
+ assertThat(query.get()).isEqualTo("bundles=true");
+ }
+
}
diff --git
a/components/camel-opa/src/test/java/org/apache/camel/component/opa/security/OpaSecurityPolicyHealthCheckTest.java
b/components/camel-opa/src/test/java/org/apache/camel/component/opa/security/OpaSecurityPolicyHealthCheckTest.java
index 5042ea75839c..7aa43f8c2234 100644
---
a/components/camel-opa/src/test/java/org/apache/camel/component/opa/security/OpaSecurityPolicyHealthCheckTest.java
+++
b/components/camel-opa/src/test/java/org/apache/camel/component/opa/security/OpaSecurityPolicyHealthCheckTest.java
@@ -21,6 +21,8 @@ import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import com.styra.opa.OPAClient;
import com.sun.net.httpserver.HttpServer;
@@ -45,6 +47,8 @@ public class OpaSecurityPolicyHealthCheckTest extends
CamelTestSupport {
private static HttpServer server;
private static String serverUrl;
+ private static final AtomicBoolean bundlesActivated = new AtomicBoolean();
+ private static final AtomicReference<String> query = new
AtomicReference<>();
private final OpaSecurityPolicy policy = new OpaSecurityPolicy();
@@ -59,7 +63,9 @@ public class OpaSecurityPolicyHealthCheckTest extends
CamelTestSupport {
private static String startHealthyServer() throws IOException {
server = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
server.createContext("/health", exchange -> {
- exchange.sendResponseHeaders(200, -1);
+ query.set(exchange.getRequestURI().getRawQuery());
+ int status = "bundles=true".equals(query.get()) &&
!bundlesActivated.get() ? 500 : 200;
+ exchange.sendResponseHeaders(status, -1);
try (OutputStream out = exchange.getResponseBody()) {
out.flush();
}
@@ -70,6 +76,8 @@ public class OpaSecurityPolicyHealthCheckTest extends
CamelTestSupport {
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
+ bundlesActivated.set(false);
+ query.set(null);
serverUrl = startHealthyServer();
policy.setPolicyPath("authz/allow");
policy.setServerUrl(serverUrl);
@@ -172,4 +180,25 @@ public class OpaSecurityPolicyHealthCheckTest extends
CamelTestSupport {
// an injected client may point anywhere, so probing serverUrl would
report on the wrong server
assertThat(registered()).hasSize(1);
}
+
+ @Test
+ void passesThePolicyBundleRequirementToItsRegisteredCheck() throws
Exception {
+ OpaSecurityPolicy bundlePolicy = new OpaSecurityPolicy(serverUrl +
"/", "authz/bundles");
+ bundlePolicy.setHealthCheckBundles(true);
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+
from("direct:bundles").policy(bundlePolicy).to("mock:bundleResult");
+ }
+ });
+ HealthCheck check = registered().stream()
+ .filter(hc -> hc.getId().contains("authz/bundles"))
+ .findFirst().orElseThrow();
+
+
assertThat(check.call(Map.of()).getState()).isEqualTo(HealthCheck.State.DOWN);
+ assertThat(query.get()).isEqualTo("bundles=true");
+ bundlesActivated.set(true);
+
assertThat(check.call(Map.of()).getState()).isEqualTo(HealthCheck.State.UP);
+ }
+
}
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 44cec1caac9f..87e1e159cc36 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
@@ -355,6 +355,26 @@ public interface OpaComponentBuilderFactory {
return this;
}
+
+ /**
+ * Whether the server readiness check also requires activation of OPA's
+ * configured bundles. Sends /health?bundles=true. Does not enable
+ * health checks, change policy evaluation or guarantee a particular
+ * policy revision. Not used in wasm mode or with an injected client.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: advanced
+ *
+ * @param healthCheckBundles the value to set
+ * @return the dsl builder
+ */
+ default OpaComponentBuilder healthCheckBundles(boolean
healthCheckBundles) {
+ doSetProperty("healthCheckBundles", healthCheckBundles);
+ return this;
+ }
+
/**
* An existing OPAClient to use. When set, serverUrl and bearerToken
are
* ignored.
@@ -562,6 +582,7 @@ public interface OpaComponentBuilderFactory {
case "autowiredEnabled": ((OpaComponent)
component).setAutowiredEnabled((boolean) value); return true;
case "borrowTimeout": getOrCreateConfiguration((OpaComponent)
component).setBorrowTimeout((long) value); return true;
case "connectionTimeout": getOrCreateConfiguration((OpaComponent)
component).setConnectionTimeout((long) value); return true;
+ case "healthCheckBundles": getOrCreateConfiguration((OpaComponent)
component).setHealthCheckBundles((boolean) value); return true;
case "opaClient": getOrCreateConfiguration((OpaComponent)
component).setOpaClient((com.styra.opa.OPAClient) value); return true;
case "poolSize": getOrCreateConfiguration((OpaComponent)
component).setPoolSize((int) value); return true;
case "requestTimeout": getOrCreateConfiguration((OpaComponent)
component).setRequestTimeout((long) value); return true;
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 0f2697bd44aa..5a2e8f2ebf7b 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
@@ -505,6 +505,42 @@ public interface OpaEndpointBuilderFactory {
doSetProperty("connectionTimeout", connectionTimeout);
return this;
}
+ /**
+ * Whether the server readiness check also requires activation of OPA's
+ * configured bundles. Sends /health?bundles=true. Does not enable
+ * health checks, change policy evaluation or guarantee a particular
+ * policy revision. Not used in wasm mode or with an injected client.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: advanced
+ *
+ * @param healthCheckBundles the value to set
+ * @return the dsl builder
+ */
+ default AdvancedOpaEndpointBuilder healthCheckBundles(boolean
healthCheckBundles) {
+ doSetProperty("healthCheckBundles", healthCheckBundles);
+ return this;
+ }
+ /**
+ * Whether the server readiness check also requires activation of OPA's
+ * configured bundles. Sends /health?bundles=true. Does not enable
+ * health checks, change policy evaluation or guarantee a particular
+ * policy revision. Not used in wasm mode or with an injected client.
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: advanced
+ *
+ * @param healthCheckBundles the value to set
+ * @return the dsl builder
+ */
+ default AdvancedOpaEndpointBuilder healthCheckBundles(String
healthCheckBundles) {
+ doSetProperty("healthCheckBundles", healthCheckBundles);
+ return this;
+ }
/**
* An existing OPAClient to use. When set, serverUrl and bearerToken
are
* ignored.