Skip to content

Commit 0abd32f

Browse files
authored
Merge pull request quarkusio#48118 from emattheis/tls-config-in-connector
Add support for setting the TLS configuration name from client connectors in WebSockets Next
2 parents 994a646 + 8e9cff4 commit 0abd32f

11 files changed

+458
-30
lines changed

docs/src/main/asciidoc/websockets-next-reference.adoc

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,16 +1465,41 @@ class MyBean {
14651465

14661466
=== Configuring SSL/TLS
14671467

1468-
To establish a TLS connection, you need to configure a _named_ configuration using the xref:./tls-registry-reference.adoc[TLS registry]:
1468+
To establish a TLS connection, you need to configure a _named_ configuration using the xref:./tls-registry-reference.adoc[TLS registry]. This is typically done via configuration:
14691469

14701470
[source, properties]
14711471
----
14721472
quarkus.tls.my-ws-client.trust-store.p12.path=server-truststore.p12
14731473
quarkus.tls.my-ws-client.trust-store.p12.password=secret
1474+
----
1475+
1476+
With a _named_ TLS configuration established, you can then configure the client to use it:
1477+
1478+
[source, properties]
1479+
----
1480+
quarkus.websockets-next.client.tls-configuration-name=my-ws-client
1481+
----
1482+
1483+
Alternatively, you can supply the configuration name using the <<client-connectors,connector>>:
1484+
1485+
[source, java]
1486+
----
1487+
@Singleton
1488+
public class MyBean {
1489+
1490+
@Inject
1491+
WebSocketConnector<MyEndpoint> connector;
14741492
1475-
quarkus.websockets-next.client.tls-configuration-name=my-ws-client # Reference the named configuration
1493+
public void connect() {
1494+
connector
1495+
.tlsConfigurationName("my-ws-client")
1496+
.connectAndAwait();
1497+
}
1498+
}
14761499
----
14771500

1501+
A name supplied to the connector will override any statically configured name. This can be useful for establishing a default configuration which can be overridden at runtime as necessary.
1502+
14781503
WARNING: When using the WebSocket client, using a _named_ configuration is required to avoid conflicts with other TLS configurations.
14791504
The client will not use the default TLS configuration.
14801505

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package io.quarkus.websockets.next.test.client;
2+
3+
import static org.junit.jupiter.api.Assertions.assertThrows;
4+
5+
import java.io.File;
6+
import java.net.URI;
7+
8+
import jakarta.inject.Inject;
9+
10+
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.api.extension.RegisterExtension;
12+
13+
import io.quarkus.test.QuarkusUnitTest;
14+
import io.quarkus.test.common.http.TestHTTPResource;
15+
import io.quarkus.websockets.next.BasicWebSocketConnector;
16+
import io.quarkus.websockets.next.OnOpen;
17+
import io.quarkus.websockets.next.WebSocket;
18+
import io.smallrye.certs.Format;
19+
import io.smallrye.certs.junit5.Certificate;
20+
import io.smallrye.certs.junit5.Certificates;
21+
22+
@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = {
23+
Format.JKS, Format.PKCS12, Format.PEM }))
24+
public class TlsBasicConnectorMissingTlsConfigurationTest {
25+
26+
@RegisterExtension
27+
public static final QuarkusUnitTest test = new QuarkusUnitTest()
28+
.withApplicationRoot(jar -> jar
29+
.addClasses(ServerEndpoint.class)
30+
.addAsResource(new File("target/certs/ssl-test-keystore.jks"), "keystore.jks")
31+
.addAsResource(new File("target/certs/ssl-test-truststore.jks"), "truststore.jks"))
32+
.overrideConfigKey("quarkus.tls.key-store.jks.path", "keystore.jks")
33+
.overrideConfigKey("quarkus.tls.key-store.jks.password", "secret")
34+
.overrideConfigKey("quarkus.websockets-next.client.tls-configuration-name", "ws-client");
35+
36+
@Inject
37+
BasicWebSocketConnector connector;
38+
39+
@TestHTTPResource(value = "/end", tls = true)
40+
URI uri;
41+
42+
@Test
43+
void testClient() {
44+
assertThrows(IllegalStateException.class, () -> connector
45+
.baseUri(uri)
46+
.path("/{name}")
47+
.pathParam("name", "Lu")
48+
.connectAndAwait());
49+
}
50+
51+
@WebSocket(path = "/end/{name}")
52+
public static class ServerEndpoint {
53+
54+
@OnOpen
55+
void open() {
56+
}
57+
58+
}
59+
60+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package io.quarkus.websockets.next.test.client;
2+
3+
import static org.junit.jupiter.api.Assertions.assertTrue;
4+
5+
import java.io.File;
6+
import java.net.URI;
7+
8+
import jakarta.inject.Inject;
9+
10+
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.api.extension.RegisterExtension;
12+
13+
import io.quarkus.test.QuarkusUnitTest;
14+
import io.quarkus.test.common.http.TestHTTPResource;
15+
import io.quarkus.tls.BaseTlsConfiguration;
16+
import io.quarkus.tls.TlsConfigurationRegistry;
17+
import io.quarkus.websockets.next.BasicWebSocketConnector;
18+
import io.quarkus.websockets.next.OnOpen;
19+
import io.quarkus.websockets.next.WebSocket;
20+
import io.quarkus.websockets.next.WebSocketClientConnection;
21+
import io.smallrye.certs.Format;
22+
import io.smallrye.certs.junit5.Certificate;
23+
import io.smallrye.certs.junit5.Certificates;
24+
import io.vertx.core.net.JksOptions;
25+
import io.vertx.core.net.TrustOptions;
26+
27+
@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = {
28+
Format.JKS, Format.PKCS12, Format.PEM }))
29+
public class TlsBasicConnectorRuntimeTlsConfigurationTest {
30+
31+
@RegisterExtension
32+
public static final QuarkusUnitTest test = new QuarkusUnitTest()
33+
.withApplicationRoot(jar -> jar
34+
.addClasses(ServerEndpoint.class)
35+
.addAsResource(new File("target/certs/ssl-test-keystore.jks"), "keystore.jks")
36+
.addAsResource(new File("target/certs/ssl-test-truststore.jks"), "truststore.jks"))
37+
.overrideConfigKey("quarkus.tls.key-store.jks.path", "keystore.jks")
38+
.overrideConfigKey("quarkus.tls.key-store.jks.password", "secret");
39+
40+
@Inject
41+
BasicWebSocketConnector connector;
42+
43+
@Inject
44+
TlsConfigurationRegistry tlsRegistry;
45+
46+
@TestHTTPResource(value = "/end", tls = true)
47+
URI uri;
48+
49+
@Test
50+
void testClient() {
51+
tlsRegistry.register("ws-client", new BaseTlsConfiguration() {
52+
@Override
53+
public TrustOptions getTrustStoreOptions() {
54+
return new JksOptions().setPath("truststore.jks").setPassword("secret");
55+
}
56+
});
57+
WebSocketClientConnection connection = connector
58+
.tlsConfigurationName("ws-client")
59+
.baseUri(uri)
60+
.path("/{name}")
61+
.pathParam("name", "Lu")
62+
.connectAndAwait();
63+
assertTrue(connection.isOpen());
64+
assertTrue(connection.isSecure());
65+
connection.closeAndAwait();
66+
}
67+
68+
@WebSocket(path = "/end/{name}")
69+
public static class ServerEndpoint {
70+
71+
@OnOpen
72+
void open() {
73+
}
74+
75+
}
76+
77+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package io.quarkus.websockets.next.test.client;
2+
3+
import static org.junit.jupiter.api.Assertions.assertTrue;
4+
5+
import java.io.File;
6+
import java.net.URI;
7+
import java.net.URISyntaxException;
8+
9+
import jakarta.inject.Inject;
10+
11+
import org.junit.jupiter.api.Test;
12+
import org.junit.jupiter.api.extension.RegisterExtension;
13+
14+
import io.quarkus.test.QuarkusUnitTest;
15+
import io.quarkus.test.common.http.TestHTTPResource;
16+
import io.quarkus.websockets.next.BasicWebSocketConnector;
17+
import io.quarkus.websockets.next.OnOpen;
18+
import io.quarkus.websockets.next.WebSocket;
19+
import io.quarkus.websockets.next.WebSocketClientConnection;
20+
import io.smallrye.certs.Format;
21+
import io.smallrye.certs.junit5.Certificate;
22+
import io.smallrye.certs.junit5.Certificates;
23+
24+
@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = {
25+
Format.JKS, Format.PKCS12, Format.PEM }))
26+
public class TlsBasicConnectorTest {
27+
28+
@RegisterExtension
29+
public static final QuarkusUnitTest test = new QuarkusUnitTest()
30+
.withApplicationRoot(jar -> jar
31+
.addClasses(ServerEndpoint.class)
32+
.addAsResource(new File("target/certs/ssl-test-keystore.jks"), "keystore.jks")
33+
.addAsResource(new File("target/certs/ssl-test-truststore.jks"), "truststore.jks"))
34+
.overrideConfigKey("quarkus.tls.key-store.jks.path", "keystore.jks")
35+
.overrideConfigKey("quarkus.tls.key-store.jks.password", "secret")
36+
.overrideConfigKey("quarkus.tls.ws-client.trust-store.jks.path", "truststore.jks")
37+
.overrideConfigKey("quarkus.tls.ws-client.trust-store.jks.password", "secret")
38+
.overrideConfigKey("quarkus.websockets-next.client.tls-configuration-name", "ws-client");
39+
40+
@Inject
41+
BasicWebSocketConnector connector;
42+
43+
@TestHTTPResource(value = "/end", tls = true)
44+
URI uri;
45+
46+
@Test
47+
void testClient() throws URISyntaxException {
48+
assertClient(uri);
49+
URI wssUri = new URI("wss", uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), uri.getQuery(),
50+
uri.getFragment());
51+
assertClient(wssUri);
52+
}
53+
54+
void assertClient(URI uri) {
55+
WebSocketClientConnection connection = connector
56+
.baseUri(uri)
57+
.path("/{name}")
58+
.pathParam("name", "Lu")
59+
.connectAndAwait();
60+
assertTrue(connection.isOpen());
61+
assertTrue(connection.isSecure());
62+
connection.closeAndAwait();
63+
}
64+
65+
@WebSocket(path = "/end/{name}")
66+
public static class ServerEndpoint {
67+
68+
@OnOpen
69+
void open() {
70+
}
71+
72+
}
73+
74+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package io.quarkus.websockets.next.test.client;
2+
3+
import static org.junit.jupiter.api.Assertions.assertThrows;
4+
5+
import java.io.File;
6+
import java.net.URI;
7+
8+
import jakarta.inject.Inject;
9+
10+
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.api.extension.RegisterExtension;
12+
13+
import io.quarkus.test.QuarkusUnitTest;
14+
import io.quarkus.test.common.http.TestHTTPResource;
15+
import io.quarkus.websockets.next.OnOpen;
16+
import io.quarkus.websockets.next.WebSocket;
17+
import io.quarkus.websockets.next.WebSocketClient;
18+
import io.quarkus.websockets.next.WebSocketConnector;
19+
import io.smallrye.certs.Format;
20+
import io.smallrye.certs.junit5.Certificate;
21+
import io.smallrye.certs.junit5.Certificates;
22+
23+
@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = {
24+
Format.JKS, Format.PKCS12, Format.PEM }))
25+
public class TlsClientEndpointMissingTlsConfigurationTest {
26+
27+
@RegisterExtension
28+
static final QuarkusUnitTest config = new QuarkusUnitTest()
29+
.withApplicationRoot((jar) -> jar
30+
.addClasses(ServerEndpoint.class, ClientEndpoint.class)
31+
.addAsResource(new File("target/certs/ssl-test-keystore.jks"), "keystore.jks")
32+
.addAsResource(new File("target/certs/ssl-test-truststore.jks"), "truststore.jks"))
33+
.overrideConfigKey("quarkus.tls.key-store.jks.path", "keystore.jks")
34+
.overrideConfigKey("quarkus.tls.key-store.jks.password", "secret")
35+
.overrideConfigKey("quarkus.websockets-next.client.tls-configuration-name", "ws-client");
36+
37+
@Inject
38+
WebSocketConnector<ClientEndpoint> connector;
39+
40+
@TestHTTPResource(value = "/", tls = true)
41+
URI uri;
42+
43+
@Test
44+
void testClient() {
45+
assertThrows(IllegalStateException.class, () -> connector
46+
.baseUri(uri)
47+
.pathParam("name", "Lu=")
48+
.connectAndAwait());
49+
}
50+
51+
@WebSocket(path = "/endpoint/{name}")
52+
public static class ServerEndpoint {
53+
54+
@OnOpen
55+
void open() {
56+
}
57+
58+
}
59+
60+
@WebSocketClient(path = "/endpoint/{name}")
61+
public static class ClientEndpoint {
62+
63+
@OnOpen
64+
void open() {
65+
}
66+
67+
}
68+
}

0 commit comments

Comments
 (0)