summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2021-03-12 15:10:57 +0100
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2021-03-12 15:10:57 +0100
commit02b31925778bd85d0002257ea893cc08e10042e1 (patch)
tree8da18b5fc934047d133696e385ff2c6315250fc3
parent5fc288ac15612f400879f7278d588541fe8257a4 (diff)
Use SSLContext supplier for ZK server configuration
Remove use of keystore/truststore from disk. Only configure client secure port if TLS is enabled.
-rw-r--r--configdefinitions/src/vespa/zookeeper-server.def1
-rw-r--r--zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/Configurator.java131
-rw-r--r--zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/VespaSslContextProvider.java26
-rw-r--r--zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/ZooKeeperRunner.java2
-rw-r--r--zookeeper-server/zookeeper-server-common/src/test/java/com/yahoo/vespa/zookeeper/ConfiguratorTest.java162
5 files changed, 91 insertions, 231 deletions
diff --git a/configdefinitions/src/vespa/zookeeper-server.def b/configdefinitions/src/vespa/zookeeper-server.def
index 39785afd681..536cd993105 100644
--- a/configdefinitions/src/vespa/zookeeper-server.def
+++ b/configdefinitions/src/vespa/zookeeper-server.def
@@ -44,6 +44,7 @@ trustEmptySnapshot bool default=true
# TLS options
tlsForQuorumCommunication enum { OFF, PORT_UNIFICATION, TLS_WITH_PORT_UNIFICATION, TLS_ONLY } default=OFF
tlsForClientServerCommunication enum { OFF, PORT_UNIFICATION, TLS_WITH_PORT_UNIFICATION, TLS_ONLY } default=OFF
+# TODO(bjorncs): remove setting - no longer in use
jksKeyStoreFile string default="conf/zookeeper/zookeeper.jks"
dynamicReconfiguration bool default=false
diff --git a/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/Configurator.java b/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/Configurator.java
index ebf5032a4a7..aff4bb950f6 100644
--- a/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/Configurator.java
+++ b/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/Configurator.java
@@ -3,22 +3,14 @@
package com.yahoo.vespa.zookeeper;
import com.yahoo.cloud.config.ZookeeperServerConfig;
-import com.yahoo.security.KeyStoreBuilder;
-import com.yahoo.security.KeyStoreType;
-import com.yahoo.security.KeyStoreUtils;
-import com.yahoo.security.KeyUtils;
-import com.yahoo.security.X509CertificateUtils;
-import com.yahoo.security.tls.TransportSecurityOptions;
-import com.yahoo.text.Utf8;
+import com.yahoo.security.tls.TlsContext;
import com.yahoo.vespa.defaults.Defaults;
import java.io.FileWriter;
import java.io.IOException;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
+import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
@@ -34,39 +26,35 @@ public class Configurator {
private final ZookeeperServerConfig zookeeperServerConfig;
private final Path configFilePath;
- private final Path jksKeyStoreFilePath;
public Configurator(ZookeeperServerConfig zookeeperServerConfig) {
log.log(Level.FINE, zookeeperServerConfig.toString());
this.zookeeperServerConfig = zookeeperServerConfig;
this.configFilePath = makeAbsolutePath(zookeeperServerConfig.zooKeeperConfigFile());
- this.jksKeyStoreFilePath = makeAbsolutePath(zookeeperServerConfig.jksKeyStoreFile());
System.setProperty(ZOOKEEPER_JMX_LOG4J_DISABLE, "true");
System.setProperty("zookeeper.snapshot.trust.empty", Boolean.valueOf(zookeeperServerConfig.trustEmptySnapshot()).toString());
System.setProperty(ZOOKEEPER_JUTE_MAX_BUFFER, Integer.valueOf(zookeeperServerConfig.juteMaxBuffer()).toString());
}
- void writeConfigToDisk(Optional<TransportSecurityOptions> transportSecurityOptions) {
+ void writeConfigToDisk(Optional<TlsContext> tlsContext) {
configFilePath.toFile().getParentFile().mkdirs();
try {
- writeZooKeeperConfigFile(zookeeperServerConfig, transportSecurityOptions);
+ writeZooKeeperConfigFile(zookeeperServerConfig, tlsContext);
writeMyIdFile(zookeeperServerConfig);
- transportSecurityOptions.ifPresent(this::writeJksKeystore);
} catch (IOException e) {
throw new RuntimeException("Error writing zookeeper config", e);
}
}
private void writeZooKeeperConfigFile(ZookeeperServerConfig config,
- Optional<TransportSecurityOptions> transportSecurityOptions) throws IOException {
+ Optional<TlsContext> tlsContext) throws IOException {
try (FileWriter writer = new FileWriter(configFilePath.toFile())) {
- writer.write(transformConfigToString(config, transportSecurityOptions));
+ writer.write(transformConfigToString(config, tlsContext));
}
}
- private String transformConfigToString(ZookeeperServerConfig config,
- Optional<TransportSecurityOptions> transportSecurityOptions) {
+ private String transformConfigToString(ZookeeperServerConfig config, Optional<TlsContext> tlsContext) {
StringBuilder sb = new StringBuilder();
sb.append("tickTime=").append(config.tickTime()).append("\n");
sb.append("initLimit=").append(config.initLimit()).append("\n");
@@ -74,7 +62,6 @@ public class Configurator {
sb.append("maxClientCnxns=").append(config.maxClientConnections()).append("\n");
sb.append("snapCount=").append(config.snapshotCount()).append("\n");
sb.append("dataDir=").append(getDefaults().underVespaHome(config.dataDir())).append("\n");
- sb.append("secureClientPort=").append(config.secureClientPort()).append("\n");
sb.append("autopurge.purgeInterval=").append(config.autopurge().purgeInterval()).append("\n");
sb.append("autopurge.snapRetainCount=").append(config.autopurge().snapRetainCount()).append("\n");
// See http://zookeeper.apache.org/doc/r3.5.5/zookeeperAdmin.html#sc_zkCommands
@@ -90,8 +77,8 @@ public class Configurator {
sb.append("metricsProvider.className=org.apache.zookeeper.metrics.impl.NullMetricsProvider\n");
ensureThisServerIsRepresented(config.myid(), config.server());
config.server().forEach(server -> addServerToCfg(sb, server, config.clientPort()));
- sb.append(new TlsQuorumConfig(jksKeyStoreFilePath).createConfig(config, transportSecurityOptions));
- sb.append(new TlsClientServerConfig(jksKeyStoreFilePath).createConfig(config, transportSecurityOptions));
+ sb.append(new TlsQuorumConfig().createConfig(config, tlsContext));
+ sb.append(new TlsClientServerConfig().createConfig(config, tlsContext));
return sb.toString();
}
@@ -101,25 +88,6 @@ public class Configurator {
}
}
- private void writeJksKeystore(TransportSecurityOptions options) {
- Path privateKeyFile = options.getPrivateKeyFile().orElseThrow(() -> new RuntimeException("Could not find private key file"));
- Path certificatesFile = options.getCertificatesFile().orElseThrow(() -> new RuntimeException("Could not find certificates file"));
-
- PrivateKey privateKey;
- List<X509Certificate> certificates;
- try {
- privateKey = KeyUtils.fromPemEncodedPrivateKey(Utf8.toString(Files.readAllBytes(privateKeyFile)));
- certificates = X509CertificateUtils.certificateListFromPem(Utf8.toString(Files.readAllBytes(certificatesFile)));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- KeyStoreBuilder keyStoreBuilder = KeyStoreBuilder
- .withType(KeyStoreType.JKS)
- .withKeyEntry("foo", privateKey, certificates);
-
- KeyStoreUtils.writeKeyStoreToFile(keyStoreBuilder.build(), jksKeyStoreFilePath);
- }
-
private void ensureThisServerIsRepresented(int myid, List<ZookeeperServerConfig.Server> servers) {
boolean found = false;
for (ZookeeperServerConfig.Server server : servers) {
@@ -172,59 +140,41 @@ public class Configurator {
}
private interface TlsConfig {
+ String createConfig(ZookeeperServerConfig config, Optional<TlsContext> tlsContext);
+
default Optional<String> getEnvironmentVariable(String variableName) {
return Optional.ofNullable(System.getenv().get(variableName))
.filter(var -> !var.isEmpty());
}
- default void validateOptions(Optional<TransportSecurityOptions> transportSecurityOptions, String tlsSetting) {
- if (transportSecurityOptions.isEmpty() && !tlsSetting.equals("OFF"))
+ default void validateOptions(Optional<TlsContext> tlsContext, String tlsSetting) {
+ if (tlsContext.isEmpty() && !tlsSetting.equals("OFF"))
throw new RuntimeException("Could not retrieve transport security options");
}
String configFieldPrefix();
- Path jksKeyStoreFilePath();
-
- default String createCommonKeyStoreTrustStoreOptions(Optional<TransportSecurityOptions> transportSecurityOptions) {
- StringBuilder sb = new StringBuilder();
- transportSecurityOptions.ifPresent(options -> {
- sb.append(configFieldPrefix()).append(".keyStore.location=").append(jksKeyStoreFilePath()).append("\n");
- sb.append(configFieldPrefix()).append(".keyStore.type=JKS\n");
-
- Path caCertificatesFile = options.getCaCertificatesFile().orElseThrow(() -> new RuntimeException("Could not find ca certificates file"));
- sb.append(configFieldPrefix()).append(".trustStore.location=").append(caCertificatesFile).append("\n");
- sb.append(configFieldPrefix()).append(".trustStore.type=PEM\n");
+ default void appendTlsConfig(StringBuilder builder, ZookeeperServerConfig config, Optional<TlsContext> tlsContext) {
+ tlsContext.ifPresent(ctx -> {
+ builder.append(configFieldPrefix()).append(".context.supplier.class=").append(VespaSslContextProvider.class.getName()).append("\n");
+ String enabledCiphers = Arrays.stream(ctx.parameters().getCipherSuites()).sorted().collect(Collectors.joining(","));
+ builder.append(configFieldPrefix()).append(".ciphersuites=").append(enabledCiphers).append("\n");
+ String enabledProtocols = Arrays.stream(ctx.parameters().getProtocols()).sorted().collect(Collectors.joining(","));
+ builder.append(configFieldPrefix()).append(".enabledProtocols=").append(enabledProtocols).append("\n");
+ builder.append(configFieldPrefix()).append(".clientAuth=NEED\n");
});
- return sb.toString();
}
-
- default String createCommonConfig() {
- StringBuilder sb = new StringBuilder();
- sb.append(configFieldPrefix()).append(".hostnameVerification=false\n");
- sb.append(configFieldPrefix()).append(".clientAuth=NEED\n");
- sb.append(configFieldPrefix()).append(".ciphersuites=").append(VespaSslContextProvider.enabledTlsCiphersConfigValue()).append("\n");
- sb.append(configFieldPrefix()).append(".enabledProtocols=").append(VespaSslContextProvider.enabledTlsProtocolConfigValue()).append("\n");
- sb.append(configFieldPrefix()).append(".protocol=").append(VespaSslContextProvider.sslContextVersion()).append("\n");
- return sb.toString();
- }
-
}
static class TlsClientServerConfig implements TlsConfig {
- private final Path jksKeyStoreFilePath;
-
- TlsClientServerConfig(Path jksKeyStoreFilePath) {
- this.jksKeyStoreFilePath = jksKeyStoreFilePath;
- }
-
- String createConfig(ZookeeperServerConfig config, Optional<TransportSecurityOptions> transportSecurityOptions) {
+ @Override
+ public String createConfig(ZookeeperServerConfig config, Optional<TlsContext> tlsContext) {
String tlsSetting = getEnvironmentVariable("VESPA_TLS_FOR_ZOOKEEPER_CLIENT_SERVER_COMMUNICATION")
.orElse(config.tlsForClientServerCommunication().name());
- validateOptions(transportSecurityOptions, tlsSetting);
+ validateOptions(tlsContext, tlsSetting);
- StringBuilder sb = new StringBuilder(createCommonConfig());
+ StringBuilder sb = new StringBuilder();
boolean portUnification;
switch (tlsSetting) {
case "OFF":
@@ -239,7 +189,9 @@ public class Configurator {
throw new IllegalArgumentException("Unknown value of config setting tlsForClientServerCommunication: " + tlsSetting);
}
sb.append("client.portUnification=").append(portUnification).append("\n");
- sb.append(createCommonKeyStoreTrustStoreOptions(transportSecurityOptions));
+ // TODO This should override "clientPort" if TLS enabled without port unification);
+ tlsContext.ifPresent(ctx -> sb.append("secureClientPort=").append(config.secureClientPort()).append("\n"));
+ appendTlsConfig(sb, config, tlsContext);
return sb.toString();
}
@@ -248,28 +200,17 @@ public class Configurator {
public String configFieldPrefix() {
return "ssl";
}
-
- @Override
- public Path jksKeyStoreFilePath() {
- return jksKeyStoreFilePath;
- }
-
}
static class TlsQuorumConfig implements TlsConfig {
- private final Path jksKeyStoreFilePath;
-
- TlsQuorumConfig(Path jksKeyStoreFilePath) {
- this.jksKeyStoreFilePath = jksKeyStoreFilePath;
- }
-
- String createConfig(ZookeeperServerConfig config, Optional<TransportSecurityOptions> transportSecurityOptions) {
+ @Override
+ public String createConfig(ZookeeperServerConfig config, Optional<TlsContext> tlsContext) {
String tlsSetting = getEnvironmentVariable("VESPA_TLS_FOR_ZOOKEEPER_QUORUM_COMMUNICATION")
.orElse(config.tlsForQuorumCommunication().name());
- validateOptions(transportSecurityOptions, tlsSetting);
+ validateOptions(tlsContext, tlsSetting);
- StringBuilder sb = new StringBuilder(createCommonConfig());
+ StringBuilder sb = new StringBuilder();
boolean sslQuorum;
boolean portUnification;
switch (tlsSetting) {
@@ -293,7 +234,7 @@ public class Configurator {
}
sb.append("sslQuorum=").append(sslQuorum).append("\n");
sb.append("portUnification=").append(portUnification).append("\n");
- sb.append(createCommonKeyStoreTrustStoreOptions(transportSecurityOptions));
+ appendTlsConfig(sb, config, tlsContext);
return sb.toString();
}
@@ -302,12 +243,6 @@ public class Configurator {
public String configFieldPrefix() {
return "ssl.quorum";
}
-
- @Override
- public Path jksKeyStoreFilePath() {
- return jksKeyStoreFilePath;
- }
-
}
}
diff --git a/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/VespaSslContextProvider.java b/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/VespaSslContextProvider.java
index dc254ade071..b65cb9faf53 100644
--- a/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/VespaSslContextProvider.java
+++ b/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/VespaSslContextProvider.java
@@ -5,39 +5,21 @@ import com.yahoo.security.tls.TlsContext;
import com.yahoo.security.tls.TransportSecurityUtils;
import javax.net.ssl.SSLContext;
-import java.util.Collection;
-import java.util.List;
import java.util.function.Supplier;
-import java.util.stream.Collectors;
/**
- * Provider for Vespa {@link SSLContext} instance to Zookeeper + misc utility methods for providing Vespa TLS specific ZK configuration.
+ * Provider for Vespa {@link SSLContext} instance to Zookeeper.
*
* @author bjorncs
*/
public class VespaSslContextProvider implements Supplier<SSLContext> {
- private static final TlsContext tlsContext = TransportSecurityUtils.getSystemTlsContext().orElse(null);
+ private static final SSLContext sslContext = TransportSecurityUtils.getSystemTlsContext().map(TlsContext::context).orElse(null);
@Override
public SSLContext get() {
- if (!tlsEnabled()) throw new IllegalStateException("Vespa TLS is not enabled");
- return tlsContext.context();
+ if (sslContext == null) throw new IllegalStateException("Vespa TLS is not enabled");
+ return sslContext;
}
- public static boolean tlsEnabled() { return tlsContext != null; }
-
- public static String enabledTlsProtocolConfigValue() {
- // Fallback to all allowed protocols if we cannot determine which are actually supported by runtime
- Collection<String> enabledProtocols = tlsEnabled() ? List.of(tlsContext.parameters().getProtocols()) : TlsContext.ALLOWED_PROTOCOLS;
- return enabledProtocols.stream().sorted().collect(Collectors.joining(","));
- }
-
- public static String enabledTlsCiphersConfigValue() {
- // Fallback to all allowed ciphers if we cannot determine which are actually supported by runtime
- Collection<String> enabledCiphers = tlsEnabled() ? List.of(tlsContext.parameters().getCipherSuites()) : TlsContext.ALLOWED_CIPHER_SUITES;
- return enabledCiphers.stream().sorted().collect(Collectors.joining(","));
- }
-
- public static String sslContextVersion() { return tlsEnabled() ? tlsContext.context().getProtocol() : TlsContext.SSL_CONTEXT_VERSION; }
}
diff --git a/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/ZooKeeperRunner.java b/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/ZooKeeperRunner.java
index 812c974f9f8..adbc7a369b3 100644
--- a/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/ZooKeeperRunner.java
+++ b/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/ZooKeeperRunner.java
@@ -39,7 +39,7 @@ public class ZooKeeperRunner implements Runnable {
public ZooKeeperRunner(ZookeeperServerConfig zookeeperServerConfig, VespaZooKeeperServer server) {
this.zookeeperServerConfig = zookeeperServerConfig;
this.server = server;
- new Configurator(zookeeperServerConfig).writeConfigToDisk(TransportSecurityUtils.getOptions());
+ new Configurator(zookeeperServerConfig).writeConfigToDisk(TransportSecurityUtils.getSystemTlsContext());
executorService = Executors.newSingleThreadExecutor(new DaemonThreadFactory("zookeeper server"));
executorService.submit(this);
}
diff --git a/zookeeper-server/zookeeper-server-common/src/test/java/com/yahoo/vespa/zookeeper/ConfiguratorTest.java b/zookeeper-server/zookeeper-server-common/src/test/java/com/yahoo/vespa/zookeeper/ConfiguratorTest.java
index a7994531b93..aee44c90cbf 100644
--- a/zookeeper-server/zookeeper-server-common/src/test/java/com/yahoo/vespa/zookeeper/ConfiguratorTest.java
+++ b/zookeeper-server/zookeeper-server-common/src/test/java/com/yahoo/vespa/zookeeper/ConfiguratorTest.java
@@ -4,8 +4,12 @@ package com.yahoo.vespa.zookeeper;
import com.yahoo.cloud.config.ZookeeperServerConfig;
import com.yahoo.security.KeyUtils;
import com.yahoo.security.X509CertificateBuilder;
-import com.yahoo.security.X509CertificateUtils;
-import com.yahoo.security.tls.TransportSecurityOptions;
+import com.yahoo.security.tls.AuthorizationMode;
+import com.yahoo.security.tls.DefaultTlsContext;
+import com.yahoo.security.tls.HostnameVerification;
+import com.yahoo.security.tls.PeerAuthentication;
+import com.yahoo.security.tls.TlsContext;
+import com.yahoo.security.tls.policy.AuthorizedPeers;
import com.yahoo.yolean.Exceptions;
import org.junit.Before;
import org.junit.Rule;
@@ -15,13 +19,13 @@ import org.junit.rules.TemporaryFolder;
import javax.security.auth.x500.X500Principal;
import java.io.File;
import java.io.IOException;
-import java.io.UncheckedIOException;
import java.math.BigInteger;
import java.nio.file.Files;
-import java.nio.file.Path;
import java.security.KeyPair;
import java.security.cert.X509Certificate;
+import java.util.List;
import java.util.Optional;
+import java.util.Set;
import static com.yahoo.cloud.config.ZookeeperServerConfig.TlsForClientServerCommunication;
import static com.yahoo.cloud.config.ZookeeperServerConfig.TlsForQuorumCommunication;
@@ -32,7 +36,6 @@ import static com.yahoo.vespa.zookeeper.Configurator.ZOOKEEPER_JUTE_MAX_BUFFER;
import static java.time.Instant.EPOCH;
import static java.time.temporal.ChronoUnit.DAYS;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
/**
* Tests the zookeeper server.
@@ -41,7 +44,6 @@ public class ConfiguratorTest {
private File cfgFile;
private File idFile;
- private File jksKeyStoreFile;
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@@ -50,12 +52,11 @@ public class ConfiguratorTest {
public void setup() throws IOException {
cfgFile = folder.newFile();
idFile = folder.newFile();
- jksKeyStoreFile = folder.newFile();
}
@Test
public void config_is_written_correctly_when_one_server() {
- ZookeeperServerConfig.Builder builder = createConfigBuilderForSingleHost(cfgFile, idFile, jksKeyStoreFile);
+ ZookeeperServerConfig.Builder builder = createConfigBuilderForSingleHost(cfgFile, idFile);
new Configurator(builder.build()).writeConfigToDisk(Optional.empty());
validateConfigFileSingleHost(cfgFile);
validateIdFile(idFile, "0\n");
@@ -77,35 +78,32 @@ public class ConfiguratorTest {
@Test
public void config_is_written_correctly_with_tls_for_quorum_communication_port_unification() {
- ZookeeperServerConfig.Builder builder = createConfigBuilderForSingleHost(cfgFile, idFile, jksKeyStoreFile);
+ ZookeeperServerConfig.Builder builder = createConfigBuilderForSingleHost(cfgFile, idFile);
builder.tlsForQuorumCommunication(TlsForQuorumCommunication.PORT_UNIFICATION);
builder.tlsForClientServerCommunication(TlsForClientServerCommunication.PORT_UNIFICATION);
- Optional<TransportSecurityOptions> transportSecurityOptions = createTransportSecurityOptions();
- new Configurator(builder.build()).writeConfigToDisk(transportSecurityOptions);
- validateConfigFilePortUnification(cfgFile, jksKeyStoreFile, transportSecurityOptions.get().getCaCertificatesFile().get().toFile());
- validateThatJksKeyStoreFileExists(jksKeyStoreFile);
+ TlsContext tlsContext = createTlsContext();
+ new Configurator(builder.build()).writeConfigToDisk(Optional.of(tlsContext));
+ validateConfigFilePortUnification(cfgFile);
}
@Test
public void config_is_written_correctly_with_tls_for_quorum_communication_tls_with_port_unification() {
- ZookeeperServerConfig.Builder builder = createConfigBuilderForSingleHost(cfgFile, idFile, jksKeyStoreFile);
+ ZookeeperServerConfig.Builder builder = createConfigBuilderForSingleHost(cfgFile, idFile);
builder.tlsForQuorumCommunication(TlsForQuorumCommunication.TLS_WITH_PORT_UNIFICATION);
builder.tlsForClientServerCommunication(TlsForClientServerCommunication.TLS_WITH_PORT_UNIFICATION);
- Optional<TransportSecurityOptions> transportSecurityOptions = createTransportSecurityOptions();
- new Configurator(builder.build()).writeConfigToDisk(transportSecurityOptions);
- validateConfigFileTlsWithPortUnification(cfgFile, jksKeyStoreFile, transportSecurityOptions.get().getCaCertificatesFile().get().toFile());
- validateThatJksKeyStoreFileExists(jksKeyStoreFile);
+ TlsContext tlsContext = createTlsContext();
+ new Configurator(builder.build()).writeConfigToDisk(Optional.of(tlsContext));
+ validateConfigFileTlsWithPortUnification(cfgFile);
}
@Test
public void config_is_written_correctly_with_tls_for_quorum_communication_tls_only() {
- ZookeeperServerConfig.Builder builder = createConfigBuilderForSingleHost(cfgFile, idFile, jksKeyStoreFile);
+ ZookeeperServerConfig.Builder builder = createConfigBuilderForSingleHost(cfgFile, idFile);
builder.tlsForQuorumCommunication(TlsForQuorumCommunication.TLS_ONLY);
builder.tlsForClientServerCommunication(TlsForClientServerCommunication.TLS_ONLY);
- Optional<TransportSecurityOptions> transportSecurityOptions = createTransportSecurityOptions();
- new Configurator(builder.build()).writeConfigToDisk(transportSecurityOptions);
- validateConfigFileTlsOnly(cfgFile, jksKeyStoreFile, transportSecurityOptions.get().getCaCertificatesFile().get().toFile());
- validateThatJksKeyStoreFileExists(jksKeyStoreFile);
+ TlsContext tlsContext = createTlsContext();
+ new Configurator(builder.build()).writeConfigToDisk(Optional.of(tlsContext));
+ validateConfigFileTlsOnly(cfgFile);
}
@Test(expected = RuntimeException.class)
@@ -138,13 +136,12 @@ public class ConfiguratorTest {
assertEquals("" + max_buffer, System.getProperty(ZOOKEEPER_JUTE_MAX_BUFFER));
}
- private ZookeeperServerConfig.Builder createConfigBuilderForSingleHost(File cfgFile, File idFile, File jksKeyStoreFile) {
+ private ZookeeperServerConfig.Builder createConfigBuilderForSingleHost(File cfgFile, File idFile) {
ZookeeperServerConfig.Builder builder = new ZookeeperServerConfig.Builder();
builder.zooKeeperConfigFile(cfgFile.getAbsolutePath());
builder.myidFile(idFile.getAbsolutePath());
builder.server(newServer(0, "foo", 123, 321, false));
builder.myid(0);
- builder.jksKeyStoreFile(jksKeyStoreFile.getAbsolutePath());
return builder;
}
@@ -170,7 +167,6 @@ public class ConfiguratorTest {
"maxClientCnxns=0\n" +
"snapCount=50000\n" +
"dataDir=" + getDefaults().underVespaHome("var/zookeeper") + "\n" +
- "secureClientPort=2184\n" +
"autopurge.purgeInterval=1\n" +
"autopurge.snapRetainCount=15\n" +
"4lw.commands.whitelist=conf,cons,crst,dirs,dump,envi,mntr,ruok,srst,srvr,stat,wchs\n" +
@@ -183,58 +179,31 @@ public class ConfiguratorTest {
"metricsProvider.className=org.apache.zookeeper.metrics.impl.NullMetricsProvider\n";
}
- private String quorumKeyStoreAndTrustStoreConfig(File jksKeyStoreFilePath, File caCertificatesFilePath) {
- StringBuilder sb = new StringBuilder();
-
- sb.append("ssl.quorum.keyStore.location=").append(jksKeyStoreFilePath.getAbsolutePath()).append("\n");
- sb.append("ssl.quorum.keyStore.type=JKS\n");
- sb.append("ssl.quorum.trustStore.location=").append(caCertificatesFilePath.getAbsolutePath()).append("\n");
- sb.append("ssl.quorum.trustStore.type=PEM\n");
- return sb.toString();
- }
-
- private String clientServerKeyStoreAndTrustStoreConfig(File jksKeyStoreFilePath, File caCertificatesFilePath) {
- StringBuilder sb = new StringBuilder();
-
- sb.append("ssl.keyStore.location=").append(jksKeyStoreFilePath.getAbsolutePath()).append("\n");
- sb.append("ssl.keyStore.type=JKS\n");
- sb.append("ssl.trustStore.location=").append(caCertificatesFilePath.getAbsolutePath()).append("\n");
- sb.append("ssl.trustStore.type=PEM\n");
- return sb.toString();
- }
-
private void validateConfigFileSingleHost(File cfgFile) {
String expected =
commonConfig() +
"server.0=foo:321:123;2181\n" +
- commonTlsQuorumConfig() +
"sslQuorum=false\n" +
"portUnification=false\n" +
- commonTlsClientServerConfig() +
"client.portUnification=false\n";
validateConfigFile(cfgFile, expected);
}
- private String commonTlsQuorumConfig() {
- return "ssl.quorum.hostnameVerification=false\n" +
- "ssl.quorum.clientAuth=NEED\n" +
- "ssl.quorum.ciphersuites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256," +
- "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384," +
- "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256," +
- "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\n" +
- "ssl.quorum.enabledProtocols=TLSv1.2\n" +
- "ssl.quorum.protocol=TLS\n";
+ private String tlsQuorumConfig() {
+ return "ssl.quorum.context.supplier.class=com.yahoo.vespa.zookeeper.VespaSslContextProvider\n" +
+ "ssl.quorum.ciphersuites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256," +
+ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n" +
+ "ssl.quorum.enabledProtocols=TLSv1.2\n" +
+ "ssl.quorum.clientAuth=NEED\n";
}
- private String commonTlsClientServerConfig() {
- return "ssl.hostnameVerification=false\n" +
- "ssl.clientAuth=NEED\n" +
- "ssl.ciphersuites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256," +
- "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384," +
- "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256," +
- "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\n" +
- "ssl.enabledProtocols=TLSv1.2\n" +
- "ssl.protocol=TLS\n";
+ private String tlsClientServerConfig() {
+ return "secureClientPort=2184\n" +
+ "ssl.context.supplier.class=com.yahoo.vespa.zookeeper.VespaSslContextProvider\n" +
+ "ssl.ciphersuites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256," +
+ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n" +
+ "ssl.enabledProtocols=TLSv1.2\n" +
+ "ssl.clientAuth=NEED\n";
}
private void validateConfigFileMultipleHosts(File cfgFile) {
@@ -243,53 +212,45 @@ public class ConfiguratorTest {
"server.0=foo:321:123;2181\n" +
"server.1=bar:432:234;2181\n" +
"server.2=baz:543:345:observer;2181\n" +
- commonTlsQuorumConfig() +
"sslQuorum=false\n" +
"portUnification=false\n" +
- commonTlsClientServerConfig() +
"client.portUnification=false\n";
validateConfigFile(cfgFile, expected);
}
- private void validateConfigFilePortUnification(File cfgFile, File jksKeyStoreFile, File caCertificatesFile) {
+ private void validateConfigFilePortUnification(File cfgFile) {
String expected =
commonConfig() +
"server.0=foo:321:123;2181\n" +
- commonTlsQuorumConfig() +
"sslQuorum=false\n" +
"portUnification=true\n" +
- quorumKeyStoreAndTrustStoreConfig(jksKeyStoreFile, caCertificatesFile) +
- commonTlsClientServerConfig() +
+ tlsQuorumConfig() +
"client.portUnification=true\n" +
- clientServerKeyStoreAndTrustStoreConfig(jksKeyStoreFile, caCertificatesFile);
+ tlsClientServerConfig();
validateConfigFile(cfgFile, expected);
}
- private void validateConfigFileTlsWithPortUnification(File cfgFile, File jksKeyStoreFile, File caCertificatesFile) {
+ private void validateConfigFileTlsWithPortUnification(File cfgFile) {
String expected =
commonConfig() +
"server.0=foo:321:123;2181\n" +
- commonTlsQuorumConfig() +
"sslQuorum=true\n" +
"portUnification=true\n" +
- quorumKeyStoreAndTrustStoreConfig(jksKeyStoreFile, caCertificatesFile) +
- commonTlsClientServerConfig() +
+ tlsQuorumConfig() +
"client.portUnification=true\n" +
- clientServerKeyStoreAndTrustStoreConfig(jksKeyStoreFile, caCertificatesFile);
+ tlsClientServerConfig();
validateConfigFile(cfgFile, expected);
}
- private void validateConfigFileTlsOnly(File cfgFile, File jksKeyStoreFile, File caCertificatesFile) {
+ private void validateConfigFileTlsOnly(File cfgFile) {
String expected =
commonConfig() +
"server.0=foo:321:123;2181\n" +
- commonTlsQuorumConfig() +
"sslQuorum=true\n" +
"portUnification=false\n" +
- quorumKeyStoreAndTrustStoreConfig(jksKeyStoreFile, caCertificatesFile) +
- commonTlsClientServerConfig() +
+ tlsQuorumConfig() +
"client.portUnification=false\n" +
- clientServerKeyStoreAndTrustStoreConfig(jksKeyStoreFile, caCertificatesFile);
+ tlsClientServerConfig();
validateConfigFile(cfgFile, expected);
}
@@ -298,33 +259,14 @@ public class ConfiguratorTest {
assertEquals(expected, actual);
}
- private void validateThatJksKeyStoreFileExists(File cfgFile) {
- assertTrue(cfgFile.exists() && cfgFile.canRead());
- }
-
- private Optional<TransportSecurityOptions> createTransportSecurityOptions() {
- try {
- KeyPair keyPair = KeyUtils.generateKeypair(EC);
- Path privateKeyFile = folder.newFile().toPath();
- Files.writeString(privateKeyFile, KeyUtils.toPem(keyPair.getPrivate()));
-
- X509Certificate certificate = X509CertificateBuilder
- .fromKeypair(keyPair, new X500Principal("CN=dummy"), EPOCH, EPOCH.plus(1, DAYS), SHA256_WITH_ECDSA, BigInteger.ONE)
- .build();
- Path certificateChainFile = folder.newFile().toPath();
- String certificatePem = X509CertificateUtils.toPem(certificate);
- Files.writeString(certificateChainFile, certificatePem);
-
- Path caCertificatesFile = folder.newFile().toPath();
- Files.writeString(caCertificatesFile, certificatePem);
-
- return Optional.of(new TransportSecurityOptions.Builder()
- .withCertificates(certificateChainFile, privateKeyFile)
- .withCaCertificates(caCertificatesFile)
- .build());
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ private TlsContext createTlsContext() {
+ KeyPair keyPair = KeyUtils.generateKeypair(EC);
+ X509Certificate certificate = X509CertificateBuilder
+ .fromKeypair(keyPair, new X500Principal("CN=dummy"), EPOCH, EPOCH.plus(1, DAYS), SHA256_WITH_ECDSA, BigInteger.ONE)
+ .build();
+ return new DefaultTlsContext(
+ List.of(certificate), keyPair.getPrivate(), List.of(certificate), new AuthorizedPeers(Set.of()),
+ AuthorizationMode.ENFORCE, PeerAuthentication.NEED, HostnameVerification.DISABLED);
}
}