Croway commented on code in PR #28237:
URL: https://github.com/apache/camel/pull/28237#discussion_r4348246471


##########
components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/CamelWebSocketHandler.java:
##########
@@ -403,12 +408,30 @@ public void setConsumer(UndertowConsumer consumer, 
HttpHandler consumerHandler)
                         = new ConsumerHandlers(
                                 consumer.getEndpoint(), consumerHandler != 
null ? consumerHandler : upgradeHandler);
                 producerEndpoints.forEach(this::warnIfProducerSettingsUnused);
+                closePeersThatNoLongerPassChecks();

Review Comment:
   Done in f041456: both methods now use a bounded best-effort send, keeping 
the 1008, no-delivery and route-invocation assertions; the full camel-undertow 
suite passes (238 tests, 0 failures, 1 skipped).



##########
components/camel-undertow/src/test/java/org/apache/camel/component/undertow/spi/SecurityProviderWebSocketConsumerHandlersWindowTest.java:
##########
@@ -0,0 +1,142 @@
+/*
+ * 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.undertow.spi;
+
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.WebSocket;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import io.undertow.websockets.core.CloseMessage;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.undertow.UndertowBasicAuthHandler;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * A WebSocket path whose producer applies the allowed roles while its 
consumer, started later, adds its own handlers on
+ * the same endpoint URI: a connection accepted while only the producer served 
the path runs the allowed-roles check but
+ * not the consumer handlers, so once that consumer is up the connection is 
neither served by the route nor sent
+ * messages, while a connection that goes through the consumer handlers is 
served.
+ */
+class SecurityProviderWebSocketConsumerHandlersWindowTest extends 
AbstractSecurityProviderTest {
+
+    private final AtomicInteger routeInvocations = new AtomicInteger();
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        context.getRegistry().bind("wsHandlers", new 
UndertowBasicAuthHandler());
+        return context;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                // producer and consumer share the same endpoint URI: the 
producer keeps the shared handler
+                // registered and applies allowedRoles, the consumer adds the 
handlers on top
+                from("direct:feed")
+                        
.to("undertow:ws://localhost:{{port}}/guarded?allowedRoles=user&handlers=#wsHandlers&sendToAll=true");
+                
from("undertow:ws://localhost:{{port}}/guarded?allowedRoles=user&handlers=#wsHandlers&sendToAll=true")
+                        .routeId("guarded").autoStartup(false)
+                        .process(exchange -> 
routeInvocations.incrementAndGet())
+                        .to("mock:guarded");
+            }
+        };
+    }
+
+    @Test
+    void connectionAcceptedBeforeAConsumerWithHandlersStartedIsNotServed() 
throws Exception {
+        securityConfiguration.setRoleToAssign("user");
+
+        // only the producer serves the path, so the handshake runs the 
allowed-roles check but not the consumer handlers
+        RecordingListener listener = new RecordingListener();
+        WebSocket webSocket = connect("/guarded", null, listener);
+
+        context.getRouteController().startRoute("guarded");
+
+        // the connection does not get what the producer sends
+        template.sendBody("direct:feed", "broadcast");
+        // and its messages do not reach the route: it is closed instead
+        webSocket.sendText("hello", true).join();
+
+        assertEquals(CloseMessage.MSG_VIOLATES_POLICY, 
listener.closeCode.orTimeout(10, TimeUnit.SECONDS).join());

Review Comment:
   Addressed in e26aaed: registering the consumer now closes existing peers 
that no longer pass the path checks, with a receive-only regression test that 
awaits 1008; the inbound rejection test is kept as separate coverage.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to