summaryrefslogtreecommitdiffstats
path: root/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java
diff options
context:
space:
mode:
Diffstat (limited to 'jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java')
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java72
1 files changed, 59 insertions, 13 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 54338c64c1e..96180f48229 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
@@ -8,6 +8,8 @@ import com.yahoo.jdisc.http.ConnectorConfig;
import com.yahoo.jdisc.http.ConnectorConfig.Ssl;
import com.yahoo.jdisc.http.ConnectorConfig.Ssl.PemKeyStore;
import com.yahoo.jdisc.http.SecretStore;
+import com.yahoo.jdisc.http.ssl.ReaderForPath;
+import com.yahoo.jdisc.http.ssl.SslKeyStore;
import com.yahoo.jdisc.http.ssl.pem.PemSslKeyStore;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.ConnectionFactory;
@@ -22,11 +24,15 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
import javax.servlet.ServletRequest;
import java.io.IOException;
-import java.io.UncheckedIOException;
+import java.io.Reader;
import java.lang.reflect.Field;
import java.net.Socket;
import java.net.SocketException;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
@@ -37,8 +43,10 @@ import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
+import static com.google.common.io.Closeables.closeQuietly;
import static com.yahoo.jdisc.http.ConnectorConfig.Ssl.KeyStoreType.Enum.JKS;
import static com.yahoo.jdisc.http.ConnectorConfig.Ssl.KeyStoreType.Enum.PEM;
+import static com.yahoo.jdisc.http.server.jetty.Exceptions.throwUnchecked;
/**
* @author Einar M R Rosenvinge
@@ -76,11 +84,11 @@ public class ConnectorFactory {
return connectorConfig;
}
- public ServerConnector createConnector(final Metric metric, final Server server, final ServerSocketChannel ch) {
+ public ServerConnector createConnector(final Metric metric, final Server server, final ServerSocketChannel ch, Map<Path, FileChannel> keyStoreChannels) {
ServerConnector connector;
if (connectorConfig.ssl().enabled()) {
connector = new JDiscServerConnector(connectorConfig, metric, server, ch,
- newSslConnectionFactory(),
+ newSslConnectionFactory(keyStoreChannels),
newHttpConnectionFactory());
} else {
connector = new JDiscServerConnector(connectorConfig, metric, server, ch,
@@ -117,7 +125,7 @@ public class ConnectorFactory {
}
//TODO: does not support loading non-yahoo readable JKS key stores.
- private SslConnectionFactory newSslConnectionFactory() {
+ private SslConnectionFactory newSslConnectionFactory(Map<Path, FileChannel> keyStoreChannels) {
Ssl sslConfig = connectorConfig.ssl();
SslContextFactory factory = new SslContextFactory();
@@ -167,7 +175,7 @@ public class ConnectorFactory {
Optional<String> keyDbPassword = secret(sslConfig.keyDbKey());
switch (sslConfig.keyStoreType()) {
case PEM:
- factory.setKeyStore(getKeyStore(sslConfig.pemKeyStore()));
+ factory.setKeyStore(getKeyStore(sslConfig.pemKeyStore(), keyStoreChannels));
if (keyDbPassword.isPresent())
log.warning("Encrypted PEM key stores are not supported.");
break;
@@ -200,16 +208,54 @@ public class ConnectorFactory {
return () -> new RuntimeException(String.format("Password is required for JKS %s store", type));
}
- private static KeyStore getKeyStore(PemKeyStore pemKeyStore) {
+ private KeyStore getKeyStore(PemKeyStore pemKeyStore, Map<Path, FileChannel> keyStoreChannels) {
Preconditions.checkArgument(!pemKeyStore.certificatePath().isEmpty(), "Missing certificate path.");
Preconditions.checkArgument(!pemKeyStore.keyPath().isEmpty(), "Missing key path.");
- try {
- Path certificatePath = Paths.get(pemKeyStore.certificatePath());
- Path keyPath = Paths.get(pemKeyStore.keyPath());
- return new PemSslKeyStore(certificatePath, keyPath)
- .loadJavaKeyStore();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
+
+ class KeyStoreReaderForPath implements AutoCloseable {
+ private final Optional<FileChannel> channel;
+ public final ReaderForPath readerForPath;
+
+
+ KeyStoreReaderForPath(String pathString) {
+ Path path = Paths.get(pathString);
+ channel = Optional.ofNullable(keyStoreChannels.get(path));
+ readerForPath = new ReaderForPath(channel.map(this::getReader).orElseGet(() -> getReader(path)), path);
+ }
+
+ private Reader getReader(FileChannel channel) {
+ try {
+ channel.position(0);
+ return Channels.newReader(channel, StandardCharsets.UTF_8.newDecoder(), -1);
+ } catch (IOException e) {
+ throw throwUnchecked(e);
+ }
+
+ }
+
+ private Reader getReader(Path path) {
+ try {
+ return Files.newBufferedReader(path);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed opening " + path, e);
+ }
+ }
+
+ @Override
+ public void close() {
+ //channels are reused
+ if (!channel.isPresent()) {
+ closeQuietly(readerForPath.reader);
+ }
+ }
+ }
+
+ try (KeyStoreReaderForPath certificateReader = new KeyStoreReaderForPath(pemKeyStore.certificatePath());
+ KeyStoreReaderForPath keyReader = new KeyStoreReaderForPath(pemKeyStore.keyPath())) {
+ SslKeyStore keyStore = new PemSslKeyStore(
+ new com.yahoo.jdisc.http.ssl.pem.PemKeyStore.KeyStoreLoadParameter(
+ certificateReader.readerForPath, keyReader.readerForPath));
+ return keyStore.loadJavaKeyStore();
} catch (Exception e) {
throw new RuntimeException("Failed setting up key store for " + pemKeyStore.keyPath() + ", " + pemKeyStore.certificatePath(), e);
}