diff options
4 files changed, 99 insertions, 4 deletions
diff --git a/jdisc_http_service/abi-spec.json b/jdisc_http_service/abi-spec.json index bb6285ab94f..483565cc69f 100644 --- a/jdisc_http_service/abi-spec.json +++ b/jdisc_http_service/abi-spec.json @@ -42,6 +42,7 @@ "public com.yahoo.jdisc.http.ConnectorConfig$Builder tlsClientAuthEnforcer(com.yahoo.jdisc.http.ConnectorConfig$TlsClientAuthEnforcer$Builder)", "public com.yahoo.jdisc.http.ConnectorConfig$Builder healthCheckProxy(com.yahoo.jdisc.http.ConnectorConfig$HealthCheckProxy$Builder)", "public com.yahoo.jdisc.http.ConnectorConfig$Builder proxyProtocol(com.yahoo.jdisc.http.ConnectorConfig$ProxyProtocol$Builder)", + "public com.yahoo.jdisc.http.ConnectorConfig$Builder secureRedirect(com.yahoo.jdisc.http.ConnectorConfig$SecureRedirect$Builder)", "public final boolean dispatchGetConfig(com.yahoo.config.ConfigInstance$Producer)", "public final java.lang.String getDefMd5()", "public final java.lang.String getDefName()", @@ -53,7 +54,8 @@ "public com.yahoo.jdisc.http.ConnectorConfig$Ssl$Builder ssl", "public com.yahoo.jdisc.http.ConnectorConfig$TlsClientAuthEnforcer$Builder tlsClientAuthEnforcer", "public com.yahoo.jdisc.http.ConnectorConfig$HealthCheckProxy$Builder healthCheckProxy", - "public com.yahoo.jdisc.http.ConnectorConfig$ProxyProtocol$Builder proxyProtocol" + "public com.yahoo.jdisc.http.ConnectorConfig$ProxyProtocol$Builder proxyProtocol", + "public com.yahoo.jdisc.http.ConnectorConfig$SecureRedirect$Builder secureRedirect" ] }, "com.yahoo.jdisc.http.ConnectorConfig$HealthCheckProxy$Builder": { @@ -133,6 +135,37 @@ ], "fields": [] }, + "com.yahoo.jdisc.http.ConnectorConfig$SecureRedirect$Builder": { + "superClass": "java.lang.Object", + "interfaces": [ + "com.yahoo.config.ConfigBuilder" + ], + "attributes": [ + "public" + ], + "methods": [ + "public void <init>()", + "public void <init>(com.yahoo.jdisc.http.ConnectorConfig$SecureRedirect)", + "public com.yahoo.jdisc.http.ConnectorConfig$SecureRedirect$Builder enabled(boolean)", + "public com.yahoo.jdisc.http.ConnectorConfig$SecureRedirect$Builder port(int)", + "public com.yahoo.jdisc.http.ConnectorConfig$SecureRedirect build()" + ], + "fields": [] + }, + "com.yahoo.jdisc.http.ConnectorConfig$SecureRedirect": { + "superClass": "com.yahoo.config.InnerNode", + "interfaces": [], + "attributes": [ + "public", + "final" + ], + "methods": [ + "public void <init>(com.yahoo.jdisc.http.ConnectorConfig$SecureRedirect$Builder)", + "public boolean enabled()", + "public int port()" + ], + "fields": [] + }, "com.yahoo.jdisc.http.ConnectorConfig$Ssl$Builder": { "superClass": "java.lang.Object", "interfaces": [ @@ -323,7 +356,8 @@ "public com.yahoo.jdisc.http.ConnectorConfig$Ssl ssl()", "public com.yahoo.jdisc.http.ConnectorConfig$TlsClientAuthEnforcer tlsClientAuthEnforcer()", "public com.yahoo.jdisc.http.ConnectorConfig$HealthCheckProxy healthCheckProxy()", - "public com.yahoo.jdisc.http.ConnectorConfig$ProxyProtocol proxyProtocol()" + "public com.yahoo.jdisc.http.ConnectorConfig$ProxyProtocol proxyProtocol()", + "public com.yahoo.jdisc.http.ConnectorConfig$SecureRedirect secureRedirect()" ], "fields": [ "public static final java.lang.String CONFIG_DEF_MD5", diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java index 71284e09669..1e4a2082094 100644 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java @@ -246,10 +246,13 @@ public class JettyHttpServer extends AbstractServerProvider { servletContextHandler.addServlet(jdiscServlet, "/*"); + List<ConnectorConfig> connectorConfigs = connectors.stream().map(JDiscServerConnector::connectorConfig).collect(toList()); + var secureRedirectHandler = new SecuredRedirectHandler(connectorConfigs); + secureRedirectHandler.setHandler(servletContextHandler); + var proxyHandler = new HealthCheckProxyHandler(connectors); - proxyHandler.setHandler(servletContextHandler); + proxyHandler.setHandler(secureRedirectHandler); - List<ConnectorConfig> connectorConfigs = connectors.stream().map(JDiscServerConnector::connectorConfig).collect(toList()); var authEnforcer = new TlsClientAuthenticationEnforcer(connectorConfigs); authEnforcer.setHandler(proxyHandler); diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SecuredRedirectHandler.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SecuredRedirectHandler.java new file mode 100644 index 00000000000..32c0628186a --- /dev/null +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SecuredRedirectHandler.java @@ -0,0 +1,52 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc.http.server.jetty; + +import com.yahoo.jdisc.http.ConnectorConfig; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.handler.HandlerWrapper; +import org.eclipse.jetty.util.URIUtil; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A secure redirect handler inspired by {@link org.eclipse.jetty.server.handler.SecuredRedirectHandler}. + * + * @author bjorncs + */ +class SecuredRedirectHandler extends HandlerWrapper { + + private final Map<Integer, Integer> redirectMap; + + SecuredRedirectHandler(List<ConnectorConfig> connectorConfigs) { + this.redirectMap = createRedirectMap(connectorConfigs); + } + + @Override + public void handle(String target, Request request, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, ServletException { + int localPort = servletRequest.getLocalPort(); + if (!redirectMap.containsKey(localPort)) { + _handler.handle(target, request, servletRequest, servletResponse); + return; + } + servletResponse.setContentLength(0); + servletResponse.sendRedirect( + URIUtil.newURI("https", request.getServerName(), redirectMap.get(localPort), request.getRequestURI(), request.getQueryString())); + request.setHandled(true); + } + + private static Map<Integer, Integer> createRedirectMap(List<ConnectorConfig> connectorConfigs) { + var redirectMap = new HashMap<Integer, Integer>(); + for (ConnectorConfig connectorConfig : connectorConfigs) { + if (connectorConfig.secureRedirect().enabled()) { + redirectMap.put(connectorConfig.listenPort(), connectorConfig.secureRedirect().port()); + } + } + return redirectMap; + } +} diff --git a/jdisc_http_service/src/main/resources/configdefinitions/jdisc.http.connector.def b/jdisc_http_service/src/main/resources/configdefinitions/jdisc.http.connector.def index 8027525521c..93378975609 100644 --- a/jdisc_http_service/src/main/resources/configdefinitions/jdisc.http.connector.def +++ b/jdisc_http_service/src/main/resources/configdefinitions/jdisc.http.connector.def @@ -106,3 +106,9 @@ proxyProtocol.enabled bool default=false # Allow https in parallel with proxy protocol proxyProtocol.mixedMode bool default=false + +# Redirect all requests to https port +secureRedirect.enabled bool default=false + +# Target port for redirect +secureRedirect.port int default=443 |