Skip to content

Commit

Permalink
Refactor TLS and network handling
Browse files Browse the repository at this point in the history
  • Loading branch information
melloware committed Jun 15, 2024
1 parent 30d7fc5 commit ab96a74
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.jboss.logging.Logger;

import io.quarkiverse.quinoa.QuinoaDevProxyHandlerConfig;
import io.quarkiverse.quinoa.QuinoaNetworkConfiguration;
import io.quarkiverse.quinoa.QuinoaRecorder;
import io.quarkiverse.quinoa.deployment.config.DevServerConfig;
import io.quarkiverse.quinoa.deployment.config.QuinoaConfig;
Expand Down Expand Up @@ -78,9 +79,8 @@ public ForwardedDevServerBuildItem prepareDevService(
final QuinoaConfig resolvedConfig = configuredQuinoa.resolvedConfig();
final DevServerConfig devServerConfig = resolvedConfig.devServer();
liveReload.setContextObject(QuinoaConfig.class, resolvedConfig);
final String configuredDevServerHost = devServerConfig.host();
final boolean configuredTls = devServerConfig.tls();
final boolean configuredTlsAllowInsecure = devServerConfig.tlsAllowInsecure();
final QuinoaNetworkConfiguration networkConfiguration = new QuinoaNetworkConfiguration(devServerConfig.tls(),
devServerConfig.tlsAllowInsecure(), devServerConfig.host(), devServerConfig.port().get(), false);
final PackageManagerRunner packageManagerRunner = installedPackageManager.getPackageManager();
final String checkPath = resolvedConfig.devServer().checkPath().orElse(null);
if (devService != null) {
Expand All @@ -94,13 +94,9 @@ public ForwardedDevServerBuildItem prepareDevService(
}
LOG.debug("Quinoa config did not change; no need to restart.");
devServices.produce(devService.toBuildItem());
final String resolvedDevServerHost = PackageManagerRunner.isDevServerUp(devServerConfig.tls(),
devServerConfig.tlsAllowInsecure(),
devServerConfig.host(),
devServerConfig.port().get(),
final String resolvedDevServerHost = PackageManagerRunner.isDevServerUp(networkConfiguration,
checkPath);
return new ForwardedDevServerBuildItem(devServerConfig.tls(), devServerConfig.tlsAllowInsecure(),
resolvedDevServerHost, devServerConfig.port().get());
return new ForwardedDevServerBuildItem(networkConfiguration);
}
shutdownDevService();
}
Expand All @@ -118,15 +114,15 @@ public ForwardedDevServerBuildItem prepareDevService(
if (!isDevServerMode(configuredQuinoa.resolvedConfig())) {
return null;
}
final Integer port = devServerConfig.port().get();
final Integer port = networkConfiguration.getPort();

if (!devServerConfig.managed()) {
// No need to start the dev-service it is not managed by Quinoa
// We just check that it is up
final String resolvedHostIPAddress = PackageManagerRunner.isDevServerUp(configuredTls, configuredTlsAllowInsecure,
configuredDevServerHost, port, checkPath);
final String resolvedHostIPAddress = PackageManagerRunner.isDevServerUp(networkConfiguration, checkPath);
if (resolvedHostIPAddress != null) {
return new ForwardedDevServerBuildItem(configuredTls, configuredTlsAllowInsecure, resolvedHostIPAddress, port);
networkConfiguration.setHost(resolvedHostIPAddress);
return new ForwardedDevServerBuildItem(networkConfiguration);
} else {
throw new IllegalStateException(
"The Web UI dev server (configured as not managed by Quinoa) is not started on port: " + port);
Expand All @@ -141,9 +137,7 @@ public ForwardedDevServerBuildItem prepareDevService(
final AtomicReference<Process> dev = new AtomicReference<>();
PackageManagerRunner.DevServer devServer = null;
try {
devServer = packageManagerRunner.dev(consoleInstalled, loggingSetup, configuredTls, configuredTlsAllowInsecure,
configuredDevServerHost,
port,
devServer = packageManagerRunner.dev(consoleInstalled, loggingSetup, networkConfiguration,
checkPath,
checkTimeout);
dev.set(devServer.process());
Expand All @@ -162,7 +156,8 @@ public ForwardedDevServerBuildItem prepareDevService(
devService = new DevServicesResultBuildItem.RunningDevService(
DEV_SERVICE_NAME, null, onClose, devServerConfigMap);
devServices.produce(devService.toBuildItem());
return new ForwardedDevServerBuildItem(configuredTls, configuredTlsAllowInsecure, devServer.hostIPAddress(), port);
networkConfiguration.setHost(devServer.hostIPAddress());
return new ForwardedDevServerBuildItem(networkConfiguration);
} catch (Throwable t) {
packageManagerRunner.stopDev(dev.get());
if (devServer != null) {
Expand Down Expand Up @@ -206,11 +201,12 @@ public void runtimeInit(
}
LOG.infof("Quinoa is forwarding unhandled requests to port: %d", devProxy.get().getPort());
final QuinoaDevProxyHandlerConfig handlerConfig = toDevProxyHandlerConfig(quinoaConfig, httpBuildTimeConfig);
final QuinoaNetworkConfiguration networkConfig = new QuinoaNetworkConfiguration(devProxy.get().isTls(),
devProxy.get().isTlsAllowInsecure(), devProxy.get().getHost(),
devProxy.get().getPort(),
quinoaConfig.devServer().websocket());
routes.produce(RouteBuildItem.builder().orderedRoute("/*", QUINOA_ROUTE_ORDER)
.handler(recorder.quinoaProxyDevHandler(handlerConfig, vertx.getVertx(), devProxy.get().isTls(),
devProxy.get().isTlsAllowInsecure(), devProxy.get().getHost(),
devProxy.get().getPort(),
quinoaConfig.devServer().websocket()))
.handler(recorder.quinoaProxyDevHandler(handlerConfig, vertx.getVertx(), networkConfig))
.build());
if (quinoaConfig.devServer().websocket()) {
websocketSubProtocols.produce(new WebsocketSubProtocolsBuildItem("*"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
package io.quarkiverse.quinoa.deployment.items;

import io.quarkiverse.quinoa.QuinoaNetworkConfiguration;
import io.quarkus.builder.item.SimpleBuildItem;

public final class ForwardedDevServerBuildItem extends SimpleBuildItem {

private final boolean tls;
private final boolean tlsAllowInsecure;
private final String host;
private final Integer port;
private final QuinoaNetworkConfiguration networkConfiguration;

public ForwardedDevServerBuildItem(boolean tls, boolean tlsAllowInsecure, String host, Integer port) {
this.tls = tls;
this.tlsAllowInsecure = tlsAllowInsecure;
this.host = host;
this.port = port;
public ForwardedDevServerBuildItem(QuinoaNetworkConfiguration networkConfiguration) {
this.networkConfiguration = networkConfiguration;
}

public QuinoaNetworkConfiguration getNetworkConfiguration() {
return networkConfiguration;
}

public boolean isTls() {
return tls;
return networkConfiguration.isTls();
}

public boolean isTlsAllowInsecure() {
return tlsAllowInsecure;
return networkConfiguration.isTlsAllowInsecure();
}

public String getHost() {
return host;
return networkConfiguration.getHost();
}

public Integer getPort() {
return port;
return networkConfiguration.getPort();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import org.jboss.logging.Logger;

import io.quarkiverse.quinoa.QuinoaNetworkConfiguration;
import io.quarkiverse.quinoa.deployment.SslUtil;
import io.quarkiverse.quinoa.deployment.config.PackageManagerCommandConfig;
import io.quarkiverse.quinoa.deployment.packagemanager.types.PackageManager;
Expand Down Expand Up @@ -139,7 +140,7 @@ private static void killDescendants(ProcessHandle process, boolean force) {
}

public DevServer dev(Optional<ConsoleInstalledBuildItem> consoleInstalled, LoggingSetupBuildItem loggingSetup,
boolean tls, boolean tlsAllowInsecure, String devServerHost, int devServerPort, String checkPath,
QuinoaNetworkConfiguration network, String checkPath,
int checkTimeout) {
final PackageManager.Command dev = packageManager.dev();
LOG.infof("Running Quinoa package manager live coding as a dev service: %s", dev.commandWithArguments);
Expand All @@ -156,16 +157,16 @@ public void run() {
});
if (checkPath == null) {
LOG.infof("Quinoa is configured to continue without check if the live coding server is up");
return new DevServer(p, devServerHost, logCompressor);
return new DevServer(p, network.getHost(), logCompressor);
}
String ipAddress = null;
try {
int i = 0;
while ((ipAddress = isDevServerUp(tls, tlsAllowInsecure, devServerHost, devServerPort, checkPath)) == null) {
while ((ipAddress = isDevServerUp(network, checkPath)) == null) {
if (++i >= checkTimeout / 500) {
stopDev(p);
throw new RuntimeException(
"Quinoa package manager live coding port " + devServerPort
"Quinoa package manager live coding port " + network.getPort()
+ " is still not listening after the checkTimeout.");
}
Thread.sleep(500);
Expand Down Expand Up @@ -275,22 +276,23 @@ public void run() {
}
}

public static String isDevServerUp(boolean tls, boolean tlsAllowInsecure, String host, int port, String path) {
public static String isDevServerUp(QuinoaNetworkConfiguration network, String path) {
if (path == null) {
return host;
return network.getHost();
}
final String normalizedPath = path.indexOf("/") == 0 ? path : "/" + path;
try {
InetAddress[] addresses = InetAddress.getAllByName(host);
InetAddress[] addresses = InetAddress.getAllByName(network.getHost());
for (InetAddress address : addresses) {
try {
final String hostAddress = address.getHostAddress();
final String ipAddress = address instanceof Inet6Address ? "[" + hostAddress + "]" : hostAddress;
URL url = new URL(String.format("%s://%s:%d%s", tls ? "https" : "http", ipAddress, port, normalizedPath));
URL url = new URL(String.format("%s://%s:%d%s", network.isTls() ? "https" : "http", ipAddress,
network.getPort(), normalizedPath));
HttpURLConnection connection;
if (tls) {
if (network.isTls()) {
HttpsURLConnection httpsConnection = (HttpsURLConnection) url.openConnection();
if (tlsAllowInsecure) {
if (network.isTlsAllowInsecure()) {
httpsConnection.setSSLSocketFactory(SslUtil.createNonValidatingSslContext().getSocketFactory());
httpsConnection.setHostnameVerifier(new HostnameVerifier() {
@Override
Expand Down
55 changes: 29 additions & 26 deletions docs/modules/ROOT/pages/includes/quarkus-quinoa.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -519,70 +519,73 @@ endif::add-copy-button-to-env-var[]
--|boolean
|`true`

a|icon:lock[title=Fixed at build time] [[quarkus-quinoa_quarkus-quinoa-dev-server-tls]]`link:#quarkus-quinoa_quarkus-quinoa-dev-server-tls[quarkus.quinoa.dev-server.tls]`

a|icon:lock[title=Fixed at build time] [[quarkus-quinoa_quarkus-quinoa-dev-server-port]]`link:#quarkus-quinoa_quarkus-quinoa-dev-server-port[quarkus.quinoa.dev-server.port]`


[.description]
--
When set to true, Quinoa requests will be forwarded with tls enabled.
Port of the server to forward requests to. The dev server process (i.e npm start) is managed like a dev service by Quarkus. If the external server responds with a 404, it is ignored by Quinoa and processed like any other backend request.

ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_QUINOA_DEV_SERVER_TLS+++[]
Environment variable: env_var_with_copy_button:+++QUARKUS_QUINOA_DEV_SERVER_PORT+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_QUINOA_DEV_SERVER_TLS+++`
Environment variable: `+++QUARKUS_QUINOA_DEV_SERVER_PORT+++`
endif::add-copy-button-to-env-var[]
--|boolean
|`false`
--|int
|`framework detection or fallback to empty`

a|icon:lock[title=Fixed at build time] [[quarkus-quinoa_quarkus-quinoa-dev-server-tls-allow-insecure]]`link:#quarkus-quinoa_quarkus-quinoa-dev-server-tls-allow-insecure[quarkus.quinoa.dev-server.tls.allow-insecure]`

a|icon:lock[title=Fixed at build time] [[quarkus-quinoa_quarkus-quinoa-dev-server-host]]`link:#quarkus-quinoa_quarkus-quinoa-dev-server-host[quarkus.quinoa.dev-server.host]`


[.description]
--
When set to true, Quinoa will accept any certificate with any hostname.
Host of the server to forward requests to.

ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_QUINOA_DEV_SERVER_TLS_ALLOW_INSECURE+++[]
Environment variable: env_var_with_copy_button:+++QUARKUS_QUINOA_DEV_SERVER_HOST+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_QUINOA_DEV_SERVER_TLS_ALLOW_INSECURE+++`
Environment variable: `+++QUARKUS_QUINOA_DEV_SERVER_HOST+++`
endif::add-copy-button-to-env-var[]
--|boolean
|`false`
--|string
|`localhost`

a|icon:lock[title=Fixed at build time] [[quarkus-quinoa_quarkus-quinoa-dev-server-port]]`link:#quarkus-quinoa_quarkus-quinoa-dev-server-port[quarkus.quinoa.dev-server.port]`

a|icon:lock[title=Fixed at build time] [[quarkus-quinoa_quarkus-quinoa-dev-server-tls]]`link:#quarkus-quinoa_quarkus-quinoa-dev-server-tls[quarkus.quinoa.dev-server.tls]`


[.description]
--
Port of the server to forward requests to. The dev server process (i.e npm start) is managed like a dev service by Quarkus. If the external server responds with a 404, it is ignored by Quinoa and processed like any other backend request.
When set to true, Quinoa requests will be forwarded with tls enabled.

ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_QUINOA_DEV_SERVER_PORT+++[]
Environment variable: env_var_with_copy_button:+++QUARKUS_QUINOA_DEV_SERVER_TLS+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_QUINOA_DEV_SERVER_PORT+++`
Environment variable: `+++QUARKUS_QUINOA_DEV_SERVER_TLS+++`
endif::add-copy-button-to-env-var[]
--|int
|`framework detection or fallback to empty`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-quinoa_quarkus-quinoa-dev-server-host]]`link:#quarkus-quinoa_quarkus-quinoa-dev-server-host[quarkus.quinoa.dev-server.host]`
a|icon:lock[title=Fixed at build time] [[quarkus-quinoa_quarkus-quinoa-dev-server-tls-allow-insecure]]`link:#quarkus-quinoa_quarkus-quinoa-dev-server-tls-allow-insecure[quarkus.quinoa.dev-server.tls-allow-insecure]`


[.description]
--
Host of the server to forward requests to.
When set to true, Quinoa will accept any certificate with any hostname.

ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_QUINOA_DEV_SERVER_HOST+++[]
Environment variable: env_var_with_copy_button:+++QUARKUS_QUINOA_DEV_SERVER_TLS_ALLOW_INSECURE+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_QUINOA_DEV_SERVER_HOST+++`
Environment variable: `+++QUARKUS_QUINOA_DEV_SERVER_TLS_ALLOW_INSECURE+++`
endif::add-copy-button-to-env-var[]
--|string
|`localhost`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-quinoa_quarkus-quinoa-dev-server-check-path]]`link:#quarkus-quinoa_quarkus-quinoa-dev-server-check-path[quarkus.quinoa.dev-server.check-path]`
Expand Down Expand Up @@ -667,7 +670,7 @@ ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_QUINOA_DEV_SERVER_INDEX_PAGE+++`
endif::add-copy-button-to-env-var[]
--|string
|`auto-detected falling back to the quinoa.index-page`
|`auto-detected falling back to index.html`


a|icon:lock[title=Fixed at build time] [[quarkus-quinoa_quarkus-quinoa-dev-server-direct-forwarding]]`link:#quarkus-quinoa_quarkus-quinoa-dev-server-direct-forwarding[quarkus.quinoa.dev-server.direct-forwarding]`
Expand Down Expand Up @@ -776,4 +779,4 @@ endif::add-copy-button-to-env-var[]

|

|===
|===
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import java.util.List;

import io.vertx.ext.web.client.WebClientOptions;
import org.jboss.logging.Logger;

import io.vertx.core.AsyncResult;
Expand All @@ -21,6 +20,7 @@
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;

class QuinoaDevProxyHandler implements Handler<RoutingContext> {
private static final Logger LOG = Logger.getLogger(QuinoaDevProxyHandler.class);
Expand All @@ -30,29 +30,21 @@ class QuinoaDevProxyHandler implements Handler<RoutingContext> {
HttpHeaders.CONTENT_LENGTH.toString(),
HttpHeaders.CONTENT_TYPE.toString());

private final String host;
private final int port;
private final QuinoaNetworkConfiguration networkConfiguration;
private final WebClient client;
private final QuinoaDevWebSocketProxyHandler wsUpgradeHandler;
private final ClassLoader currentClassLoader;
private final QuinoaDevProxyHandlerConfig config;

QuinoaDevProxyHandler(final QuinoaDevProxyHandlerConfig config, final Vertx vertx, boolean tls, boolean tlsAllowInsecure,
String host, int port,
boolean websocket) {
this.host = host;
this.port = port;
QuinoaDevProxyHandler(final QuinoaDevProxyHandlerConfig config, final Vertx vertx, QuinoaNetworkConfiguration network) {
WebClientOptions options = new WebClientOptions();
if (tls) {
options.setSsl(true);
if (tlsAllowInsecure) {
options.setTrustAll(true);
options.setVerifyHost(false);
}
}
options.setSsl(network.isTls());
options.setTrustAll(network.isTlsAllowInsecure());
options.setVerifyHost(!network.isTlsAllowInsecure());
this.client = WebClient.create(vertx, options);
this.wsUpgradeHandler = websocket ? new QuinoaDevWebSocketProxyHandler(vertx, host, port) : null;
this.wsUpgradeHandler = network.isWebsocket() ? new QuinoaDevWebSocketProxyHandler(vertx, network) : null;
this.config = config;
this.networkConfiguration = network;
currentClassLoader = Thread.currentThread().getContextClassLoader();
}

Expand Down Expand Up @@ -97,7 +89,7 @@ private void handleHttpRequest(final RoutingContext ctx, final String resourcePa

// Disable compression in the forwarded request
headers.remove("Accept-Encoding");
client.request(request.method(), port, host, uri)
client.request(request.method(), networkConfiguration.getPort(), networkConfiguration.getHost(), uri)
.putHeaders(headers)
.send(event -> {
if (event.succeeded()) {
Expand Down
Loading

0 comments on commit ab96a74

Please sign in to comment.