From 259d53767305223b57122e975aba9bf3ea43790e Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Fri, 14 Sep 2018 08:17:04 +0200 Subject: Remove soLingerTime from connector config --- .../src/main/resources/configdefinitions/jdisc.http.connector.def | 4 ---- 1 file changed, 4 deletions(-) (limited to 'jdisc_http_service/src/main/resources/configdefinitions/jdisc.http.connector.def') 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 676fdbc8157..3356eb3a100 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 @@ -25,10 +25,6 @@ acceptQueueSize int default=0 # Whether the server socket reuses addresses. reuseAddress bool default=true -# TODO Vespa 7: Remove soLingerTime - Jetty no longer support it. -# DEPRECATED No longer in use -soLingerTime double default=-1.0 - # The maximum idle time for a connection, which roughly translates to the Socket.setSoTimeout(int). idleTimeout double default=180.0 -- cgit v1.2.3 From 6e7198c87d0451b3ac441bb21348ab9cf71bf699 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Fri, 14 Sep 2018 08:32:01 +0200 Subject: Remove old ssl connector config --- .../model/container/http/ConnectorFactory.java | 4 +- .../model/container/http/ssl/DummySslProvider.java | 31 ++ .../container/http/ssl/LegacySslProvider.java | 36 --- .../container/http/xml/JettyConnectorBuilder.java | 6 +- .../ssl/ThrowingSslContextFactoryProvider.java | 16 + .../ssl/impl/DefaultSslContextFactoryProvider.java | 103 ------- .../ssl/impl/LegacySslContextFactoryProvider.java | 164 ---------- .../com/yahoo/jdisc/http/ssl/pem/PemKeyStore.java | 336 --------------------- .../yahoo/jdisc/http/ssl/pem/PemSslKeyStore.java | 64 ---- .../configdefinitions/jdisc.http.connector.def | 57 ---- .../http/server/jetty/ConnectorFactoryTest.java | 27 -- 11 files changed, 51 insertions(+), 793 deletions(-) create mode 100644 config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/DummySslProvider.java delete mode 100644 config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/LegacySslProvider.java create mode 100644 jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/ThrowingSslContextFactoryProvider.java delete mode 100644 jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/DefaultSslContextFactoryProvider.java delete mode 100644 jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/LegacySslContextFactoryProvider.java delete mode 100644 jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/pem/PemKeyStore.java delete mode 100644 jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/pem/PemSslKeyStore.java (limited to 'jdisc_http_service/src/main/resources/configdefinitions/jdisc.http.connector.def') diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ConnectorFactory.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ConnectorFactory.java index 44ce65bd9ab..73fc9c0cf41 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ConnectorFactory.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ConnectorFactory.java @@ -6,7 +6,7 @@ import com.yahoo.container.bundle.BundleInstantiationSpecification; import com.yahoo.jdisc.http.ConnectorConfig; import com.yahoo.osgi.provider.model.ComponentModel; import com.yahoo.vespa.model.container.component.SimpleComponent; -import com.yahoo.vespa.model.container.http.ssl.LegacySslProvider; +import com.yahoo.vespa.model.container.http.ssl.DummySslProvider; import static com.yahoo.component.ComponentSpecification.fromString; @@ -22,7 +22,7 @@ public class ConnectorFactory extends SimpleComponent implements ConnectorConfig private final SimpleComponent sslProviderComponent; public ConnectorFactory(String name, int listenPort) { - this(name, listenPort, new LegacySslProvider(name)); + this(name, listenPort, new DummySslProvider(name)); } public ConnectorFactory(String name, diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/DummySslProvider.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/DummySslProvider.java new file mode 100644 index 00000000000..4e2ee61f33f --- /dev/null +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/DummySslProvider.java @@ -0,0 +1,31 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.model.container.http.ssl; + +import com.yahoo.component.ComponentId; +import com.yahoo.container.bundle.BundleInstantiationSpecification; +import com.yahoo.jdisc.http.ConnectorConfig; +import com.yahoo.jdisc.http.ssl.ThrowingSslContextFactoryProvider; +import com.yahoo.osgi.provider.model.ComponentModel; +import com.yahoo.vespa.model.container.component.SimpleComponent; + +import static com.yahoo.component.ComponentSpecification.fromString; + +/** + * @author bjorncs + */ +public class DummySslProvider extends SimpleComponent implements ConnectorConfig.Producer { + + public static final String COMPONENT_ID_PREFIX = "dummy-ssl-provider@"; + public static final String COMPONENT_CLASS = ThrowingSslContextFactoryProvider.class.getName(); + public static final String COMPONENT_BUNDLE = "jdisc_http_service"; + + public DummySslProvider(String serverName) { + super(new ComponentModel( + new BundleInstantiationSpecification(new ComponentId(COMPONENT_ID_PREFIX + serverName), + fromString(COMPONENT_CLASS), + fromString(COMPONENT_BUNDLE)))); + } + + @Override + public void getConfig(ConnectorConfig.Builder builder) {} +} \ No newline at end of file diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/LegacySslProvider.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/LegacySslProvider.java deleted file mode 100644 index 7ab553c45b9..00000000000 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/LegacySslProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.model.container.http.ssl; - -import com.yahoo.component.ComponentId; -import com.yahoo.container.bundle.BundleInstantiationSpecification; -import com.yahoo.jdisc.http.ConnectorConfig; -import com.yahoo.jdisc.http.ssl.SslContextFactoryProvider; -import com.yahoo.jdisc.http.ssl.impl.LegacySslContextFactoryProvider; -import com.yahoo.osgi.provider.model.ComponentModel; -import com.yahoo.vespa.model.container.component.SimpleComponent; - -import static com.yahoo.component.ComponentSpecification.fromString; - -/** - * Provides a legacy implementation of {@link SslContextFactoryProvider} to be injected into non-ssl connectors and connectors using legacy ssl config override - * - * @author bjorncs - */ -public class LegacySslProvider extends SimpleComponent implements ConnectorConfig.Producer { - - public static final String COMPONENT_ID_PREFIX = "legacy-ssl-provider@"; - public static final String COMPONENT_CLASS = LegacySslContextFactoryProvider.class.getName(); - public static final String COMPONENT_BUNDLE = "jdisc_http_service"; - - public LegacySslProvider(String serverName) { - super(new ComponentModel( - new BundleInstantiationSpecification(new ComponentId(COMPONENT_ID_PREFIX + serverName), - fromString(COMPONENT_CLASS), - fromString(COMPONENT_BUNDLE)))); - } - - @Override - public void getConfig(ConnectorConfig.Builder builder) { - - } -} diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyConnectorBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyConnectorBuilder.java index a33b49f8749..4c41aaa504c 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyConnectorBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyConnectorBuilder.java @@ -10,12 +10,10 @@ import com.yahoo.vespa.model.container.component.SimpleComponent; import com.yahoo.vespa.model.container.http.ConnectorFactory; import com.yahoo.vespa.model.container.http.ssl.CustomSslProvider; import com.yahoo.vespa.model.container.http.ssl.DefaultSslProvider; -import com.yahoo.vespa.model.container.http.ssl.LegacySslProvider; +import com.yahoo.vespa.model.container.http.ssl.DummySslProvider; import org.w3c.dom.Element; import java.util.Optional; -import java.util.logging.Level; -import java.util.logging.Logger; /** * @author Einar M R Rosenvinge @@ -52,7 +50,7 @@ public class JettyConnectorBuilder extends VespaDomBuilder.DomConfigProducerBuil String bundle = sslProviderConfigurator.getAttribute("bundle"); return new CustomSslProvider(serverName, className, bundle); } else { - return new LegacySslProvider(serverName); + return new DummySslProvider(serverName); } } } diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/ThrowingSslContextFactoryProvider.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/ThrowingSslContextFactoryProvider.java new file mode 100644 index 00000000000..b28ef54e822 --- /dev/null +++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/ThrowingSslContextFactoryProvider.java @@ -0,0 +1,16 @@ +// Copyright 2018 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; + +/** + * A dummy implementation of {@link SslContextFactoryProvider} to be injected into non-ssl connectors + * + * @author bjorncs + */ +public class ThrowingSslContextFactoryProvider implements SslContextFactoryProvider { + @Override + public SslContextFactory getInstance(String containerId, int port) { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/DefaultSslContextFactoryProvider.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/DefaultSslContextFactoryProvider.java deleted file mode 100644 index fa31f58dfc0..00000000000 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/DefaultSslContextFactoryProvider.java +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.jdisc.http.ssl.impl; - -import com.yahoo.jdisc.http.ConnectorConfig; -import com.yahoo.jdisc.http.ssl.SslContextFactoryProvider; -import com.yahoo.security.KeyStoreBuilder; -import com.yahoo.security.KeyStoreType; -import com.yahoo.security.KeyUtils; -import com.yahoo.security.X509CertificateUtils; -import org.eclipse.jetty.util.ssl.SslContextFactory; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.List; - -/** - * JDisc's default implementation of {@link SslContextFactoryProvider} that uses the {@link ConnectorConfig} to construct a {@link SslContextFactory}. - * - * @author bjorncs - */ -public class DefaultSslContextFactoryProvider implements SslContextFactoryProvider { - - private final ConnectorConfig connectorConfig; - - public DefaultSslContextFactoryProvider(ConnectorConfig connectorConfig) { - validateConfig(connectorConfig.ssl()); - this.connectorConfig = connectorConfig; - } - - @Override - public SslContextFactory getInstance(String containerId, int port) { - ConnectorConfig.Ssl sslConfig = connectorConfig.ssl(); - if (!sslConfig.enabled()) throw new IllegalStateException(); - SslContextFactory factory = new JDiscSslContextFactory(); - - switch (sslConfig.clientAuth()) { - case NEED_AUTH: - factory.setNeedClientAuth(true); - break; - case WANT_AUTH: - factory.setWantClientAuth(true); - break; - } - - // NOTE: All ciphers matching ^TLS_RSA_.*$ are disabled by default in Jetty 9.4.12+ (https://github.com/eclipse/jetty.project/issues/2807) - // JDisc will allow these ciphers by default to support older clients (e.g. Java 8u60 and curl 7.29.0) - // Removing the exclusion will allow for the TLS_RSA variants that are not covered by other exclusions - String[] excludedCiphersWithoutTlsRsaExclusion = Arrays.stream(factory.getExcludeCipherSuites()) - .filter(cipher -> !cipher.equals("^TLS_RSA_.*$")) - .toArray(String[]::new); - factory.setExcludeCipherSuites(excludedCiphersWithoutTlsRsaExclusion); - - // Check if using new ssl syntax from services.xml - factory.setKeyStore(createKeystore(sslConfig)); - factory.setKeyStorePassword(""); - if (!sslConfig.caCertificateFile().isEmpty()) { - factory.setTrustStore(createTruststore(sslConfig)); - } - factory.setProtocol("TLS"); - return factory; - } - - private static void validateConfig(ConnectorConfig.Ssl config) { - if (!config.enabled()) return; - if (config.certificateFile().isEmpty()) { - throw new IllegalArgumentException("Missing certificate file."); - } - if (config.privateKeyFile().isEmpty()) { - throw new IllegalArgumentException("Missing private key file."); - } - - } - - private static KeyStore createTruststore(ConnectorConfig.Ssl sslConfig) { - List caCertificates = X509CertificateUtils.certificateListFromPem(readToString(sslConfig.caCertificateFile())); - KeyStoreBuilder truststoreBuilder = KeyStoreBuilder.withType(KeyStoreType.JKS); - for (int i = 0; i < caCertificates.size(); i++) { - truststoreBuilder.withCertificateEntry("entry-" + i, caCertificates.get(i)); - } - return truststoreBuilder.build(); - } - - private static KeyStore createKeystore(ConnectorConfig.Ssl sslConfig) { - PrivateKey privateKey = KeyUtils.fromPemEncodedPrivateKey(readToString(sslConfig.privateKeyFile())); - List certificates = X509CertificateUtils.certificateListFromPem(readToString(sslConfig.certificateFile())); - return KeyStoreBuilder.withType(KeyStoreType.JKS).withKeyEntry("default", privateKey, certificates).build(); - } - - private static String readToString(String filename) { - try { - return new String(Files.readAllBytes(Paths.get(filename))); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - -} diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/LegacySslContextFactoryProvider.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/LegacySslContextFactoryProvider.java deleted file mode 100644 index 281f80c3aeb..00000000000 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/LegacySslContextFactoryProvider.java +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.jdisc.http.ssl.impl; - -import com.yahoo.config.InnerNode; -import com.yahoo.jdisc.http.ConnectorConfig; -import com.yahoo.jdisc.http.ssl.SslContextFactoryProvider; -import com.yahoo.jdisc.http.ssl.pem.PemSslKeyStore; -import org.eclipse.jetty.util.ssl.SslContextFactory; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.KeyStore; -import java.util.Arrays; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.logging.Logger; - -/** - * A implementation of {@link SslContextFactoryProvider} to be injected into non-ssl connectors or connectors using legacy ssl config - * - * @author bjorncs - */ -// TODO Vespa 7: Remove legacy ssl config -public class LegacySslContextFactoryProvider implements SslContextFactoryProvider { - private static final Logger log = Logger.getLogger(LegacySslContextFactoryProvider.class.getName()); - - private final ConnectorConfig connectorConfig; - @SuppressWarnings("deprecation") - private final com.yahoo.jdisc.http.SecretStore secretStore; - - public LegacySslContextFactoryProvider(ConnectorConfig connectorConfig, - @SuppressWarnings("deprecation") com.yahoo.jdisc.http.SecretStore secretStore) { - validateConfig(connectorConfig.ssl()); - this.connectorConfig = connectorConfig; - this.secretStore = secretStore; - } - - @Override - public SslContextFactory getInstance(String containerId, int port) { - ConnectorConfig.Ssl sslConfig = connectorConfig.ssl(); - if (!sslConfig.enabled()) throw new IllegalStateException(); - SslContextFactory factory = new JDiscSslContextFactory(); - - switch (sslConfig.clientAuth()) { - case NEED_AUTH: - factory.setNeedClientAuth(true); - break; - case WANT_AUTH: - factory.setWantClientAuth(true); - break; - } - - // NOTE: All ciphers matching ^TLS_RSA_.*$ are disabled by default in Jetty 9.4.12+ (https://github.com/eclipse/jetty.project/issues/2807) - // JDisc will allow these ciphers by default to support older clients (e.g. Java 8u60 and curl 7.29.0) - // Removing the exclusion will allow for the TLS_RSA variants that are not covered by other exclusions - String[] excludedCiphersWithoutTlsRsaExclusion = Arrays.stream(factory.getExcludeCipherSuites()) - .filter(cipher -> !cipher.equals("^TLS_RSA_.*$")) - .toArray(String[]::new); - factory.setExcludeCipherSuites(excludedCiphersWithoutTlsRsaExclusion); - - switch (sslConfig.keyStoreType()) { - case JKS: - factory.setKeyStorePath(sslConfig.keyStorePath()); - factory.setKeyStoreType("JKS"); - factory.setKeyStorePassword(secretStore.getSecret(sslConfig.keyDbKey())); - break; - case PEM: - factory.setKeyStorePath(sslConfig.keyStorePath()); - factory.setKeyStore(createPemKeyStore(sslConfig.pemKeyStore())); - break; - } - - if (!sslConfig.trustStorePath().isEmpty()) { - factory.setTrustStorePath(sslConfig.trustStorePath()); - factory.setTrustStoreType(sslConfig.trustStoreType().toString()); - if (sslConfig.useTrustStorePassword()) { - factory.setTrustStorePassword(secretStore.getSecret(sslConfig.keyDbKey())); - } - } - - if (!sslConfig.prng().isEmpty()) { - factory.setSecureRandomAlgorithm(sslConfig.prng()); - } - - setStringArrayParameter( - factory, sslConfig.excludeProtocol(), ConnectorConfig.Ssl.ExcludeProtocol::name, SslContextFactory::setExcludeProtocols); - setStringArrayParameter( - factory, sslConfig.includeProtocol(), ConnectorConfig.Ssl.IncludeProtocol::name, SslContextFactory::setIncludeProtocols); - setStringArrayParameter( - factory, sslConfig.excludeCipherSuite(), ConnectorConfig.Ssl.ExcludeCipherSuite::name, SslContextFactory::setExcludeCipherSuites); - setStringArrayParameter( - factory, sslConfig.includeCipherSuite(), ConnectorConfig.Ssl.IncludeCipherSuite::name, SslContextFactory::setIncludeCipherSuites); - - factory.setKeyManagerFactoryAlgorithm(sslConfig.sslKeyManagerFactoryAlgorithm()); - factory.setProtocol(sslConfig.protocol()); - - return factory; - } - - private static void validateConfig(ConnectorConfig.Ssl config) { - if (!config.enabled()) return; - switch (config.keyStoreType()) { - case JKS: - validateJksConfig(config); - break; - case PEM: - validatePemConfig(config); - break; - } - if (!config.trustStorePath().isEmpty() && config.useTrustStorePassword() && config.keyDbKey().isEmpty()) { - throw new IllegalArgumentException("Missing password for JKS truststore"); - } - } - - private static void validateJksConfig(ConnectorConfig.Ssl ssl) { - if (!ssl.pemKeyStore().keyPath().isEmpty() || ! ssl.pemKeyStore().certificatePath().isEmpty()) { - throw new IllegalArgumentException("pemKeyStore attributes can not be set when keyStoreType is JKS."); - } - if (ssl.keyDbKey().isEmpty()) { - throw new IllegalArgumentException("Missing password for JKS keystore"); - } - } - - private static void validatePemConfig(ConnectorConfig.Ssl ssl) { - if (! ssl.keyStorePath().isEmpty()) { - throw new IllegalArgumentException("keyStorePath can not be set when keyStoreType is PEM"); - } - if (!ssl.keyDbKey().isEmpty()) { - log.warning("Encrypted PEM key stores are not supported. Password is only applied to truststore"); - } - if (ssl.pemKeyStore().certificatePath().isEmpty()) { - throw new IllegalArgumentException("Missing certificate path."); - } - if (ssl.pemKeyStore().keyPath().isEmpty()) { - throw new IllegalArgumentException("Missing key path."); - } - } - - private static KeyStore createPemKeyStore(ConnectorConfig.Ssl.PemKeyStore pemKeyStore) { - 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); - } catch (Exception e) { - throw new RuntimeException("Failed setting up key store for " + pemKeyStore.keyPath() + ", " + pemKeyStore.certificatePath(), e); - } - } - - private static void setStringArrayParameter(SslContextFactory sslContextFactory, - List configValues, - Function nameProperty, - BiConsumer 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/pem/PemKeyStore.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/pem/PemKeyStore.java deleted file mode 100644 index b52e923662f..00000000000 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/pem/PemKeyStore.java +++ /dev/null @@ -1,336 +0,0 @@ -// 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.pem; - -import com.google.common.base.Preconditions; -import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openssl.PEMException; -import org.bouncycastle.openssl.PEMKeyPair; -import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; - -import javax.annotation.concurrent.GuardedBy; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.Key; -import java.security.KeyStore; -import java.security.KeyStore.LoadStoreParameter; -import java.security.KeyStoreException; -import java.security.KeyStoreSpi; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.Enumeration; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Consumer; - -import static com.yahoo.jdisc.http.server.jetty.Exceptions.throwUnchecked; - -/** - * Exposes keys and certificates from unencrypted PEM keystore. - * - * @author Tony Vaagenes - * @author bjorncs - */ -public class PemKeyStore extends KeyStoreSpi { - - private static String KEY_ALIAS = "KEY"; - - static List aliases = Collections.emptyList(); - static Map attributes = Collections.emptyMap(); - private static final BouncyCastleProvider bouncyCastleProvider = new BouncyCastleProvider(); - - @GuardedBy("this") - private StoreRole storeRole; - @GuardedBy("this") - private Key privateKey; - @GuardedBy("this") - private final Map aliasToCertificate = new LinkedHashMap<>(); - - /** - * The user is responsible for closing any readers given in the parameter. - */ - @Override - public synchronized void engineLoad(LoadStoreParameter parameter) throws IOException { - if (storeRole != null) - throw new IllegalStateException("Already initialized."); - - if (parameter instanceof KeyStoreLoadParameter) { - storeRole = new KeyStoreRole(); - loadKeyStore((KeyStoreLoadParameter) parameter); - } else if (parameter instanceof TrustStoreLoadParameter) { - storeRole = new TrustStoreRole(); - loadTrustStore((TrustStoreLoadParameter) parameter); - } else { - throw new IllegalArgumentException("Expected key store or trust store load parameter, got " + parameter.getClass()); - } - } - - private void loadTrustStore(TrustStoreLoadParameter parameter) throws IOException { - withPemParser(parameter.certificateReader, this::loadCertificates); - } - - private void loadKeyStore(KeyStoreLoadParameter parameter) throws IOException{ - withPemParser(parameter.keyReader, this::loadPrivateKey); - withPemParser(parameter.certificateReader, this::loadCertificates); - } - - private static void withPemParser(ReaderForPath reader, Consumer f) throws IOException { - try { - //parser.close() will close the underlying reader, - //which we want to avoid. - //See engineLoad comment. - PEMParser parser = new PEMParser(reader.reader); - f.accept(parser); - } catch (Exception e) { - throw new RuntimeException("Failed loading pem key store " + reader.path, e); - } - } - - private void loadPrivateKey(PEMParser parser) { - try { - Object object = parser.readObject(); - PrivateKeyInfo privateKeyInfo; - if (object instanceof PEMKeyPair) { // Legacy PKCS1 - privateKeyInfo = ((PEMKeyPair) object).getPrivateKeyInfo(); - } else if (object instanceof PrivateKeyInfo) { // PKCS8 - privateKeyInfo = (PrivateKeyInfo) object; - } else { - throw new UnsupportedOperationException( - "Expected " + PrivateKeyInfo.class + " or " + PEMKeyPair.class + ", got " + object.getClass()); - } - - Object nextObject = parser.readObject(); - if (nextObject != null) { - throw new UnsupportedOperationException( - "Expected a single private key, but found a second element " + nextObject.getClass()); - } - - setPrivateKey(privateKeyInfo); - } catch (Exception e) { - throw throwUnchecked(e); - } - } - - private synchronized void setPrivateKey(PrivateKeyInfo privateKey) throws PEMException { - JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(bouncyCastleProvider); - this.privateKey = converter.getPrivateKey(privateKey); - } - - private void loadCertificates(PEMParser parser) { - try { - Object pemObject; - while ((pemObject = parser.readObject()) != null) { - addCertificate(pemObject); - } - - if (aliasToCertificate.isEmpty()) - throw new RuntimeException("No certificates available"); - } catch (Exception e) { - throw throwUnchecked(e); - } - } - - private synchronized void addCertificate(Object pemObject) throws CertificateException { - if (pemObject instanceof X509CertificateHolder) { - JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(bouncyCastleProvider); - String alias = "cert-" + aliasToCertificate.size(); - aliasToCertificate.put(alias, converter.getCertificate((X509CertificateHolder) pemObject)); - } else { - throw new UnsupportedOperationException("Expected X509 certificate, got " + pemObject.getClass()); - } - } - - @Override - public synchronized Enumeration engineAliases() { - return Collections.enumeration(storeRole.engineAliases()); - - } - - @Override - public synchronized boolean engineIsKeyEntry(String alias) { - return KEY_ALIAS.equals(alias); - } - - @Override - public synchronized Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException { - Preconditions.checkArgument(KEY_ALIAS.equals(alias)); - return privateKey; - } - - @Override - public synchronized boolean engineIsCertificateEntry(String alias) { - return aliasToCertificate.containsKey(alias); - } - - - @Override - public synchronized Certificate engineGetCertificate(String alias) { - return aliasToCertificate.get(alias); - } - - @Override - public synchronized Certificate[] engineGetCertificateChain(String alias) { - Preconditions.checkArgument(KEY_ALIAS.equals(alias)); - return aliasToCertificate.values().toArray(new Certificate[aliasToCertificate.size()]); - } - - - @Override - public synchronized boolean engineContainsAlias(String alias) { - return storeRole.engineContainsAlias(alias); - } - - @Override - public synchronized int engineSize() { - return storeRole.engineSize(); - } - - @Override - public synchronized String engineGetCertificateAlias(final Certificate certificate) { - for (Entry entry : aliasToCertificate.entrySet()) { - if (entry.getValue() == certificate) - return entry.getKey(); - } - - return null; - } - - @Override - public synchronized Date engineGetCreationDate(String alias) { - throw new UnsupportedOperationException(); - } - - @Override - public synchronized void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { - throw new UnsupportedOperationException(); - } - - @Override - public synchronized void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { - throw new UnsupportedOperationException(); - } - - @Override - public synchronized void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException { - throw new UnsupportedOperationException(); - } - - @Override - public synchronized void engineDeleteEntry(String alias) throws KeyStoreException { - throw new UnsupportedOperationException(); - } - - - @Override - public synchronized void engineStore(OutputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException { - throw new UnsupportedOperationException(); - } - - @Override - public synchronized void engineLoad(InputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException { - throw new UnsupportedOperationException(); - } - - private interface StoreRole { - Collection engineAliases(); - boolean engineContainsAlias(String alias); - int engineSize(); - } - - private class KeyStoreRole implements StoreRole { - @Override - public Collection engineAliases() { - return Collections.singletonList(KEY_ALIAS); - } - - @Override - public boolean engineContainsAlias(String alias) { - return KEY_ALIAS.equals(alias); - } - - @Override - public int engineSize() { - return 1; - } - } - - private class TrustStoreRole implements StoreRole{ - @Override - public Collection engineAliases() { - return aliasToCertificate.keySet(); - } - - @Override - public boolean engineContainsAlias(String alias) { - return aliasToCertificate.containsKey(alias); - } - - @Override - public int engineSize() { - return aliasToCertificate.size(); - } - } - - // A reader along with the path used to construct it. - private static class ReaderForPath { - final Reader reader; - final Path path; - - private ReaderForPath(Reader reader, Path path) { - this.reader = reader; - this.path = path; - } - - static ReaderForPath of(Path path) { - try { - return new ReaderForPath(Files.newBufferedReader(path), path); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - } - - static class TrustStoreLoadParameter implements KeyStore.LoadStoreParameter { - final ReaderForPath certificateReader; - - TrustStoreLoadParameter(Path certificateReader) { - this.certificateReader = ReaderForPath.of(certificateReader); - } - - @Override - public KeyStore.ProtectionParameter getProtectionParameter() { - return null; - } - } - - static class KeyStoreLoadParameter implements KeyStore.LoadStoreParameter { - final ReaderForPath certificateReader; - final ReaderForPath keyReader; - - KeyStoreLoadParameter(Path certificateReader, Path keyReader) { - this.certificateReader = ReaderForPath.of(certificateReader); - this.keyReader = ReaderForPath.of(keyReader); - } - - @Override - public KeyStore.ProtectionParameter getProtectionParameter() { - return null; - } - } - -} diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/pem/PemSslKeyStore.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/pem/PemSslKeyStore.java deleted file mode 100644 index fe41d74f692..00000000000 --- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/pem/PemSslKeyStore.java +++ /dev/null @@ -1,64 +0,0 @@ -// 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.pem; - -import com.yahoo.jdisc.http.ssl.pem.PemKeyStore.KeyStoreLoadParameter; -import com.yahoo.jdisc.http.ssl.pem.PemKeyStore.TrustStoreLoadParameter; - -import java.io.IOException; -import java.nio.file.Path; -import java.security.KeyStore; -import java.security.KeyStore.LoadStoreParameter; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.Provider; -import java.security.Security; -import java.security.cert.CertificateException; - -/** - * Responsible for creating pem key stores. - * - * @author Tony Vaagenes - * @author bjorncs - */ -public class PemSslKeyStore { - - static { - Security.addProvider(new PemKeyStoreProvider()); - } - - private static final String KEY_STORE_TYPE = "PEM"; - - private final LoadStoreParameter loadParameter; - private KeyStore keyStore; - - public PemSslKeyStore(Path certificatePath, Path keyPath) { - this.loadParameter = new KeyStoreLoadParameter(certificatePath, keyPath); - } - - public PemSslKeyStore(Path certificatePath) { - this.loadParameter = new TrustStoreLoadParameter(certificatePath); - } - - public KeyStore loadJavaKeyStore() - throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { - if (keyStore == null) { - keyStore = KeyStore.getInstance(KEY_STORE_TYPE); - keyStore.load(loadParameter); - } - return keyStore; - } - - private static class PemKeyStoreProvider extends Provider { - - static final String NAME = "PEMKeyStoreProvider"; - static final double VERSION = 1; - static final String DESCRIPTION = "Provides PEM keystore support"; - - @SuppressWarnings("deprecation") // TODO: Remove annotation and use new super ctor when we don't need Java 8 support anymore. - PemKeyStoreProvider() { - super(NAME, VERSION, DESCRIPTION); - putService(new Service(this, "KeyStore", "PEM", PemKeyStore. class.getName(), PemKeyStore.aliases, PemKeyStore.attributes)); - } - } - -} 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 3356eb3a100..30c74ed2c35 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 @@ -66,60 +66,3 @@ ssl.caCertificateFile string default="" # Client authentication mode. See SSLEngine.getNeedClientAuth()/getWantClientAuth() for details. ssl.clientAuth enum { DISABLED, WANT_AUTH, NEED_AUTH } default=DISABLED - - -######################################################################################### -# Config below is deprecated. Do not use -######################################################################################### - -# The name of the key to the password to the key store if in the secret store, if JKS is used. -# Must be empty with PEM -# By default this is also used to look up the password to the trust store. -ssl.keyDbKey string default="" -# TODO Rename keyDbKey to keyStorePassword after introducing custom services.xml syntax - -# Names of protocols to exclude. -ssl.excludeProtocol[].name string - -# Names of protocols to include. -ssl.includeProtocol[].name string - -# Names of cipher suites to exclude. -ssl.excludeCipherSuite[].name string - -# Names of cipher suites to include. -ssl.includeCipherSuite[].name string - -# The type of the keystore. -ssl.keyStoreType enum { JKS, PEM } default=JKS - -# JKS only - the path to the keystore. -ssl.keyStorePath string default="" - -ssl.pemKeyStore.keyPath string default="" -ssl.pemKeyStore.certificatePath string default="" - -ssl.trustStoreType enum { JKS } default=JKS - -# JKS only - the path to the truststore. -ssl.trustStorePath string default="" - -# TODO Add separate config for truststore password - -# Whether we should use keyDbKey as password to the trust store (true, default), -# or use no password with the trust store (false) -ssl.useTrustStorePassword bool default=true -# TODO Fix broken semantics with truststore and keystore password in Vespa 7 / Vespa 8 - -# The algorithm name used by the KeyManagerFactory. -ssl.sslKeyManagerFactoryAlgorithm string default="SunX509" - -# The SSL protocol passed to SSLContext.getInstance() -ssl.protocol string default="TLS" - -# The SecureRandom implementation passed to SSLEngine.init() -# Java have a default pseudo-random number generator (PRNG) for crypto operations. This default may have performance -# issues on some platform (e.g. NativePRNG in Linux utilizes a global lock). Changing the generator to SHA1PRNG may -# improve performance. Set value to empty string to use the default generator. -ssl.prng string default="" - 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 eb18a3ee341..cf32801ce88 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 @@ -17,9 +17,6 @@ import java.net.InetSocketAddress; import java.nio.channels.ServerSocketChannel; import java.util.Map; -import static com.yahoo.jdisc.http.ConnectorConfig.Ssl; -import static com.yahoo.jdisc.http.ConnectorConfig.Ssl.KeyStoreType.Enum.JKS; -import static com.yahoo.jdisc.http.ConnectorConfig.Ssl.KeyStoreType.Enum.PEM; import static org.hamcrest.CoreMatchers.equalTo; /** @@ -27,30 +24,6 @@ import static org.hamcrest.CoreMatchers.equalTo; */ public class ConnectorFactoryTest { - @Test(expectedExceptions = IllegalArgumentException.class) - public void ssl_jks_config_is_validated() { - ConnectorConfig config = new ConnectorConfig( - new ConnectorConfig.Builder() - .ssl(new Ssl.Builder() - .enabled(true) - .keyStoreType(JKS) - .pemKeyStore( - new Ssl.PemKeyStore.Builder() - .keyPath("nonEmpty")))); - ConnectorFactory willThrowException = createConnectorFactory(config); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void ssl_pem_config_is_validated() { - ConnectorConfig config = new ConnectorConfig( - new ConnectorConfig.Builder() - .ssl(new Ssl.Builder() - .enabled(true) - .keyStoreType(PEM) - .keyStorePath("nonEmpty"))); - ConnectorFactory willThrowException = createConnectorFactory(config); - } - @Test public void requireThatNoPreBoundChannelWorks() throws Exception { Server server = new Server(); -- cgit v1.2.3