Skip to content

Commit

Permalink
Fix #682: Allow to define if dev-server is HTTPS / TLS (#684)
Browse files Browse the repository at this point in the history
* Fix #682: Allow to define if dev-server is HTTPS / TLS

* Fix #682: Pass formatter
  • Loading branch information
ylemoigne authored Jun 13, 2024
1 parent 5d2cfc5 commit dc9c997
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ public ForwardedDevServerBuildItem prepareDevService(
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 PackageManagerRunner packageManagerRunner = installedPackageManager.getPackageManager();
final String checkPath = resolvedConfig.devServer().checkPath().orElse(null);
if (devService != null) {
Expand All @@ -92,7 +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.host(),
final String resolvedDevServerHost = PackageManagerRunner.isDevServerUp(devServerConfig.tls(),
devServerConfig.tlsAllowInsecure(),
devServerConfig.host(),
devServerConfig.port().get(),
checkPath);
return new ForwardedDevServerBuildItem(resolvedDevServerHost, devServerConfig.port().get());
Expand All @@ -118,7 +122,8 @@ public ForwardedDevServerBuildItem prepareDevService(
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(configuredDevServerHost, port, checkPath);
final String resolvedHostIPAddress = PackageManagerRunner.isDevServerUp(configuredTls, configuredTlsAllowInsecure,
configuredDevServerHost, port, checkPath);
if (resolvedHostIPAddress != null) {
return new ForwardedDevServerBuildItem(resolvedHostIPAddress, port);
} else {
Expand All @@ -135,7 +140,8 @@ public ForwardedDevServerBuildItem prepareDevService(
final AtomicReference<Process> dev = new AtomicReference<>();
PackageManagerRunner.DevServer devServer = null;
try {
devServer = packageManagerRunner.dev(consoleInstalled, loggingSetup, configuredDevServerHost,
devServer = packageManagerRunner.dev(consoleInstalled, loggingSetup, configuredTls, configuredTlsAllowInsecure,
configuredDevServerHost,
port,
checkPath,
checkTimeout);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.quarkiverse.quinoa.deployment;

import javax.net.ssl.*;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class SslUtil {
private final static X509ExtendedTrustManager NON_VALIDATING_TRUST_MANAGER = new X509ExtendedTrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException {
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException {
}

@Override
public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException {
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException {
}

@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};

public static SSLContext createNonValidatingSslContext() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { NON_VALIDATING_TRUST_MANAGER }, new SecureRandom());
return sslContext;
} catch (NoSuchAlgorithmException | KeyManagementException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ public interface DevServerConfig {
@WithDefault("localhost")
String host();

/**
* Protocol of the server to forward requests to.
*/
@WithDefault("false")
boolean tls();

/**
* Protocol of the server to forward requests to.
*/
@WithDefault("false")
boolean tlsAllowInsecure();

/**
* After start, Quinoa wait for the external dev server.
* by sending GET requests to this path waiting for a 200 status.
Expand Down Expand Up @@ -100,6 +112,12 @@ static boolean isEqual(DevServerConfig d1, DevServerConfig d2) {
if (!Objects.equals(d1.host(), d2.host())) {
return false;
}
if (!Objects.equals(d1.tls(), d2.tls())) {
return false;
}
if (!Objects.equals(d1.tlsAllowInsecure(), d2.tlsAllowInsecure())) {
return false;
}
if (!Objects.equals(d1.checkPath(), d2.checkPath())) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ public String host() {
return delegate.host();
}

@Override
public boolean tls() {
return delegate.tls();
}

@Override
public boolean tlsAllowInsecure() {
return delegate.tlsAllowInsecure();
}

@Override
public Optional<String> checkPath() {
return delegate.checkPath();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

import io.quarkiverse.quinoa.deployment.SslUtil;
import org.jboss.logging.Logger;

import io.quarkiverse.quinoa.deployment.config.PackageManagerCommandConfig;
Expand All @@ -33,6 +34,10 @@
import io.quarkus.dev.console.QuarkusConsole;
import io.quarkus.runtime.LaunchMode;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

public class PackageManagerRunner {
private static final Logger LOG = Logger.getLogger(PackageManagerRunner.class);
public static final Predicate<Thread> DEV_PROCESS_THREAD_PREDICATE = thread -> thread.getName()
Expand Down Expand Up @@ -134,7 +139,8 @@ private static void killDescendants(ProcessHandle process, boolean force) {
}

public DevServer dev(Optional<ConsoleInstalledBuildItem> consoleInstalled, LoggingSetupBuildItem loggingSetup,
String devServerHost, int devServerPort, String checkPath, int checkTimeout) {
boolean tls, boolean tlsAllowInsecure, String devServerHost, int devServerPort, 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);
StartupLogCompressor logCompressor = new StartupLogCompressor(
Expand All @@ -155,7 +161,7 @@ public void run() {
String ipAddress = null;
try {
int i = 0;
while ((ipAddress = isDevServerUp(devServerHost, devServerPort, checkPath)) == null) {
while ((ipAddress = isDevServerUp(tls, tlsAllowInsecure, devServerHost, devServerPort, checkPath)) == null) {
if (++i >= checkTimeout / 500) {
stopDev(p);
throw new RuntimeException(
Expand Down Expand Up @@ -269,7 +275,7 @@ public void run() {
}
}

public static String isDevServerUp(String host, int port, String path) {
public static String isDevServerUp(boolean tls, boolean tlsAllowInsecure, String host, int port, String path) {
if (path == null) {
return host;
}
Expand All @@ -280,8 +286,24 @@ public static String isDevServerUp(String host, int port, String path) {
try {
final String hostAddress = address.getHostAddress();
final String ipAddress = address instanceof Inet6Address ? "[" + hostAddress + "]" : hostAddress;
URL url = new URL(String.format("http://%s:%d%s", ipAddress, port, normalizedPath));
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
URL url = new URL(String.format("%s://%s:%d%s", tls ? "https" : "http", ipAddress, port, normalizedPath));
HttpURLConnection connection;
if (tls) {
HttpsURLConnection httpsConnection = (HttpsURLConnection) url.openConnection();
if (tlsAllowInsecure) {
httpsConnection.setSSLSocketFactory(SslUtil.createNonValidatingSslContext().getSocketFactory());
httpsConnection.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
}
connection = httpsConnection;
} else {
connection = (HttpURLConnection) url.openConnection();
}

connection.setRequestMethod("GET");
connection.setConnectTimeout(2000);
connection.setReadTimeout(2000);
Expand Down

0 comments on commit dc9c997

Please sign in to comment.