All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.zookeeper.common.ClientX509Util Maven / Gradle / Ivy

There is a newer version: 8.410.10
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.zookeeper.common;

import com.yahoo.vespa.zookeeper.tls.VespaZookeeperTlsContextUtils;
import io.netty.handler.ssl.DelegatingSslContext;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * X509 utilities specific for client-server communication framework.
 * 

* Modified to use Vespa's TLS context, whenever it is available, instead of the file-based key and trust stores of ZK 3.9. * Based on https://github.com/apache/zookeeper/blob/branch-3.9/zookeeper-server/src/main/java/org/apache/zookeeper/common/ClientX509Util.java * * @author jonmv */ public class ClientX509Util extends X509Util { private static final Logger LOG = LoggerFactory.getLogger(ClientX509Util.class); private final String sslAuthProviderProperty = getConfigPrefix() + "authProvider"; private final String sslProviderProperty = getConfigPrefix() + "sslProvider"; @Override protected String getConfigPrefix() { return "zookeeper.ssl."; } @Override protected boolean shouldVerifyClientHostname() { return false; } public String getSslAuthProviderProperty() { return sslAuthProviderProperty; } public String getSslProviderProperty() { return sslProviderProperty; } public SslContext createNettySslContextForClient(ZKConfig config) throws X509Exception.KeyManagerException, X509Exception.TrustManagerException, SSLException { SslContextBuilder sslContextBuilder = SslContextBuilder.forClient(); KeyManager km; TrustManager tm; if (VespaZookeeperTlsContextUtils.tlsContext().isPresent()) { km = VespaZookeeperTlsContextUtils.tlsContext().get().sslContext().keyManager(); tm = VespaZookeeperTlsContextUtils.tlsContext().get().sslContext().trustManager(); } else { String keyStoreLocation = config.getProperty(getSslKeystoreLocationProperty(), ""); String keyStorePassword = getPasswordFromConfigPropertyOrFile(config, getSslKeystorePasswdProperty(), getSslKeystorePasswdPathProperty()); String keyStoreType = config.getProperty(getSslKeystoreTypeProperty()); if (keyStoreLocation.isEmpty()) { LOG.warn("{} not specified", getSslKeystoreLocationProperty()); km = null; } else { km = createKeyManager(keyStoreLocation, keyStorePassword, keyStoreType); } tm = getTrustManager(config); } if (km != null) { sslContextBuilder.keyManager(km); } if (tm != null) { sslContextBuilder.trustManager(tm); } sslContextBuilder.enableOcsp(config.getBoolean(getSslOcspEnabledProperty())); sslContextBuilder.protocols(getEnabledProtocols(config)); Iterable enabledCiphers = getCipherSuites(config); if (enabledCiphers != null) { sslContextBuilder.ciphers(enabledCiphers); } sslContextBuilder.sslProvider(getSslProvider(config)); SslContext sslContext1 = sslContextBuilder.build(); if (getFipsMode(config) && isServerHostnameVerificationEnabled(config)) { return addHostnameVerification(sslContext1, "Server"); } else { return sslContext1; } } public SslContext createNettySslContextForServer(ZKConfig config) throws X509Exception.SSLContextException, X509Exception.KeyManagerException, X509Exception.TrustManagerException, SSLException { KeyManager km; TrustManager tm; if (VespaZookeeperTlsContextUtils.tlsContext().isPresent()) { km = VespaZookeeperTlsContextUtils.tlsContext().get().sslContext().keyManager(); tm = VespaZookeeperTlsContextUtils.tlsContext().get().sslContext().trustManager(); } else { String keyStoreLocation = config.getProperty(getSslKeystoreLocationProperty(), ""); String keyStorePassword = getPasswordFromConfigPropertyOrFile(config, getSslKeystorePasswdProperty(), getSslKeystorePasswdPathProperty()); String keyStoreType = config.getProperty(getSslKeystoreTypeProperty()); if (keyStoreLocation.isEmpty()) { throw new X509Exception.SSLContextException( "Keystore is required for SSL server: " + getSslKeystoreLocationProperty()); } km = createKeyManager(keyStoreLocation, keyStorePassword, keyStoreType); tm = getTrustManager(config); } return createNettySslContextForServer(config, km, tm); } public SslContext createNettySslContextForServer(ZKConfig config, KeyManager keyManager, TrustManager trustManager) throws SSLException { SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(keyManager); if (trustManager != null) { sslContextBuilder.trustManager(trustManager); } sslContextBuilder.enableOcsp(config.getBoolean(getSslOcspEnabledProperty())); sslContextBuilder.protocols(getEnabledProtocols(config)); sslContextBuilder.clientAuth(getClientAuth(config).toNettyClientAuth()); Iterable enabledCiphers = getCipherSuites(config); if (enabledCiphers != null) { sslContextBuilder.ciphers(enabledCiphers); } sslContextBuilder.sslProvider(getSslProvider(config)); SslContext sslContext1 = sslContextBuilder.build(); if (getFipsMode(config) && isClientHostnameVerificationEnabled(config)) { return addHostnameVerification(sslContext1, "Client"); } else { return sslContext1; } } private SslContext addHostnameVerification(SslContext sslContext, String clientOrServer) { return new DelegatingSslContext(sslContext) { @Override protected void initEngine(SSLEngine sslEngine) { SSLParameters sslParameters = sslEngine.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); sslEngine.setSSLParameters(sslParameters); if (LOG.isDebugEnabled()) { LOG.debug("{} hostname verification: enabled HTTPS style endpoint identification algorithm", clientOrServer); } } }; } private String[] getEnabledProtocols(final ZKConfig config) { String enabledProtocolsInput = config.getProperty(getSslEnabledProtocolsProperty()); if (enabledProtocolsInput == null) { return new String[]{ config.getProperty(getSslProtocolProperty(), DEFAULT_PROTOCOL) }; } return enabledProtocolsInput.split(","); } private X509Util.ClientAuth getClientAuth(final ZKConfig config) { return X509Util.ClientAuth.fromPropertyValue(config.getProperty(getSslClientAuthProperty())); } private Iterable getCipherSuites(final ZKConfig config) { String cipherSuitesInput = config.getProperty(getSslCipherSuitesProperty()); if (cipherSuitesInput == null) { if (getSslProvider(config) != SslProvider.JDK) { return null; } return List.of(X509Util.getDefaultCipherSuites()); } else { return List.of(cipherSuitesInput.split(",")); } } public SslProvider getSslProvider(ZKConfig config) { return SslProvider.valueOf(config.getProperty(getSslProviderProperty(), "JDK")); } private TrustManager getTrustManager(ZKConfig config) throws X509Exception.TrustManagerException { String trustStoreLocation = config.getProperty(getSslTruststoreLocationProperty(), ""); String trustStorePassword = getPasswordFromConfigPropertyOrFile(config, getSslTruststorePasswdProperty(), getSslTruststorePasswdPathProperty()); String trustStoreType = config.getProperty(getSslTruststoreTypeProperty()); boolean sslCrlEnabled = config.getBoolean(getSslCrlEnabledProperty()); boolean sslOcspEnabled = config.getBoolean(getSslOcspEnabledProperty()); boolean sslServerHostnameVerificationEnabled = isServerHostnameVerificationEnabled(config); boolean sslClientHostnameVerificationEnabled = isClientHostnameVerificationEnabled(config); if (trustStoreLocation.isEmpty()) { LOG.warn("{} not specified", getSslTruststoreLocationProperty()); return null; } else { return createTrustManager(trustStoreLocation, trustStorePassword, trustStoreType, sslCrlEnabled, sslOcspEnabled, sslServerHostnameVerificationEnabled, sslClientHostnameVerificationEnabled, getFipsMode(config)); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy