summaryrefslogtreecommitdiffstats
path: root/jdisc_http_service
diff options
context:
space:
mode:
Diffstat (limited to 'jdisc_http_service')
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java89
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/DefaultSslTrustStoreConfigurator.java40
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/DefaultSslTrustStoreContext.java54
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslTrustStoreConfigurator.java14
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslTrustStoreContext.java16
-rw-r--r--jdisc_http_service/src/test/java/com/yahoo/jdisc/http/guiceModules/ConnectorFactoryRegistryModule.java5
-rw-r--r--jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactoryTest.java5
7 files changed, 165 insertions, 58 deletions
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java
index 8255e16e0ee..e4a21f2eb73 100644
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java
+++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java
@@ -2,12 +2,19 @@
package com.yahoo.jdisc.http.server.jetty;
import com.google.inject.Inject;
+import com.yahoo.config.InnerNode;
import com.yahoo.jdisc.Metric;
import com.yahoo.jdisc.http.ConnectorConfig;
import com.yahoo.jdisc.http.ConnectorConfig.Ssl;
+import com.yahoo.jdisc.http.ConnectorConfig.Ssl.ExcludeCipherSuite;
+import com.yahoo.jdisc.http.ConnectorConfig.Ssl.ExcludeProtocol;
+import com.yahoo.jdisc.http.ConnectorConfig.Ssl.IncludeCipherSuite;
+import com.yahoo.jdisc.http.ConnectorConfig.Ssl.IncludeProtocol;
import com.yahoo.jdisc.http.SecretStore;
import com.yahoo.jdisc.http.ssl.DefaultSslKeyStoreContext;
+import com.yahoo.jdisc.http.ssl.DefaultSslTrustStoreContext;
import com.yahoo.jdisc.http.ssl.SslKeyStoreConfigurator;
+import com.yahoo.jdisc.http.ssl.SslTrustStoreConfigurator;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
@@ -18,6 +25,10 @@ import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import java.nio.channels.ServerSocketChannel;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
/**
* @author Einar M R Rosenvinge
@@ -26,27 +37,16 @@ import java.nio.channels.ServerSocketChannel;
public class ConnectorFactory {
private final ConnectorConfig connectorConfig;
- private final SecretStore secretStore;
private final SslKeyStoreConfigurator sslKeyStoreConfigurator;
+ private final SslTrustStoreConfigurator sslTrustStoreConfigurator;
@Inject
public ConnectorFactory(ConnectorConfig connectorConfig,
- SecretStore secretStore,
- SslKeyStoreConfigurator sslKeyStoreConfigurator) {
+ SslKeyStoreConfigurator sslKeyStoreConfigurator,
+ SslTrustStoreConfigurator sslTrustStoreConfigurator) {
this.connectorConfig = connectorConfig;
- this.secretStore = secretStore;
this.sslKeyStoreConfigurator = sslKeyStoreConfigurator;
-
- if (connectorConfig.ssl().enabled())
- validateSslConfig(connectorConfig);
- }
-
- // TODO: can be removed when we have dedicated SSL config in services.xml
- private static void validateSslConfig(ConnectorConfig config) {
- ConnectorConfig.Ssl ssl = config.ssl();
- if (!ssl.trustStorePath().isEmpty() && ssl.useTrustStorePassword() && ssl.keyDbKey().isEmpty()) {
- throw new IllegalArgumentException("Missing password for JKS truststore");
- }
+ this.sslTrustStoreConfigurator = sslTrustStoreConfigurator;
}
public ConnectorConfig getConnectorConfig() {
@@ -93,13 +93,13 @@ public class ConnectorFactory {
return new HttpConnectionFactory(httpConfig);
}
- //TODO: does not support loading non-yahoo readable JKS key stores.
private SslConnectionFactory newSslConnectionFactory() {
Ssl sslConfig = connectorConfig.ssl();
SslContextFactory factory = new SslContextFactory();
sslKeyStoreConfigurator.configure(new DefaultSslKeyStoreContext(factory));
+ sslTrustStoreConfigurator.configure(new DefaultSslTrustStoreContext(factory));
switch (sslConfig.clientAuth()) {
case NEED_AUTH:
@@ -114,49 +114,28 @@ public class ConnectorFactory {
factory.setSecureRandomAlgorithm(sslConfig.prng());
}
- if (!sslConfig.excludeProtocol().isEmpty()) {
- String[] prots = new String[sslConfig.excludeProtocol().size()];
- for (int i = 0; i < prots.length; i++) {
- prots[i] = sslConfig.excludeProtocol(i).name();
- }
- factory.setExcludeProtocols(prots);
- }
- if (!sslConfig.includeProtocol().isEmpty()) {
- String[] prots = new String[sslConfig.includeProtocol().size()];
- for (int i = 0; i < prots.length; i++) {
- prots[i] = sslConfig.includeProtocol(i).name();
- }
- factory.setIncludeProtocols(prots);
- }
- if (!sslConfig.excludeCipherSuite().isEmpty()) {
- String[] ciphs = new String[sslConfig.excludeCipherSuite().size()];
- for (int i = 0; i < ciphs.length; i++) {
- ciphs[i] = sslConfig.excludeCipherSuite(i).name();
- }
- factory.setExcludeCipherSuites(ciphs);
-
- }
- if (!sslConfig.includeCipherSuite().isEmpty()) {
- String[] ciphs = new String[sslConfig.includeCipherSuite().size()];
- for (int i = 0; i < ciphs.length; i++) {
- ciphs[i] = sslConfig.includeCipherSuite(i).name();
- }
- factory.setIncludeCipherSuites(ciphs);
- }
-
- String keyDbPassword = sslConfig.keyDbKey();
-
- if (!sslConfig.trustStorePath().isEmpty()) {
- factory.setTrustStorePath(sslConfig.trustStorePath());
- factory.setTrustStoreType(sslConfig.trustStoreType().toString());
- if (sslConfig.useTrustStorePassword()) {
- factory.setTrustStorePassword(secretStore.getSecret(keyDbPassword));
- }
- }
+ setStringArrayParameter(
+ factory, sslConfig.excludeProtocol(), ExcludeProtocol::name, SslContextFactory::setExcludeProtocols);
+ setStringArrayParameter(
+ factory, sslConfig.includeProtocol(), IncludeProtocol::name, SslContextFactory::setIncludeProtocols);
+ setStringArrayParameter(
+ factory, sslConfig.excludeCipherSuite(), ExcludeCipherSuite::name, SslContextFactory::setExcludeCipherSuites);
+ setStringArrayParameter(
+ factory, sslConfig.includeCipherSuite(), IncludeCipherSuite::name, SslContextFactory::setIncludeCipherSuites);
factory.setKeyManagerFactoryAlgorithm(sslConfig.sslKeyManagerFactoryAlgorithm());
factory.setProtocol(sslConfig.protocol());
return new SslConnectionFactory(factory, HttpVersion.HTTP_1_1.asString());
}
+ private static <T extends InnerNode> void setStringArrayParameter(SslContextFactory sslContextFactory,
+ List<T> configValues,
+ Function<T, String> nameProperty,
+ BiConsumer<SslContextFactory, String[]> setter) {
+ if (!configValues.isEmpty()) {
+ String[] nameArray = configValues.stream().map(nameProperty).toArray(String[]::new);
+ setter.accept(sslContextFactory, nameArray);
+ }
+ }
+
}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/DefaultSslTrustStoreConfigurator.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/DefaultSslTrustStoreConfigurator.java
new file mode 100644
index 00000000000..8af21d48e9a
--- /dev/null
+++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/DefaultSslTrustStoreConfigurator.java
@@ -0,0 +1,40 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jdisc.http.ssl;
+
+import com.google.inject.Inject;
+import com.yahoo.jdisc.http.ConnectorConfig;
+import com.yahoo.jdisc.http.SecretStore;
+
+/**
+ * @author bjorncs
+ */
+public class DefaultSslTrustStoreConfigurator implements SslTrustStoreConfigurator {
+
+ private final SecretStore secretStore;
+ private final ConnectorConfig.Ssl config;
+
+ @Inject
+ public DefaultSslTrustStoreConfigurator(ConnectorConfig config, SecretStore secretStore) {
+ validateConfig(config.ssl());
+ this.secretStore = secretStore;
+ this.config = config.ssl();
+ }
+
+ @Override
+ public void configure(SslTrustStoreContext context) {
+ if (!config.enabled()) return;
+ String keyDbPassword = config.keyDbKey();
+ if (!config.trustStorePath().isEmpty()) {
+ String password = config.useTrustStorePassword() ? secretStore.getSecret(keyDbPassword) : null;
+ context.updateTrustStore(config.trustStorePath(), config.trustStoreType().toString(), password);
+ }
+ }
+
+ private static void validateConfig(ConnectorConfig.Ssl config) {
+ if (!config.enabled()) return;
+ if (!config.trustStorePath().isEmpty() && config.useTrustStorePassword() && config.keyDbKey().isEmpty()) {
+ throw new IllegalArgumentException("Missing password for JKS truststore");
+ }
+ }
+
+}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/DefaultSslTrustStoreContext.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/DefaultSslTrustStoreContext.java
new file mode 100644
index 00000000000..c2d91cca3ea
--- /dev/null
+++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/DefaultSslTrustStoreContext.java
@@ -0,0 +1,54 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jdisc.http.ssl;
+
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+import java.security.KeyStore;
+import java.util.function.Consumer;
+
+/**
+ * @author bjorncs
+ */
+public class DefaultSslTrustStoreContext implements SslTrustStoreContext {
+
+ private final SslContextFactory sslContextFactory;
+
+ public DefaultSslTrustStoreContext(SslContextFactory sslContextFactory) {
+ this.sslContextFactory = sslContextFactory;
+ }
+
+ @Override
+ public void updateTrustStore(KeyStore trustStore) {
+ updateTrustStore(trustStore, null);
+ }
+
+ @Override
+ public void updateTrustStore(KeyStore trustStore, String password) {
+ updateTrustStore(sslContextFactory -> {
+ sslContextFactory.setTrustStore(trustStore);
+ if (password != null) {
+ sslContextFactory.setTrustStorePassword(password);
+ }
+ });
+ }
+
+ @Override
+ public void updateTrustStore(String trustStorePath, String trustStoreType, String trustStorePassword) {
+ updateTrustStore(sslContextFactory -> {
+ sslContextFactory.setTrustStorePath(trustStorePath);
+ sslContextFactory.setTrustStoreType(trustStoreType);
+ if (trustStorePassword != null) {
+ sslContextFactory.setTrustStorePassword(trustStorePassword);
+ }
+ });
+ }
+
+ private void updateTrustStore(Consumer<SslContextFactory> reloader) {
+ try {
+ sslContextFactory.reload(reloader);
+ } catch (Exception e) {
+ throw new RuntimeException("Could not update truststore: " + e.getMessage(), e);
+ }
+ }
+
+}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslTrustStoreConfigurator.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslTrustStoreConfigurator.java
new file mode 100644
index 00000000000..de1119a5275
--- /dev/null
+++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslTrustStoreConfigurator.java
@@ -0,0 +1,14 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jdisc.http.ssl;
+
+/**
+ * An interface for an component that can configure an {@link SslTrustStoreContext}. The implementor can assume that
+ * the {@link SslTrustStoreContext} instance is thread-safe and be updated at any time
+ * during and after the call to{@link #configure(SslTrustStoreContext)}.
+ * Modifying the {@link SslKeyStoreContext} instance will trigger a hot reload of the truststore in JDisc.
+ *
+ * @author bjorncs
+ */
+public interface SslTrustStoreConfigurator {
+ void configure(SslTrustStoreContext context);
+}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslTrustStoreContext.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslTrustStoreContext.java
new file mode 100644
index 00000000000..fc8cf397b24
--- /dev/null
+++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslTrustStoreContext.java
@@ -0,0 +1,16 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jdisc.http.ssl;
+
+import java.security.KeyStore;
+
+/**
+ * An interface to update the truststore in JDisc. Any update will trigger a hot reload and new connections will
+ * authenticated using the update truststore.
+ *
+ * @author bjorncs
+ */
+public interface SslTrustStoreContext {
+ void updateTrustStore(KeyStore trustStore);
+ void updateTrustStore(KeyStore trustStore, String password);
+ void updateTrustStore(String trustStorePath, String trustStoreType, String trustStorePassword);
+}
diff --git a/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/guiceModules/ConnectorFactoryRegistryModule.java b/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/guiceModules/ConnectorFactoryRegistryModule.java
index 0d8f433cc39..6281907e083 100644
--- a/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/guiceModules/ConnectorFactoryRegistryModule.java
+++ b/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/guiceModules/ConnectorFactoryRegistryModule.java
@@ -12,6 +12,7 @@ import com.yahoo.jdisc.http.SecretStore;
import com.yahoo.jdisc.http.server.jetty.ConnectorFactory;
import com.yahoo.jdisc.http.server.jetty.TestDrivers;
import com.yahoo.jdisc.http.ssl.DefaultSslKeyStoreConfigurator;
+import com.yahoo.jdisc.http.ssl.DefaultSslTrustStoreConfigurator;
/**
* Guice module for test ConnectorFactories
@@ -48,8 +49,8 @@ public class ConnectorFactoryRegistryModule implements Module {
public StaticKeyDbConnectorFactory(ConnectorConfig connectorConfig) {
super(connectorConfig,
- new MockSecretStore(),
- new DefaultSslKeyStoreConfigurator(connectorConfig, new MockSecretStore()));
+ new DefaultSslKeyStoreConfigurator(connectorConfig, new MockSecretStore()),
+ new DefaultSslTrustStoreConfigurator(connectorConfig, new MockSecretStore()));
}
}
diff --git a/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactoryTest.java b/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactoryTest.java
index 781bc6a7b5f..103a317094b 100644
--- a/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactoryTest.java
+++ b/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactoryTest.java
@@ -5,6 +5,7 @@ import com.yahoo.jdisc.Metric;
import com.yahoo.jdisc.http.ConnectorConfig;
import com.yahoo.jdisc.http.SecretStore;
import com.yahoo.jdisc.http.ssl.DefaultSslKeyStoreConfigurator;
+import com.yahoo.jdisc.http.ssl.DefaultSslTrustStoreConfigurator;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
@@ -107,7 +108,9 @@ public class ConnectorFactoryTest {
private static ConnectorFactory createConnectorFactory(ConnectorConfig config) {
ThrowingSecretStore secretStore = new ThrowingSecretStore();
- return new ConnectorFactory(config, secretStore, new DefaultSslKeyStoreConfigurator(config, secretStore));
+ return new ConnectorFactory(config,
+ new DefaultSslKeyStoreConfigurator(config, secretStore),
+ new DefaultSslTrustStoreConfigurator(config, secretStore));
}
private static class HelloWorldHandler extends AbstractHandler {