summaryrefslogtreecommitdiffstats
path: root/container-core
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@yahooinc.com>2022-10-06 09:58:49 +0200
committerBjørn Christian Seime <bjorncs@yahooinc.com>2022-10-06 09:59:36 +0200
commita1f7601cd6257dceae6b986a3aa64d16d2d8516f (patch)
treedc3b23df41a5ba30451149bcc47c880fc4e55828 /container-core
parent62ac14f904d43604b0f0522d4dd65232f6e915b5 (diff)
Restrict server names accepted per connector
Diffstat (limited to 'container-core')
-rw-r--r--container-core/abi-spec.json10
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java10
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java9
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java73
-rw-r--r--container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def2
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java20
6 files changed, 78 insertions, 46 deletions
diff --git a/container-core/abi-spec.json b/container-core/abi-spec.json
index 5985e79b786..7844282b7e9 100644
--- a/container-core/abi-spec.json
+++ b/container-core/abi-spec.json
@@ -1236,9 +1236,13 @@
"public void <init>()",
"public void <init>(com.yahoo.jdisc.http.ConnectorConfig$ServerName)",
"public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder fallback(java.lang.String)",
+ "public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder allowed(java.lang.String)",
+ "public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder allowed(java.util.Collection)",
"public com.yahoo.jdisc.http.ConnectorConfig$ServerName build()"
],
- "fields": []
+ "fields": [
+ "public java.util.List allowed"
+ ]
},
"com.yahoo.jdisc.http.ConnectorConfig$ServerName": {
"superClass": "com.yahoo.config.InnerNode",
@@ -1249,7 +1253,9 @@
],
"methods": [
"public void <init>(com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder)",
- "public java.lang.String fallback()"
+ "public java.lang.String fallback()",
+ "public java.util.List allowed()",
+ "public java.lang.String allowed(int)"
],
"fields": []
},
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java
index bf278981b69..e59e95a59a7 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java
@@ -9,7 +9,6 @@ import com.yahoo.jdisc.http.ssl.impl.DefaultConnectorSsl;
import com.yahoo.security.tls.MixedMode;
import com.yahoo.security.tls.TransportSecurityUtils;
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
-import org.eclipse.jetty.http.HttpCompliance;
import org.eclipse.jetty.http2.server.AbstractHTTP2ServerConnectionFactory;
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
@@ -82,16 +81,9 @@ public class ConnectorFactory {
public ServerConnector createConnector(final Metric metric, final Server server, JettyConnectionLogger connectionLogger,
ConnectionMetricAggregator connectionMetricAggregator) {
- ServerConnector connector = new JDiscServerConnector(
+ return new JDiscServerConnector(
connectorConfig, metric, server, connectionLogger, connectionMetricAggregator,
createConnectionFactories(metric).toArray(ConnectionFactory[]::new));
- connector.setPort(connectorConfig.listenPort());
- connector.setName(connectorConfig.name());
- connector.setAcceptQueueSize(connectorConfig.acceptQueueSize());
- connector.setReuseAddress(connectorConfig.reuseAddress());
- connector.setIdleTimeout(toMillis(connectorConfig.idleTimeout()));
- connector.addBean(HttpCompliance.RFC7230);
- return connector;
}
private List<ConnectionFactory> createConnectionFactories(Metric metric) {
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
index 79cdb8f67cf..4b297fd5a44 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
@@ -3,6 +3,7 @@ package com.yahoo.jdisc.http.server.jetty;
import com.yahoo.jdisc.Metric;
import com.yahoo.jdisc.http.ConnectorConfig;
+import org.eclipse.jetty.http.HttpCompliance;
import org.eclipse.jetty.io.ConnectionStatistics;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Server;
@@ -50,8 +51,16 @@ class JDiscServerConnector extends ServerConnector {
}
addBean(connectionLogger);
addBean(connectionMetricAggregator);
+ setPort(config.listenPort());
+ setName(config.name());
+ setAcceptQueueSize(config.acceptQueueSize());
+ setReuseAddress(config.reuseAddress());
+ setIdleTimeout(toMillis(config.idleTimeout()));
+ addBean(HttpCompliance.RFC7230);
}
+ private static long toMillis(double seconds) { return (long)(seconds * 1000); }
+
@Override
protected void configure(final Socket socket) {
super.configure(socket);
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
index 96c5bac335b..d2811847995 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
@@ -14,7 +14,6 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.jmx.ConnectorServer;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
@@ -139,43 +138,51 @@ public class JettyHttpServer extends AbstractServerProvider {
private HandlerCollection getHandlerCollection(ServerConfig serverConfig,
List<JDiscServerConnector> connectors,
ServletHolder jdiscServlet) {
- ServletContextHandler servletContextHandler = createServletContextHandler();
- 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(secureRedirectHandler);
-
- var authEnforcer = new TlsClientAuthenticationEnforcer(connectorConfigs);
- authEnforcer.setHandler(proxyHandler);
-
- GzipHandler gzipHandler = newGzipHandler(serverConfig);
- gzipHandler.setHandler(authEnforcer);
+ HandlerCollection connectorSpecificHandlers = new HandlerCollection();
+ for (JDiscServerConnector connector : connectors) {
+ ServletContextHandler servletContextHandler = createServletContextHandler(connector);
+ 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(secureRedirectHandler);
+
+ var authEnforcer = new TlsClientAuthenticationEnforcer(connectorConfigs);
+ authEnforcer.setHandler(proxyHandler);
+
+ GzipHandler gzipHandler = newGzipHandler(serverConfig);
+ gzipHandler.setHandler(authEnforcer);
+
+ HttpResponseStatisticsCollector statisticsCollector =
+ new HttpResponseStatisticsCollector(serverConfig.metric().monitoringHandlerPaths(),
+ serverConfig.metric().searchHandlerPaths());
+ statisticsCollector.setHandler(gzipHandler);
+ for (String agent : serverConfig.metric().ignoredUserAgents()) {
+ statisticsCollector.ignoreUserAgent(agent);
+ }
+ StatisticsHandler statisticsHandler = newStatisticsHandler();
+ statisticsHandler.setHandler(statisticsCollector);
- HttpResponseStatisticsCollector statisticsCollector =
- new HttpResponseStatisticsCollector(serverConfig.metric().monitoringHandlerPaths(),
- serverConfig.metric().searchHandlerPaths());
- statisticsCollector.setHandler(gzipHandler);
- for (String agent : serverConfig.metric().ignoredUserAgents()) {
- statisticsCollector.ignoreUserAgent(agent);
+ connectorSpecificHandlers.addHandler(statisticsHandler);
}
- StatisticsHandler statisticsHandler = newStatisticsHandler();
- statisticsHandler.setHandler(statisticsCollector);
-
- HandlerCollection handlerCollection = new HandlerCollection();
- handlerCollection.setHandlers(new Handler[] { statisticsHandler });
- return handlerCollection;
+ return connectorSpecificHandlers;
}
- private ServletContextHandler createServletContextHandler() {
- ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SECURITY | ServletContextHandler.NO_SESSIONS);
- servletContextHandler.setContextPath("/");
- servletContextHandler.setDisplayName(getDisplayName(listenedPorts));
- return servletContextHandler;
+ private ServletContextHandler createServletContextHandler(JDiscServerConnector connector) {
+ var ctx = new ServletContextHandler(ServletContextHandler.NO_SECURITY | ServletContextHandler.NO_SESSIONS);
+ ctx.setContextPath("/");
+ ctx.setDisplayName(getDisplayName(listenedPorts));
+ List<String> allowedServerNames = connector.connectorConfig().serverName().allowed();
+ if (allowedServerNames.isEmpty()) {
+ ctx.setVirtualHosts(new String[]{"@%s".formatted(connector.getName())});
+ } else {
+ ctx.setVirtualHosts(allowedServerNames.toArray(new String[0]));
+ }
+ return ctx;
}
private static String getDisplayName(List<Integer> ports) {
diff --git a/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def b/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def
index 1f4763d32a7..5e50be05115 100644
--- a/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def
+++ b/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def
@@ -138,3 +138,5 @@ http2.maxConcurrentStreams int default=4096
# Override the default server name when authority is missing from request.
serverName.fallback string default=""
+# The list of accepted server names. Empty list to accept any. Elements follows format of 'serverName.default'.
+serverName.allowed[] string
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java
index 2c5d36bd776..318067ac634 100644
--- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java
@@ -743,7 +743,7 @@ public class HttpServerTest {
}
@Test
- void requestThatFallbackServerNameCanBeOverridden() throws Exception {
+ void fallbackServerNameCanBeOverridden() throws Exception {
String fallbackHostname = "myhostname";
JettyTestDriver driver = JettyTestDriver.newConfiguredInstance(
new UriRequestHandler(),
@@ -752,13 +752,29 @@ public class HttpServerTest {
.serverName(new ConnectorConfig.ServerName.Builder().fallback(fallbackHostname)));
int listenPort = driver.server().getListenPort();
HttpGet req = new HttpGet("http://localhost:" + listenPort + "/");
- req.addHeader("Host", null);
+ req.setHeader("Host", null);
driver.client().execute(req)
.expectStatusCode(is(OK))
.expectContent(containsString("http://" + fallbackHostname + ":" + listenPort + "/"));
assertTrue(driver.close());
}
+ @Test
+ void acceptedServerNamesCanBeRestricted() throws Exception {
+ String requiredServerName = "myhostname";
+ JettyTestDriver driver = JettyTestDriver.newConfiguredInstance(
+ new EchoRequestHandler(),
+ new ServerConfig.Builder(),
+ new ConnectorConfig.Builder()
+ .serverName(new ConnectorConfig.ServerName.Builder().allowed(requiredServerName)));
+ int listenPort = driver.server().getListenPort();
+ HttpGet req = new HttpGet("http://localhost:" + listenPort + "/");
+ req.setHeader("Host", requiredServerName);
+ driver.client().execute(req).expectStatusCode(is(OK));
+ driver.client().get("/").expectStatusCode(is(NOT_FOUND));
+ assertTrue(driver.close());
+ }
+
private static JettyTestDriver createSslWithTlsClientAuthenticationEnforcer(Path certificateFile, Path privateKeyFile) {
ConnectorConfig.Builder connectorConfig = new ConnectorConfig.Builder()
.tlsClientAuthEnforcer(