diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-03-17 12:06:30 +0100 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-03-17 12:06:30 +0100 |
commit | cbd7a553e33d57fd3fd69b6c0c4a032a66d46bfb (patch) | |
tree | f46ecdd9856e88c9761c99d394c581afeae94ba1 /zookeeper-server | |
parent | e91a0341b66180d8a0ac8f1a8f17b0fcd4e5a30f (diff) |
Use custom x509 authentication provider for ZK server
Default provider implementation from ZK does not work in conjunction
with ssl context supplier (fails on missing trust manager).
Diffstat (limited to 'zookeeper-server')
3 files changed, 53 insertions, 4 deletions
diff --git a/zookeeper-server/zookeeper-server-3.6.2/src/main/java/com/yahoo/vespa/zookeeper/VespaMtlsAuthenticationProvider.java b/zookeeper-server/zookeeper-server-3.6.2/src/main/java/com/yahoo/vespa/zookeeper/VespaMtlsAuthenticationProvider.java new file mode 100644 index 00000000000..d72e36ba909 --- /dev/null +++ b/zookeeper-server/zookeeper-server-3.6.2/src/main/java/com/yahoo/vespa/zookeeper/VespaMtlsAuthenticationProvider.java @@ -0,0 +1,41 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.zookeeper; + +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.common.X509Exception; +import org.apache.zookeeper.data.Id; +import org.apache.zookeeper.server.ServerCnxn; +import org.apache.zookeeper.server.auth.AuthenticationProvider; +import org.apache.zookeeper.server.auth.X509AuthenticationProvider; + +import java.security.cert.X509Certificate; +import java.util.logging.Logger; + +/** + * A {@link AuthenticationProvider} to be used in combination with Vespa mTLS + * + * @author bjorncs + */ +public class VespaMtlsAuthenticationProvider extends X509AuthenticationProvider { + + private static final Logger log = Logger.getLogger(VespaMtlsAuthenticationProvider.class.getName()); + + public VespaMtlsAuthenticationProvider() throws X509Exception { super(null, null);} + + @Override + public KeeperException.Code handleAuthentication(ServerCnxn cnxn, byte[] authData) { + // Vespa's mTLS peer authorization rules are performed by the underlying trust manager implementation. + // The client is authorized once the SSL handshake has completed. + X509Certificate[] certificateChain = (X509Certificate[]) cnxn.getClientCertificateChain(); + if (certificateChain == null || certificateChain.length == 0) { + log.warning("Client not authenticated - should not be possible with clientAuth=NEED"); + return KeeperException.Code.AUTHFAILED; + } + X509Certificate certificate = certificateChain[0]; + cnxn.addAuthInfo(new Id(getScheme(), certificate.getSubjectX500Principal().getName())); + return KeeperException.Code.OK; + } + + @Override public String getScheme() { return "vespaMtls"; } + +} 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 9f2144966e0..0cb495fef2a 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 @@ -152,7 +152,7 @@ public class Configurator { String configFieldPrefix(); - default void appendTlsConfig(StringBuilder builder, Optional<TlsContext> tlsContext) { + default void appendSharedTlsConfig(StringBuilder builder, 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(",")); @@ -195,8 +195,10 @@ public class Configurator { sb.append("client.portUnification=").append(portUnification).append("\n") .append("clientPort=").append(secureClientPort ? 0 : config.clientPort()).append("\n") .append("secureClientPort=").append(secureClientPort ? config.clientPort() : 0).append("\n"); - - appendTlsConfig(sb, tlsContext); + tlsContext.ifPresent(ignored -> + sb.append("ssl.authProvider.vespaMtls=com.yahoo.vespa.zookeeper.VespaMtlsAuthenticationProvider\n") + .append("ssl.authProvider=vespaMtls\n")); + appendSharedTlsConfig(sb, tlsContext); return sb.toString(); } @@ -239,7 +241,7 @@ public class Configurator { } sb.append("sslQuorum=").append(sslQuorum).append("\n"); sb.append("portUnification=").append(portUnification).append("\n"); - appendTlsConfig(sb, tlsContext); + appendSharedTlsConfig(sb, tlsContext); return sb.toString(); } 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 147b61a804c..3fdb900def7 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 @@ -231,6 +231,8 @@ public class ConfiguratorTest { "client.portUnification=true\n" + "clientPort=2181\n" + "secureClientPort=0\n" + + "ssl.authProvider.vespaMtls=com.yahoo.vespa.zookeeper.VespaMtlsAuthenticationProvider\n" + + "ssl.authProvider=vespaMtls\n" + tlsClientServerConfig(); validateConfigFile(cfgFile, expected); } @@ -245,6 +247,8 @@ public class ConfiguratorTest { "client.portUnification=true\n" + "clientPort=2181\n" + "secureClientPort=0\n" + + "ssl.authProvider.vespaMtls=com.yahoo.vespa.zookeeper.VespaMtlsAuthenticationProvider\n" + + "ssl.authProvider=vespaMtls\n" + tlsClientServerConfig(); validateConfigFile(cfgFile, expected); } @@ -259,6 +263,8 @@ public class ConfiguratorTest { "client.portUnification=false\n" + "clientPort=0\n" + "secureClientPort=2181\n" + + "ssl.authProvider.vespaMtls=com.yahoo.vespa.zookeeper.VespaMtlsAuthenticationProvider\n" + + "ssl.authProvider=vespaMtls\n" + tlsClientServerConfig(); validateConfigFile(cfgFile, expected); } |