com.netflix.client.ssl.URLSslContextFactory Maven / Gradle / Ivy
/*
*
* Copyright 2013 Netflix, Inc.
*
* Licensed 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 com.netflix.client.ssl;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
/**
* Secure socket factory that is used the NIWS code if a non-standard key store or trust store
* is specified.
*
* @author Danny Yuan
* @author Peter D. Stout
*/
public class URLSslContextFactory extends AbstractSslContextFactory{
private final static Logger LOGGER = LoggerFactory.getLogger(URLSslContextFactory.class);
private final URL keyStoreUrl;
private final URL trustStoreUrl;
/**
* Creates a {@code ClientSSLSocketFactory} instance. This instance loads only the given trust
* store file and key store file. Both trust store and key store must be protected by passwords,
* even though it is not mandated by JSSE.
*
* @param trustStoreUrl A {@link URL} that points to a trust store file. If non-null, this URL
* must refer to a JKS key store file that contains trusted certificates.
* @param trustStorePassword The password of the given trust store file. If a trust store is
* specified, then the password may not be empty.
* @param keyStoreUrl A {@code URL} that points to a key store file that contains both client
* certificate and the client's private key. If non-null, this URL must be of JKS format.
* @param keyStorePassword the password of the given key store file. If a key store is
* specified, then the password may not be empty.
* @throws ClientSslSocketFactoryException thrown if creating this instance fails.
*/
public URLSslContextFactory(final URL trustStoreUrl, final String trustStorePassword, final URL keyStoreUrl, final String keyStorePassword) throws ClientSslSocketFactoryException {
super(createKeyStore(trustStoreUrl, trustStorePassword), trustStorePassword, createKeyStore(keyStoreUrl, keyStorePassword), keyStorePassword);
this.keyStoreUrl = keyStoreUrl;
this.trustStoreUrl = trustStoreUrl;
LOGGER.info("Loaded keyStore from: {}", keyStoreUrl);
LOGGER.info("loaded trustStore from: {}", trustStoreUrl);
}
/**
* Opens the specified key or trust store using the given password.
*
* In case of failure {@link com.netflix.client.ssl.ClientSslSocketFactoryException} is thrown, and wrapps the
* underlying cause exception. That could be:
*
* - KeyStoreException if the JRE doesn't support the standard Java Keystore format, in other words: never
* - NoSuchAlgorithmException if the algorithm used to check the integrity of the keystore cannot be found
* - CertificateException if any of the certificates in the keystore could not be loaded
* -
* IOException if there is an I/O or format problem with the keystore data, if a
* password is required but not given, or if the given password was incorrect. If the
* error is due to a wrong password, the cause of the IOException should be an UnrecoverableKeyException.
*
*
*
* @param storeFile the location of the store to load
* @param password the password protecting the store
* @return the newly loaded key store
* @throws ClientSslSocketFactoryException a wrapper exception for any problems encountered during keystore creation.
*/
private static KeyStore createKeyStore(final URL storeFile, final String password) throws ClientSslSocketFactoryException {
if(storeFile == null){
return null;
}
Preconditions.checkArgument(StringUtils.isNotEmpty(password), "Null keystore should have empty password, defined keystore must have password");
KeyStore keyStore = null;
try{
keyStore = KeyStore.getInstance("jks");
InputStream is = storeFile.openStream();
try {
keyStore.load(is, password.toCharArray());
} catch (NoSuchAlgorithmException e) {
throw new ClientSslSocketFactoryException(String.format("Failed to create a keystore that supports algorithm %s: %s", SOCKET_ALGORITHM, e.getMessage()), e);
} catch (CertificateException e) {
throw new ClientSslSocketFactoryException(String.format("Failed to create keystore with algorithm %s due to certificate exception: %s", SOCKET_ALGORITHM, e.getMessage()), e);
} finally {
try {
is.close();
} catch (IOException ignore) { // NOPMD
}
}
}catch(KeyStoreException e){
throw new ClientSslSocketFactoryException(String.format("KeyStore exception creating keystore: %s", e.getMessage()), e);
} catch (IOException e) {
throw new ClientSslSocketFactoryException(String.format("IO exception creating keystore: %s", e.getMessage()), e);
}
return keyStore;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("ClientSslSocketFactory [trustStoreUrl=").append(trustStoreUrl);
if (trustStoreUrl != null) {
builder.append(", trustStorePassword=");
builder.append(Strings.repeat("*", this.getTrustStorePasswordLength()));
}
builder.append(", keyStoreUrl=").append(keyStoreUrl);
if (keyStoreUrl != null) {
builder.append(", keystorePassword = ");
builder.append(Strings.repeat("*", this.getKeyStorePasswordLength()));
}
builder.append(']');
return builder.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy