Skip to content

Instantly share code, notes, and snippets.

@ex0b1t
Last active July 7, 2023 08:37
Show Gist options
  • Save ex0b1t/563bd016805fb3862565fa94014d0afb to your computer and use it in GitHub Desktop.
Save ex0b1t/563bd016805fb3862565fa94014d0afb to your computer and use it in GitHub Desktop.
package com.railway.security;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import lombok.extern.slf4j.Slf4j;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
/**
* CompositeX509TrustManager
* <p>
* Only needed as our trust store only ships with with 6 custom trusted certs, java default ships with 95, we need more!
* <br>
* <code>com.railway.security.CompositeX509TrustManager</code>
* <br>
*
* @since 03 July 2020
*/
@Slf4j
public class CompositeX509TrustManager implements X509TrustManager {
private final List<X509TrustManager> trustManagers;
public CompositeX509TrustManager(List<X509TrustManager> trustManagers) {
this.trustManagers = ImmutableList.copyOf(trustManagers);
}
public CompositeX509TrustManager(KeyStore keystore) {
this.trustManagers = ImmutableList.of(getDefaultTrustManager(), getTrustManager(keystore));
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
for (X509TrustManager trustManager : trustManagers) {
try {
trustManager.checkClientTrusted(chain, authType);
return; // someone trusts them. success!
} catch (CertificateException e) {
// maybe someone else will trust them
}
}
throw new CertificateException("None of the TrustManagers trust this certificate chain");
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
for (X509TrustManager trustManager : trustManagers) {
try {
trustManager.checkServerTrusted(chain, authType);
return; // someone trusts them. success!
} catch (CertificateException e) {
// maybe someone else will trust them
}
}
throw new CertificateException("None of the TrustManagers trust this certificate chain");
}
@Override
public X509Certificate[] getAcceptedIssuers() {
ImmutableList.Builder<X509Certificate> certificates = ImmutableList.builder();
for (X509TrustManager trustManager : trustManagers) {
for (X509Certificate cert : trustManager.getAcceptedIssuers()) {
certificates.add(cert);
}
}
return Iterables.toArray(certificates.build(), X509Certificate.class);
}
public static TrustManager[] getTrustManagers(KeyStore keyStore) {
return new TrustManager[]{new CompositeX509TrustManager(keyStore)};
}
public static X509TrustManager getDefaultTrustManager() {
return getTrustManager(null);
}
public static X509TrustManager getTrustManager(KeyStore keystore) {
return getTrustManager(TrustManagerFactory.getDefaultAlgorithm(), keystore);
}
public static X509TrustManager getTrustManager(String algorithm, KeyStore keystore) {
TrustManagerFactory factory;
try {
factory = TrustManagerFactory.getInstance(algorithm);
factory.init(keystore);
return Iterables.getFirst(Iterables.filter(
Arrays.asList(factory.getTrustManagers()), X509TrustManager.class), null);
} catch (NoSuchAlgorithmException | KeyStoreException e) {
log.error("Failed to get trust manager", e);
}
return null;
}
}
@Bean("trustManager")
Supplier<CompositeX509TrustManager> trustManagerSupplier(ServerProperties serverProperties) {
return () -> {
log.info("Autoconfigure: trustManagerSupplier");
CompositeX509TrustManager compositeX509TrustManager;
Ssl ssl = serverProperties.getSsl();
if (ssl != null && ssl.isEnabled() && ssl.getTrustStore() != null) {
log.info("Creating CompositeX509TrustManager");
char[] trustStorePassword = Optional.ofNullable(ssl.getTrustStorePassword())
.orElse("")
.toCharArray();
try {
File truststoreFile = ResourceUtils.getFile(ssl.getTrustStore());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream myKeys = new FileInputStream(truststoreFile);
keyStore.load(myKeys, trustStorePassword);
myKeys.close();
compositeX509TrustManager = new CompositeX509TrustManager(keyStore);
} catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException e) {
log.error("Failed to create CompositeX509TrustManager", e);
compositeX509TrustManager = null;
}
} else {
log.debug("No SSL CompositeX509TrustManager, returning null");
compositeX509TrustManager = null;
}
return compositeX509TrustManager;
};
}
@Bean("sslContextSupplier")
Supplier<SSLContext> sslContextSupplier(Supplier<CompositeX509TrustManager> trustManagerSupplier) {
return () -> {
log.info("Autoconfigure: sslContextSupplier");
SSLContext sslContext;
if (trustManagerSupplier.get() != null) {
try {
log.info("Creating creating ssl context");
sslContext = SSLContext.getInstance("TLS");
TrustManager[] tm = {trustManagerSupplier.get()};
sslContext.init(null, tm, null);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
log.error("Failed to create ssl context", e);
sslContext = null;
}
} else {
log.debug("No SSL context setup, returning null");
sslContext = null;
}
return sslContext;
};
}
@Bean("restTemplate")
RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory) {
log.info("Autoconfigure: restTemplate");
return new RestTemplate(clientHttpRequestFactory);
}
@Bean("clientHttpRequestFactory")
ClientHttpRequestFactory clientHttpRequestFactory(Supplier<SSLContext> sslContextSupplier) {
log.info("Autoconfigure: ClientHttpRequestFactory");
return Optional.ofNullable(sslContextSupplier.get())
.map(sslContext -> {
log.info("Enabling SSL ClientHttpRequestFactory");
final CloseableHttpClient httpClient = HttpClientBuilder.create()
.setSSLContext(sslContext)
.build();
return new HttpComponentsClientHttpRequestFactory(httpClient);
})
.orElseGet(() -> {
log.warn("Enabling ClientHttpRequestFactory with No SSL");
return new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create().build());
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment