diff options
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); } |