Remove mutual TLS configuration, in favor of the Cloud Foundry Java Buildpack's container security provider support.
This commit is contained in:
@@ -39,11 +39,6 @@
|
||||
<artifactId>httpclient</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
|
||||
@@ -19,17 +19,11 @@ package org.springframework.credhub.configuration;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.ssl.SSLContexts;
|
||||
|
||||
import org.springframework.credhub.support.ClientOptions;
|
||||
import org.springframework.credhub.support.SslConfiguration;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -50,23 +44,19 @@ public class ClientHttpRequestFactoryFactory {
|
||||
ClientHttpRequestFactoryFactory.class.getClassLoader());
|
||||
|
||||
/**
|
||||
* Create a {@link ClientHttpRequestFactory} for the given {@link ClientOptions} and
|
||||
* {@link SslConfiguration}.
|
||||
* Create a {@link ClientHttpRequestFactory} for the given {@link ClientOptions}.
|
||||
*
|
||||
* @param options must not be {@literal null}
|
||||
* @param sslConfiguration must not be {@literal null}
|
||||
* @return a new {@link ClientHttpRequestFactory}. Lifecycle beans must be initialized
|
||||
* after obtaining.
|
||||
*/
|
||||
public static ClientHttpRequestFactory create(ClientOptions options,
|
||||
SslConfiguration sslConfiguration) {
|
||||
public static ClientHttpRequestFactory create(ClientOptions options) {
|
||||
|
||||
Assert.notNull(options, "ClientOptions must not be null");
|
||||
Assert.notNull(sslConfiguration, "SslConfiguration must not be null");
|
||||
|
||||
try {
|
||||
if (HTTP_COMPONENTS_PRESENT) {
|
||||
return HttpComponents.usingHttpComponents(options, sslConfiguration);
|
||||
return HttpComponents.usingHttpComponents(options);
|
||||
}
|
||||
}
|
||||
catch (GeneralSecurityException e) {
|
||||
@@ -79,36 +69,16 @@ public class ClientHttpRequestFactoryFactory {
|
||||
throw new IllegalStateException("Only Apache HTTP Components is supported.");
|
||||
}
|
||||
|
||||
private static boolean hasSslConfiguration(SslConfiguration sslConfiguration) {
|
||||
return sslConfiguration.getTrustStore() != null
|
||||
|| sslConfiguration.getKeyStore() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequestFactory} for Apache HttpComponents.
|
||||
*/
|
||||
static class HttpComponents {
|
||||
|
||||
static ClientHttpRequestFactory usingHttpComponents(ClientOptions options,
|
||||
SslConfiguration sslConfiguration)
|
||||
static ClientHttpRequestFactory usingHttpComponents(ClientOptions options)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
HttpClientBuilder httpClientBuilder = HttpClients.custom();
|
||||
|
||||
if (hasSslConfiguration(sslConfiguration)) {
|
||||
SSLContext sslContext = SSLContexts.custom()
|
||||
.loadTrustMaterial(sslConfiguration.getKeyStore(),
|
||||
new TrustSelfSignedStrategy())
|
||||
.loadKeyMaterial(sslConfiguration.getTrustStore(),
|
||||
sslConfiguration.getKeyPassword())
|
||||
.build();
|
||||
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
|
||||
sslContext);
|
||||
httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
|
||||
httpClientBuilder.setSSLContext(sslContext);
|
||||
}
|
||||
|
||||
RequestConfig requestConfig = RequestConfig.custom()
|
||||
.setConnectTimeout(options.getConnectionTimeout())
|
||||
.setSocketTimeout(options.getReadTimeout())
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.credhub.core.CloudFoundryAppInstanceProperties;
|
||||
import org.springframework.credhub.core.CredHubProperties;
|
||||
import org.springframework.credhub.core.CredHubTemplate;
|
||||
import org.springframework.credhub.support.ClientOptions;
|
||||
import org.springframework.credhub.support.SslConfiguration;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
|
||||
/**
|
||||
@@ -84,18 +83,17 @@ public class CredHubConfiguration {
|
||||
* Create a {@link ClientFactoryWrapper} containing a
|
||||
* {@link ClientHttpRequestFactory}. {@link ClientHttpRequestFactory} is not exposed
|
||||
* as root bean because {@link ClientHttpRequestFactory} is configured with
|
||||
* {@link ClientOptions} and {@link SslConfiguration} which are not necessarily
|
||||
* {@link ClientOptions} which are not necessarily
|
||||
* applicable for the whole application.
|
||||
*
|
||||
* @return the {@link ClientFactoryWrapper} to wrap a {@link ClientHttpRequestFactory}
|
||||
* instance.
|
||||
* @see #clientOptions()
|
||||
* @see #sslConfiguration()
|
||||
*/
|
||||
@Bean
|
||||
public ClientFactoryWrapper clientHttpRequestFactoryWrapper() {
|
||||
ClientHttpRequestFactory clientHttpRequestFactory =
|
||||
ClientHttpRequestFactoryFactory.create(clientOptions(), sslConfiguration());
|
||||
ClientHttpRequestFactoryFactory.create(clientOptions());
|
||||
return new ClientFactoryWrapper(clientHttpRequestFactory);
|
||||
}
|
||||
|
||||
@@ -108,20 +106,6 @@ public class CredHubConfiguration {
|
||||
return new ClientOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the default {@link SslConfiguration} to configure SSL context parameters.
|
||||
* The default configuration uses a certificate and key supplied in the application
|
||||
* container to configure mutual SSL authentication between the client application
|
||||
* and the CredHub server.
|
||||
*
|
||||
* @return the default {@link SslConfiguration}
|
||||
*/
|
||||
private SslConfiguration sslConfiguration() {
|
||||
CloudFoundryAppInstanceProperties properties = cloudFoundryAppInstanceProperties();
|
||||
return SslConfiguration.forContainerCert(properties.getInstanceCertLocation(),
|
||||
properties.getInstanceKeyLocation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for {@link ClientHttpRequestFactory} to not expose the bean globally.
|
||||
*/
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.credhub.support;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.Certificate;
|
||||
|
||||
import org.bouncycastle.cert.X509CertificateHolder;
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||
import org.bouncycastle.openssl.PEMKeyPair;
|
||||
import org.bouncycastle.openssl.PEMParser;
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
||||
|
||||
/**
|
||||
* Client configuration for SSL connectivity.
|
||||
*/
|
||||
public class SslConfiguration {
|
||||
private static final char[] KEY_PASSWORD = "keystore".toCharArray();
|
||||
private static final String CERTIFICATE_NAME = "credhub-cert";
|
||||
private static final String KEY_NAME = "credhub-key";
|
||||
|
||||
private KeyStore trustStore;
|
||||
private KeyStore keyStore;
|
||||
|
||||
/**
|
||||
* Create an empty {@link SslConfiguration}. Intended for internal use.
|
||||
*/
|
||||
public SslConfiguration() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link SslConfiguration} that uses a certificate and private key that
|
||||
* have been placed in a Cloud Foundry application container for use with mutual SSL
|
||||
* authentication to CredHub.
|
||||
*
|
||||
* @param instanceCertLocation the absolute path of the certificate file in the app
|
||||
* instance container
|
||||
* @param instanceKeyLocation the absolute path of the private key file in the app
|
||||
* instance container
|
||||
* @return the {@link SslConfiguration} configured to use the container certificate
|
||||
* and private key
|
||||
*/
|
||||
public static SslConfiguration forContainerCert(String instanceCertLocation,
|
||||
String instanceKeyLocation) {
|
||||
SslConfiguration sslConfiguration = new SslConfiguration();
|
||||
KeyStore keyStore = sslConfiguration.buildKeyStore(instanceCertLocation,
|
||||
instanceKeyLocation);
|
||||
sslConfiguration.setKeyStore(keyStore);
|
||||
sslConfiguration.setTrustStore(keyStore);
|
||||
return sslConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link KeyStore key store} resource used to configure the SSL context.
|
||||
*
|
||||
* @return the key store
|
||||
*/
|
||||
public KeyStore getKeyStore() {
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
private void setKeyStore(KeyStore keyStore) {
|
||||
this.keyStore = keyStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link KeyStore trust store} resource used to configure the SSL context.
|
||||
*
|
||||
* @return the trust store
|
||||
*/
|
||||
public KeyStore getTrustStore() {
|
||||
return trustStore;
|
||||
}
|
||||
|
||||
private void setTrustStore(KeyStore keyStore) {
|
||||
this.trustStore = keyStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the password used to secure the generated key store.
|
||||
*
|
||||
* @return they key store password
|
||||
*/
|
||||
public char[] getKeyPassword() {
|
||||
return KEY_PASSWORD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link KeyStore} using the container certificate and private key.
|
||||
*
|
||||
* @param instanceCertLocation the absolute path of the certificate file in the app
|
||||
* instance container
|
||||
* @param instanceKeyLocation the absolute path of the private key file in the app
|
||||
* instance container
|
||||
* @return the created key store
|
||||
*/
|
||||
private KeyStore buildKeyStore(String instanceCertLocation,
|
||||
String instanceKeyLocation) {
|
||||
Certificate cert = parseCertificate(instanceCertLocation);
|
||||
PrivateKey key = parsePrivateKey(instanceKeyLocation);
|
||||
return createKeyStore(cert, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a PEM-formatted certificate and convert to a {@link Certificate}.
|
||||
*
|
||||
* @param certificateLocation the absolute path of the certificate file in the app
|
||||
* instance container
|
||||
* @return the created {@link Certificate}
|
||||
*/
|
||||
private Certificate parseCertificate(String certificateLocation) {
|
||||
try {
|
||||
PEMParser parser = new PEMParser(new FileReader(certificateLocation));
|
||||
X509CertificateHolder certHolder =
|
||||
(X509CertificateHolder) parser.readObject();
|
||||
JcaX509CertificateConverter converter = new JcaX509CertificateConverter();
|
||||
return converter.getCertificate(certHolder);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Error parsing and loading certificate from location "
|
||||
+ certificateLocation,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a PEM-formatted key and convert to a {@link PrivateKey}.
|
||||
*
|
||||
* @param keyLocation the absolute path of the key file in the app
|
||||
* instance container
|
||||
* @return the created {@link PrivateKey}
|
||||
*/
|
||||
private PrivateKey parsePrivateKey(String keyLocation) {
|
||||
try {
|
||||
PEMParser reader = new PEMParser(new FileReader(keyLocation));
|
||||
PEMKeyPair key = (PEMKeyPair) reader.readObject();
|
||||
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
|
||||
return converter.getKeyPair(key).getPrivate();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Error parsing and loading private key from location " + keyLocation,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link KeyStore} from the provided certificate and private key.
|
||||
*
|
||||
* @param cert the certifcate to add to the key store
|
||||
* @param key the private key to add to the key store
|
||||
* @return the created {@link KeyStore}
|
||||
*/
|
||||
private KeyStore createKeyStore(Certificate cert, PrivateKey key) {
|
||||
try {
|
||||
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keystore.load(null);
|
||||
keystore.setCertificateEntry(CERTIFICATE_NAME, cert);
|
||||
keystore.setKeyEntry(KEY_NAME, key, KEY_PASSWORD, new Certificate[] { cert });
|
||||
return keystore;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException("Error creating keystore ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,21 +22,19 @@ import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.credhub.support.ClientOptions;
|
||||
import org.springframework.credhub.support.SslConfiguration;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.credhub.configuration.ClientHttpRequestFactoryFactory.HttpComponents.usingHttpComponents;
|
||||
|
||||
public class ClientHttpRequestFactoryFactoryTests {
|
||||
|
||||
@Test
|
||||
public void httpComponentsClientCreated() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory =
|
||||
ClientHttpRequestFactoryFactory.HttpComponents.usingHttpComponents(
|
||||
new ClientOptions(), new SslConfiguration());
|
||||
ClientHttpRequestFactory factory = usingHttpComponents(new ClientOptions());
|
||||
|
||||
assertThat(factory, instanceOf(HttpComponentsClientHttpRequestFactory.class));
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
<properties>
|
||||
<jackson.version>2.8.7</jackson.version>
|
||||
<httpclient.version>4.5.3</httpclient.version>
|
||||
<bouncycastle.version>1.56</bouncycastle.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -88,13 +87,6 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user