This is an automated email from the ASF dual-hosted git repository.
cdeppisch 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 1babc70f2a2 CAMEL-21900: Verify OIDC token on Knative service endpoint
1babc70f2a2 is described below
commit 1babc70f2a20da42e4af89fd28951c7bd83580ed
Author: Christoph Deppisch <[email protected]>
AuthorDate: Wed Mar 26 15:30:52 2025 +0100
CAMEL-21900: Verify OIDC token on Knative service endpoint
- Add Knative service options to enable OIDC support when receiving Knative
events
- OIDC service options define OIDC token path
- Enhance Knative Http service to verify OIDC Authorization headers to
match given token
- Make Knative OIDC service options configurable via environment settings
---
.../camel/component/knative/KnativeEndpoint.java | 3 -
.../knative/http/KnativeHttpConsumer.java | 25 ++++
.../knative/http/KnativeHttpConsumerFactory.java | 22 +++
.../knative/http/KnativeHttpServiceOptions.java | 26 ++++
.../component/knative/http/KnativeHttpSupport.java | 16 +++
.../knative/http/KnativeOidcClientOptions.java | 23 +--
...Options.java => KnativeOidcServiceOptions.java} | 58 +++-----
.../component/knative/http/KnativeHttpTest.java | 154 +++++++++++++++++++++
8 files changed, 270 insertions(+), 57 deletions(-)
diff --git
a/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java
b/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java
index 151d3ed8e3a..00c7511eb52 100644
---
a/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java
+++
b/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java
@@ -131,9 +131,6 @@ public class KnativeEndpoint extends DefaultEndpoint {
Consumer consumer =
getComponent().getOrCreateConsumerFactory().createConsumer(this,
createTransportConfiguration(service), service, pipeline);
- // signal that this path is exposed for knative
- String path = service.getPath();
-
PropertyBindingSupport.build()
.withCamelContext(camelContext)
.withProperties(configuration.getTransportOptions())
diff --git
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumer.java
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumer.java
index a8ee6485f61..8d23a83d7b4 100644
---
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumer.java
+++
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumer.java
@@ -24,6 +24,7 @@ import java.util.function.Predicate;
import java.util.function.Supplier;
import io.vertx.core.buffer.Buffer;
+import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
@@ -36,6 +37,7 @@ import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.NoTypeConversionAvailableException;
import org.apache.camel.Processor;
+import org.apache.camel.RuntimeCamelException;
import org.apache.camel.TypeConverter;
import org.apache.camel.api.management.ManagedAttribute;
import org.apache.camel.api.management.ManagedResource;
@@ -59,6 +61,7 @@ public class KnativeHttpConsumer extends DefaultConsumer {
private final KnativeTransportConfiguration configuration;
private final Predicate<HttpServerRequest> filter;
private final KnativeResource resource;
+ private final KnativeHttpServiceOptions serviceOptions;
private final Supplier<Router> router;
private final HeaderFilterStrategy headerFilterStrategy;
private volatile String path;
@@ -72,11 +75,13 @@ public class KnativeHttpConsumer extends DefaultConsumer {
Endpoint endpoint,
KnativeResource resource,
Supplier<Router> router,
+ KnativeHttpServiceOptions serviceOptions,
Processor processor) {
super(endpoint, processor);
this.configuration = configuration;
this.resource = resource;
this.router = router;
+ this.serviceOptions = serviceOptions;
this.headerFilterStrategy = new KnativeHttpHeaderFilterStrategy();
this.filter =
KnativeHttpSupport.createFilter(this.configuration.getCloudEvent(), resource);
this.preallocateBodyBuffer = true;
@@ -142,6 +147,26 @@ public class KnativeHttpConsumer extends DefaultConsumer {
bodyHandler.setBodyLimit(this.maxBodySize.longValueExact());
}
+ // add OIDC token verification handler
+ if (serviceOptions instanceof KnativeOidcServiceOptions
oidcServiceOptions &&
+ oidcServiceOptions.isOidcEnabled()) {
+ route.handler(routingContext -> {
+ if
(routingContext.request().headers().contains(HttpHeaders.AUTHORIZATION)) {
+ String auth =
routingContext.request().getHeader(HttpHeaders.AUTHORIZATION);
+ String token = oidcServiceOptions.retrieveOidcToken();
+ if (("Bearer " + token).equals(auth)) {
+ routingContext.next();
+ } else {
+ routingContext.fail(401, new
RuntimeCamelException("OIDC request verification failed - forbidden"));
+ }
+ } else {
+ routingContext.fail(401, new RuntimeCamelException(
+ "OIDC request verification failed - " +
+
"missing proper authorization token"));
+ }
+ });
+ }
+
// add body handler
route.handler((RoutingContext event) -> {
event.request().resume();
diff --git
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumerFactory.java
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumerFactory.java
index b05719bb22e..f268d76412e 100644
---
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumerFactory.java
+++
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumerFactory.java
@@ -33,6 +33,7 @@ import org.apache.camel.support.service.ServiceSupport;
public class KnativeHttpConsumerFactory extends ServiceSupport implements
CamelContextAware, KnativeConsumerFactory {
private Router router;
private CamelContext camelContext;
+ private KnativeHttpServiceOptions serviceOptions;
public KnativeHttpConsumerFactory() {
}
@@ -41,6 +42,14 @@ public class KnativeHttpConsumerFactory extends
ServiceSupport implements CamelC
this.camelContext = camelContext;
}
+ @Override
+ protected void doInit() throws Exception {
+ if (serviceOptions == null) {
+ KnativeHttpSupport.lookupServiceOptions(camelContext)
+ .ifPresent(options -> serviceOptions = options);
+ }
+ }
+
public Router getRouter() {
return router;
}
@@ -54,6 +63,18 @@ public class KnativeHttpConsumerFactory extends
ServiceSupport implements CamelC
return this;
}
+ public KnativeHttpServiceOptions getServiceOptions() {
+ return serviceOptions;
+ }
+
+ public void setServiceOptions(KnativeHttpServiceOptions serviceOptions) {
+ if (ServiceHelper.isStarted(this)) {
+ throw new IllegalArgumentException("Can't set the service options
after the service has been started");
+ }
+
+ this.serviceOptions = serviceOptions;
+ }
+
@Override
public void setCamelContext(CamelContext camelContext) {
this.camelContext = camelContext;
@@ -72,6 +93,7 @@ public class KnativeHttpConsumerFactory extends
ServiceSupport implements CamelC
endpoint,
service,
this::lookupRouter,
+ serviceOptions,
processor);
}
diff --git
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpServiceOptions.java
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpServiceOptions.java
new file mode 100644
index 00000000000..b3fba587ebb
--- /dev/null
+++
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpServiceOptions.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.component.knative.http;
+
+import org.apache.camel.CamelContextAware;
+
+/**
+ * Interface specifying Knative service options applied to the exposed Http
service.
+ */
+public interface KnativeHttpServiceOptions extends CamelContextAware {
+}
diff --git
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpSupport.java
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpSupport.java
index a9665be83ec..f0abeea3c4a 100644
---
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpSupport.java
+++
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpSupport.java
@@ -156,4 +156,20 @@ public final class KnativeHttpSupport {
return Optional.empty();
}
+
+ /**
+ * Retrieve service options from given CamelContext.
+ *
+ * @param camelContext the current context.
+ * @return service options or empty
+ */
+ public static Optional<KnativeHttpServiceOptions>
lookupServiceOptions(CamelContext camelContext) {
+ KnativeHttpServiceOptions serviceOptions
+ = CamelContextHelper.findSingleByType(camelContext,
KnativeHttpServiceOptions.class);
+ if (serviceOptions != null) {
+ return Optional.of(serviceOptions);
+ }
+
+ return Optional.empty();
+ }
}
diff --git
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeOidcClientOptions.java
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeOidcClientOptions.java
index ebd278f6339..3e38e87db1d 100644
---
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeOidcClientOptions.java
+++
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeOidcClientOptions.java
@@ -20,7 +20,6 @@ package org.apache.camel.component.knative.http;
import java.io.IOException;
import java.util.Optional;
-import io.vertx.ext.web.client.OAuth2WebClientOptions;
import org.apache.camel.CamelContext;
import org.apache.camel.spi.PropertiesComponent;
import org.apache.camel.support.ResourceHelper;
@@ -37,8 +36,6 @@ public class KnativeOidcClientOptions extends
KnativeSslClientOptions {
private static final String PROPERTY_PREFIX = "camel.knative.client.oidc.";
- private OAuth2WebClientOptions oAuth2ClientOptions;
-
private boolean oidcEnabled;
private String oidcTokenPath;
@@ -47,6 +44,8 @@ public class KnativeOidcClientOptions extends
KnativeSslClientOptions {
private boolean cacheTokens = true;
+ private boolean renewTokenOnForbidden = true;
+
public KnativeOidcClientOptions() {
}
@@ -61,10 +60,6 @@ public class KnativeOidcClientOptions extends
KnativeSslClientOptions {
public void configureOptions(CamelContext camelContext) {
super.configureOptions(camelContext);
- if (oAuth2ClientOptions == null) {
- oAuth2ClientOptions = new
OAuth2WebClientOptions().setRenewTokenOnForbidden(true);
- }
-
PropertiesComponent propertiesComponent =
camelContext.getPropertiesComponent();
boolean oidcEnabled = Boolean.parseBoolean(
@@ -78,7 +73,7 @@ public class KnativeOidcClientOptions extends
KnativeSslClientOptions {
boolean renewTokenOnForbidden = Boolean.parseBoolean(
propertiesComponent.resolveProperty(PROPERTY_PREFIX +
"renew.tokens.on.forbidden").orElse("true"));
-
oAuth2ClientOptions.setRenewTokenOnForbidden(renewTokenOnForbidden);
+ setRenewTokenOnForbidden(renewTokenOnForbidden);
boolean cacheTokens = Boolean.parseBoolean(
propertiesComponent.resolveProperty(PROPERTY_PREFIX +
"cache.tokens").orElse("true"));
@@ -137,18 +132,10 @@ public class KnativeOidcClientOptions extends
KnativeSslClientOptions {
}
public void setRenewTokenOnForbidden(boolean enabled) {
- this.oAuth2ClientOptions.setRenewTokenOnForbidden(enabled);
+ this.renewTokenOnForbidden = enabled;
}
public boolean isRenewTokenOnForbidden() {
- return this.oAuth2ClientOptions.isRenewTokenOnForbidden();
- }
-
- public void setOAuth2ClientOptions(OAuth2WebClientOptions
oAuth2ClientOptions) {
- this.oAuth2ClientOptions = oAuth2ClientOptions;
- }
-
- public OAuth2WebClientOptions getOAuth2ClientOptions() {
- return oAuth2ClientOptions;
+ return this.renewTokenOnForbidden;
}
}
diff --git
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeOidcClientOptions.java
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeOidcServiceOptions.java
similarity index 66%
copy from
components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeOidcClientOptions.java
copy to
components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeOidcServiceOptions.java
index ebd278f6339..1c2c54f274a 100644
---
a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeOidcClientOptions.java
+++
b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeOidcServiceOptions.java
@@ -20,24 +20,19 @@ package org.apache.camel.component.knative.http;
import java.io.IOException;
import java.util.Optional;
-import io.vertx.ext.web.client.OAuth2WebClientOptions;
import org.apache.camel.CamelContext;
import org.apache.camel.spi.PropertiesComponent;
import org.apache.camel.support.ResourceHelper;
import org.apache.camel.util.IOHelper;
/**
- * Knative client options are able to autoconfigure OpenID Connect
authentication with the use of an access token. The
- * path to the OIDC access token is configurable via system property or
environment variable settings. Usually the token
- * is mounted by a Kubernetes volume and gets refreshed over time. The options
provide a procedure to renew the token.
- * Basically that means reading the token again from the given path to get the
updated value. As an alternative to that
- * you can disable token caching so the token is read for each request.
+ * OpenID connect service options implementation grants access to the OIDC
token that should be used to verify client
+ * requests.
*/
-public class KnativeOidcClientOptions extends KnativeSslClientOptions {
+public class KnativeOidcServiceOptions implements KnativeHttpServiceOptions {
+ private static final String PROPERTY_PREFIX =
"camel.knative.service.oidc.";
- private static final String PROPERTY_PREFIX = "camel.knative.client.oidc.";
-
- private OAuth2WebClientOptions oAuth2ClientOptions;
+ private CamelContext camelContext;
private boolean oidcEnabled;
@@ -47,11 +42,18 @@ public class KnativeOidcClientOptions extends
KnativeSslClientOptions {
private boolean cacheTokens = true;
- public KnativeOidcClientOptions() {
+ public KnativeOidcServiceOptions() {
+ }
+
+ public KnativeOidcServiceOptions(CamelContext camelContext) {
+ this.camelContext = camelContext;
+ configureOptions(camelContext);
}
- public KnativeOidcClientOptions(CamelContext camelContext) {
- super(camelContext);
+ public void configureOptions() {
+ if (camelContext != null) {
+ configureOptions(camelContext);
+ }
}
/**
@@ -59,12 +61,6 @@ public class KnativeOidcClientOptions extends
KnativeSslClientOptions {
* Camel context.
*/
public void configureOptions(CamelContext camelContext) {
- super.configureOptions(camelContext);
-
- if (oAuth2ClientOptions == null) {
- oAuth2ClientOptions = new
OAuth2WebClientOptions().setRenewTokenOnForbidden(true);
- }
-
PropertiesComponent propertiesComponent =
camelContext.getPropertiesComponent();
boolean oidcEnabled = Boolean.parseBoolean(
@@ -75,11 +71,6 @@ public class KnativeOidcClientOptions extends
KnativeSslClientOptions {
Optional<String> oidcTokenPath =
propertiesComponent.resolveProperty(PROPERTY_PREFIX + "token.path");
oidcTokenPath.ifPresent(token -> this.oidcTokenPath = token);
- boolean renewTokenOnForbidden = Boolean.parseBoolean(
- propertiesComponent.resolveProperty(PROPERTY_PREFIX +
"renew.tokens.on.forbidden").orElse("true"));
-
-
oAuth2ClientOptions.setRenewTokenOnForbidden(renewTokenOnForbidden);
-
boolean cacheTokens = Boolean.parseBoolean(
propertiesComponent.resolveProperty(PROPERTY_PREFIX +
"cache.tokens").orElse("true"));
setCacheTokens(cacheTokens);
@@ -136,19 +127,14 @@ public class KnativeOidcClientOptions extends
KnativeSslClientOptions {
return oidcTokenPath;
}
- public void setRenewTokenOnForbidden(boolean enabled) {
- this.oAuth2ClientOptions.setRenewTokenOnForbidden(enabled);
- }
-
- public boolean isRenewTokenOnForbidden() {
- return this.oAuth2ClientOptions.isRenewTokenOnForbidden();
- }
-
- public void setOAuth2ClientOptions(OAuth2WebClientOptions
oAuth2ClientOptions) {
- this.oAuth2ClientOptions = oAuth2ClientOptions;
+ @Override
+ public void setCamelContext(CamelContext camelContext) {
+ this.camelContext = camelContext;
+ configureOptions();
}
- public OAuth2WebClientOptions getOAuth2ClientOptions() {
- return oAuth2ClientOptions;
+ @Override
+ public CamelContext getCamelContext() {
+ return camelContext;
}
}
diff --git
a/components/camel-knative/camel-knative-http/src/test/java/org/apache/camel/component/knative/http/KnativeHttpTest.java
b/components/camel-knative/camel-knative-http/src/test/java/org/apache/camel/component/knative/http/KnativeHttpTest.java
index e138f80c247..cf64d5c696f 100644
---
a/components/camel-knative/camel-knative-http/src/test/java/org/apache/camel/component/knative/http/KnativeHttpTest.java
+++
b/components/camel-knative/camel-knative-http/src/test/java/org/apache/camel/component/knative/http/KnativeHttpTest.java
@@ -2476,4 +2476,158 @@ public class KnativeHttpTest {
server.stop();
}
}
+
+ @ParameterizedTest
+ @EnumSource(CloudEvents.class)
+ void testOidcServiceOptions(CloudEvent ce) throws Exception {
+ KnativeComponent component = configureKnativeComponent(
+ context,
+ ce,
+ sourceEvent(
+ "default",
+ Map.of(
+ Knative.KNATIVE_CLOUD_EVENT_TYPE, "myEvent",
+ Knative.CONTENT_TYPE, "text/plain")));
+
+ KnativeOidcServiceOptions serviceOptions = new
KnativeOidcServiceOptions(context);
+ serviceOptions.setOidcEnabled(true);
+ serviceOptions.setOidcTokenPath("classpath:oidc/token.txt");
+
+ if (component.getConsumerFactory() instanceof
KnativeHttpConsumerFactory consumerFactory) {
+ consumerFactory.setServiceOptions(serviceOptions);
+ }
+
+ RouteBuilder.addRoutes(context, b -> {
+ b.from("knative:event/myEvent")
+ .to("mock:ce");
+ });
+
+ context.start();
+
+ MockEndpoint mock = context.getEndpoint("mock:ce", MockEndpoint.class);
+ mock.expectedHeaderReceived(CloudEvent.CAMEL_CLOUD_EVENT_VERSION,
ce.version());
+ mock.expectedHeaderReceived(CloudEvent.CAMEL_CLOUD_EVENT_TYPE,
"myEvent");
+ mock.expectedHeaderReceived(CloudEvent.CAMEL_CLOUD_EVENT_ID,
"myEventID");
+ mock.expectedHeaderReceived(CloudEvent.CAMEL_CLOUD_EVENT_SOURCE,
"/somewhere");
+ mock.expectedHeaderReceived(Exchange.CONTENT_TYPE, "text/plain");
+ mock.expectedMessagesMatches(e ->
e.getMessage().getHeaders().containsKey(CloudEvent.CAMEL_CLOUD_EVENT_TIME));
+ mock.expectedBodiesReceived("test");
+ mock.expectedMessageCount(1);
+
+ given()
+ .body("test")
+ .header(Exchange.CONTENT_TYPE, "text/plain")
+ .header(httpAttribute(ce,
CloudEvent.CAMEL_CLOUD_EVENT_VERSION), ce.version())
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TYPE),
"myEvent")
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_ID),
"myEventID")
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TIME),
+
DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now()))
+ .header(httpAttribute(ce,
CloudEvent.CAMEL_CLOUD_EVENT_SOURCE), "/somewhere")
+ .when()
+ .post()
+ .then()
+ .statusCode(401); // forbidden - missing token
+
+ given()
+ .body("test")
+ .header(Exchange.CONTENT_TYPE, "text/plain")
+ .header("Authorization", "Bearer wrong_token")
+ .header(httpAttribute(ce,
CloudEvent.CAMEL_CLOUD_EVENT_VERSION), ce.version())
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TYPE),
"myEvent")
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_ID),
"myEventID")
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TIME),
+
DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now()))
+ .header(httpAttribute(ce,
CloudEvent.CAMEL_CLOUD_EVENT_SOURCE), "/somewhere")
+ .when()
+ .post()
+ .then()
+ .statusCode(401); // forbidden - wrong token
+
+ given()
+ .body("test")
+ .header(Exchange.CONTENT_TYPE, "text/plain")
+ .header("Authorization", "Bearer whatever_the_token_is")
+ .header(httpAttribute(ce,
CloudEvent.CAMEL_CLOUD_EVENT_VERSION), ce.version())
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TYPE),
"myEvent")
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_ID),
"myEventID")
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TIME),
+
DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now()))
+ .header(httpAttribute(ce,
CloudEvent.CAMEL_CLOUD_EVENT_SOURCE), "/somewhere")
+ .when()
+ .post()
+ .then()
+ .statusCode(200);
+
+ mock.assertIsSatisfied();
+ }
+
+ @ParameterizedTest
+ @EnumSource(CloudEvents.class)
+ void testOidcServiceOptionsPropertyConf(CloudEvent ce) throws Exception {
+
context.getPropertiesComponent().addInitialProperty("camel.knative.service.oidc.enabled",
"true");
+
context.getPropertiesComponent().addInitialProperty("camel.knative.service.oidc.token.path",
+ "classpath:oidc/token.txt");
+
+ KnativeComponent component = configureKnativeComponent(
+ context,
+ ce,
+ sourceEvent(
+ "default",
+ Map.of(
+ Knative.KNATIVE_CLOUD_EVENT_TYPE, "myEvent",
+ Knative.CONTENT_TYPE, "text/plain")));
+
+ RouteBuilder.addRoutes(context, b -> {
+ b.from("knative:event/myEvent")
+ .to("mock:ce");
+ });
+
+ PropertyBindingSupport.build().bind(context, component,
+ "camel.component.knative.consumerFactory.serviceOptions",
+ "#class:" + KnativeOidcServiceOptions.class.getName());
+
+ context.start();
+
+ MockEndpoint mock = context.getEndpoint("mock:ce", MockEndpoint.class);
+ mock.expectedHeaderReceived(CloudEvent.CAMEL_CLOUD_EVENT_VERSION,
ce.version());
+ mock.expectedHeaderReceived(CloudEvent.CAMEL_CLOUD_EVENT_TYPE,
"myEvent");
+ mock.expectedHeaderReceived(CloudEvent.CAMEL_CLOUD_EVENT_ID,
"myEventID");
+ mock.expectedHeaderReceived(CloudEvent.CAMEL_CLOUD_EVENT_SOURCE,
"/somewhere");
+ mock.expectedHeaderReceived(Exchange.CONTENT_TYPE, "text/plain");
+ mock.expectedMessagesMatches(e ->
e.getMessage().getHeaders().containsKey(CloudEvent.CAMEL_CLOUD_EVENT_TIME));
+ mock.expectedBodiesReceived("test");
+ mock.expectedMessageCount(1);
+
+ given()
+ .body("test")
+ .header(Exchange.CONTENT_TYPE, "text/plain")
+ .header("Authorization", "Bearer wrong_token")
+ .header(httpAttribute(ce,
CloudEvent.CAMEL_CLOUD_EVENT_VERSION), ce.version())
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TYPE),
"myEvent")
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_ID),
"myEventID")
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TIME),
+
DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now()))
+ .header(httpAttribute(ce,
CloudEvent.CAMEL_CLOUD_EVENT_SOURCE), "/somewhere")
+ .when()
+ .post()
+ .then()
+ .statusCode(401); // forbidden - wrong token
+
+ given()
+ .body("test")
+ .header(Exchange.CONTENT_TYPE, "text/plain")
+ .header("Authorization", "Bearer whatever_the_token_is")
+ .header(httpAttribute(ce,
CloudEvent.CAMEL_CLOUD_EVENT_VERSION), ce.version())
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TYPE),
"myEvent")
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_ID),
"myEventID")
+ .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TIME),
+
DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now()))
+ .header(httpAttribute(ce,
CloudEvent.CAMEL_CLOUD_EVENT_SOURCE), "/somewhere")
+ .when()
+ .post()
+ .then()
+ .statusCode(200);
+
+ mock.assertIsSatisfied();
+ }
}