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 <cdeppi...@redhat.com>
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();
+    }
 }

Reply via email to