Spring LDAP over SSL - spring

I am trying to implement spring ldap with multi tenancy where number of ldap servers is unknown.
Client is supposed to insert their LDAP info and certificate into a form and I am supposed to create a secure TLS connection. I've managed to setup the regular LDAP without SSL but I am having problems configuring SSL to work properly.
This is my test server:
docker run \
--rm \
-p 389:389 \
-p 636:636 \
--hostname local.dev \
--name ldap-local \
-e LDAP_ORGANISATION="Local" \
-e LDAP_DOMAIN=local.dev \
-e LDAP_BASE_DN="dc=local,dc=dev" \
-e LDAP_LOG_LEVEL=-1 \
-e LDAP_READONLY_USER=true \
-e LDAP_READONLY_USER_USERNAME=milos \
-e LDAP_READONLY_USER_PASSWORD=milos1234 \
-v /home/devel/script/ldap/keys:/container/service/slapd/assets/certs \
-e LDAP_TLS_CRT_FILENAME=ldap.crt \
-e LDAP_TLS_KEY_FILENAME=ldap.key \
-e LDAP_TLS_CA_CRT_FILENAME=jatheon.crt \
-e LDAP_TLS_VERIFY_CLIENT=try \
osixia/openldap:1.2.4 --copy-service --loglevel trace
keys mounted folder contains self-signed certificate generated with:
openssl req -newkey rsa:1024 -x509 -sha256 -days 3650 -nodes -out ldap.crt -keyout ldap.key
I use Spring LdapTemplate to validate the connection:
final LdapTemplate template = new LdapTemplate(contextFactory.buildLdapContext(connection));
template.getContextSource().getContext(connection.getUserDN(), connection.getAdminPassword());
buildLdapContext(Connection):
public LdapContextSource buildLdapContext(final LdapConnection connection) {
final LdapContextSource context = new LdapContextSource();
context.setBase(connection.getBaseDN());
context.setUrl(connection.getConnectionUrl());
context.setUserDn(connection.getUserDN());
context.setPassword(connection.getAdminPassword());
if(connection.hasCertificate()) {
final DefaultTlsDirContextAuthenticationStrategy authenticationStrategy = new DefaultTlsDirContextAuthenticationStrategy();
authenticationStrategy.setHostnameVerifier((hostname, session) -> hostname.equals(connection.getHost()));
authenticationStrategy.setSslSocketFactory(ldapSslSocketFactoryBuilder.buildSslSocketFactory(connection));
authenticationStrategy.setShutdownTlsGracefully(true);
context.setAuthenticationStrategy(authenticationStrategy);
}
context.afterPropertiesSet();
return context;
}
buildSslSocketFactory:
public SSLSocketFactory buildSslSocketFactory(final LdapConnection connection) {
try {
final KeyStore store = buildKeyStore(connection);
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(store, null);
final SSLContext ctx = SSLContext.getInstance("TLSv1.2");
ctx.init(kmf.getKeyManagers(), new TrustManager[] {new DummyTrustManager()}, null);
return ctx.getSocketFactory();
} catch(Exception e) {
throw new LdapException(e.getMessage(), e);
}
}
private KeyStore buildKeyStore(final LdapConnection ldapConnection) {
try {
// Load in-memory keystore
final KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null);
// Decode certificate
byte[] decoded = Base64.decodeBase64(ldapConnection.getSslCertificate()
.replaceAll(BEGIN_CERT, "")
.replaceAll(END_CERT, "")
.trim().getBytes(StandardCharsets.UTF_8));
// Load certificate
CertificateFactory certificateFactory = CertificateFactory.getInstance("x.509");
Certificate cert = certificateFactory.generateCertificate(new ByteArrayInputStream(decoded));
keystore.setCertificateEntry(ldapConnection.getConnectionUrl(), cert);
return keystore;
} catch(Exception e) {
log.error(e.getMessage(), e);
throw new LdapException(e.getMessage(), e);
}
}
I use DummyTrustManager in order to enable Self-Signed certificates:
public class DummyTrustManager implements X509TrustManager {
#Override
public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
This works, but for some reason it works for any random certificate ie. I can place any valid certificate and it will work. This is the OpenLDAP log:
5ea9a99d connection_read(12): unable to get TLS client DN, error=49 id=1000
5ea9a99d conn=1000 fd=12 TLS established tls_ssf=256 ssf=256
If I change -e LDAP_TLS_VERIFY_CLIENT=demand the request fails:
TLS: can't accept: No certificate was found..
5ea9aaee connection_read(12): TLS accept failure error=-1 id=1000, closing

Related

ECDSA related ciphers not working with Spring Cloud Gateway and OpenSSL

I am currently trying to make ECDSA related ciphers to work with TLS 1.2 in Spring Cloud Gateway (Spring Boot Parent 2.6.7 and Spring Cloud 2021.0.2). Here's the snippet of WebServerFactoryCustomizer
#Bean
public WebServerFactoryCustomizer<NettyReactiveWebServerFactory> customizer() {
return factory -> factory.addServerCustomizers(httpServer -> httpServer.secure(sslContextSpec -> {
try {
Ssl ssl = factory.getSsl();
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
char[] keyStorePassword = ssl.getKeyStorePassword().toCharArray();
keyStore.load(resourceLoader.getResource(ssl.getKeyStore()).getInputStream(), keyStorePassword);
KeyManagerFactory keyManagerFactory = OpenSslCachingX509KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyStorePassword);
Http11SslContextSpec http11SslContextSpec = Http11SslContextSpec.forServer(keyManagerFactory)
.configure(sslContextBuilder -> {
sslContextBuilder.sslProvider(SslProvider.OPENSSL);
sslContextBuilder.ciphers(Arrays.asList(ssl.getCiphers()));
sslContextBuilder.protocols(ssl.getEnabledProtocols());
sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
sslContextBuilder.clientAuth(ClientAuth.REQUIRE);
});
sslContextSpec.sslContext(http11SslContextSpec)
.handlerConfigurator(sslHandler -> {
sslHandler.setCloseNotifyReadTimeout(18000, TimeUnit.MILLISECONDS);
sslHandler.setHandshakeTimeout(19000, TimeUnit.MILLISECONDS);
SSLParameters sslParameters = sslHandler.engine().getSSLParameters();
sslParameters.setUseCipherSuitesOrder(false);
sslHandler.engine().setSSLParameters(sslParameters);
});
} catch (UnrecoverableKeyException | IOException | CertificateException | KeyStoreException |
NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}));
}
When I try to connect using openssl s_client with ECDHE-ECDSA-AES128-GCM-SHA256 cipher the server returns an error with no shared ciphers, but I do have it in the configuration as
server.ssl.ciphers=TLS_RSA_WITH_AES_128_GCM_SHA256,\
TLS_RSA_WITH_AES_256_GCM_SHA384, \
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
server.ssl.enabled-protocols=TLSv1.2
This behavior was observed when I upgraded versions from Spring Boot 2.3.3.RELEASE and Spring Cloud Hoxton.SR7. Any advice/suggestions would be of great help on fixing or correctly configuring it.

How to find out what trusted CA's are preinstalled for AWS Lambda?

For my AWS Lambda, I need to know what trusted CA's are there. I want to have a list of CA's so for a service the lambda tries to reach it can trust it without installing any new certs.
You could find out yourself:
public class PrintCAInfo implements RequestStreamHandler {
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
LambdaLogger logger = context.getLogger();
StringBuilder stringBuilder = new StringBuilder("[");
try {
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
for( TrustManager trustManager: trustManagerFactory.getTrustManagers()) {
X509TrustManager x509TrustManager = (X509TrustManager)trustManager;
for(X509Certificate x509Certificate: x509TrustManager.getAcceptedIssuers() ) {
stringBuilder.append("{");
stringBuilder.append("\"subjectDN\":\"");
stringBuilder.append(x509Certificate.getSubjectDN().toString().replaceAll("\"", ""));
stringBuilder.append("\"},");
}
}
} catch (NoSuchAlgorithmException | KeyStoreException e) {
e.printStackTrace();
}
stringBuilder = new StringBuilder(stringBuilder.substring(0, stringBuilder.length() - 1));
stringBuilder.append("]");
OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
writer.write(stringBuilder.toString());
logger.log(stringBuilder.toString());
writer.close();
}
}
This returns (and logs) a very simple JSON body:
[
{
"subjectDN": "CN=Amazon RDS eu-south-1 CA, OU=Amazon RDS, O=Amazon Web Services, Inc., L=Seattle, ST=Washington, C=US"
},
{
"subjectDN": "CN=Hongkong Post Root CA 1, O=Hongkong Post, C=HK"
},
{
"subjectDN": "CN=SecureTrust CA, O=SecureTrust Corporation, C=US"
},
{
"subjectDN": "CN=Entrust Root Certification Authority - EC1, OU=(c) 2012 Entrust, Inc. - for authorized use only, OU=See www.entrust.net/legal-terms, O=Entrust, Inc., C=US"
},
{
"subjectDN": "CN=DigiCert Global Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US"
},
{
"subjectDN": "OU=Security Communication RootCA1, O=SECOM Trust.net, C=JP"
},

Spring boot ssl how to trust all valid certificates

I have enabled ssl in my spring boot application and anytime I want to use a Rest service like googleapis or facebook I have to add the certificate in the truststore.
I use openssl to get the certificate:
openssl s_client -connect googleapis.com:443
and I import it into the truststore :
keytool.exe -import -noprompt -trustcacerts -alias googleapis.com
-file googleapis.com.cer -keystore app-server.p12 -storepass *****
The problem is that it's very inconvenient to manage, when the certificate expires I have to update the certificates in the truststore everytime.
Also even if I add the right certificate sometimes I get an error:
Caused by: javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to
find valid certification path to requested target
I know these certificates are valid so, is there a possibility to trust them automatically without adding them in the truststore?
Here is my ssl configuration
ssl:
enabled: true
key-store: classpath:keystore/app-server.p12
key-store-password: ******
key-alias: app-server
key-store-type: PKCS12
trust-store: classpath:keystore/app-server.p12
trust-store-password: *****
trust-store-type: PKCS12
keyStorePath: config/keystore/app-server.p12
Also I had to add system properties in the main method
private static String keyStorePath;
private static String keyStorePassword;
#Value("${server.ssl.keyStorePath}")
public void setKeyStorePath(String keyStorePath) {
ClientUiApplication.keyStorePath = keyStorePath;
}
#Value("${server.ssl.key-store-password}")
public void setKeyStorePassword(String keyStorePassword) {
ClientUiApplication.keyStorePassword = keyStorePassword;
}
public static void main(String[] args) {
SpringApplication.run(ClientUiApplication.class, args);
System.setProperty("javax.net.ssl.trustStore", keyStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", keyStorePassword);
}
Another important detail, I need a truststore because I use self-signed certificates generated with Keytool. Without, my services cannot communicate with each other.
You give the code:
public static void main(String[] args) {
SpringApplication.run(ClientUiApplication.class, args);
System.setProperty("javax.net.ssl.trustStore", keyStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", keyStorePassword);
}
This means that you force the java trust store to be the trust store you provide. The default trust store is not in use anymore.
So yes, you have to add every needed root certificates in this trust store to not have the issue you describe.
Why do you need to have a specific trust store?
If there is no use, remove that.
If you have a specific additional certificate you have to trust, you'd better add this certificate to the default trust store (the jre/lib/security/cacerts file)
You can also Bypass SSL Certificate Checking using CloseableHttpClient
public static CloseableHttpClient getCloseableHttpClient()
{
CloseableHttpClient httpClient = null;
try {
httpClient = HttpClients.custom().
setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).
setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy()
{
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
{
return true;
}
}).build()).build();
} catch (KeyManagementException e) {
LOGGER.error("KeyManagementException in creating http client instance", e);
} catch (NoSuchAlgorithmException e) {
LOGGER.error("NoSuchAlgorithmException in creating http client instance", e);
} catch (KeyStoreException e) {
LOGGER.error("KeyStoreException in creating http client instance", e);
}
return httpClient;
}
It will trust automatically all the certificates and saves you from SSLHandshakeException: sun.security.validator.ValidatorException
Note this method is not recommended in Production

How to use p12 client certificate with spring feign client

I have a Spring Boot application that calls a remote service.
This remote web service provided me a p12 file that should authenticate my application.
How do I configure my feign client to use the p12 certificate ?
I've tried settings these properties:
-Djavax.net.ssl.keyStore=path_to_cert.p12 -Djavax.net.ssl.keyStorePassword=xxx -Djavax.net.ssl.keyStoreType=PKCS12
But it doesn't change anything, I still get this error:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I could finally manage to do it with a lot of blind trial and error.
The problem is, by default, the feign builder builds feign clients with null SSLSocketFactory:
org.springframework.cloud.openfeign.FeignClientsConfiguration#feignBuilder:
#Bean
#Scope("prototype")
#ConditionalOnMissingBean
public Feign.Builder feignBuilder(Retryer retryer) {
return Feign.builder().retryer(retryer);
}
feign.Feign.Builder:
public static class Builder {
// ...
private Client client = new Client.Default(null, null);
So, I had to define this bean in a #Configuration:
#Bean
#Profile({"prod", "docker"})
public Feign.Builder feignBuilder() {
return Feign.builder()
.retryer(Retryer.NEVER_RETRY)
.client(new Client.Default(getSSLSocketFactory(), null));
with this method: (can't remember source)
SSLSocketFactory getSSLSocketFactory() {
char[] allPassword = keyStorePassword.toCharArray();
SSLContext sslContext = null;
try {
sslContext = SSLContextBuilder
.create()
.setKeyStoreType(keyStoreType)
.loadKeyMaterial(ResourceUtils.getFile(keyStore), allPassword, allPassword)
.build();
} catch (Exception e) { /* *** */ }
return sslContext.getSocketFactory();
}
Now, it works for me, I debugged though the feign client calls and the sslSocketFactory is correctly passed to the underlying connection.
In case you wish to achieve the above effect programmatically without using keytool, you can do the following:
class CustomFeignConfiguration {
private val log = Logger.getLogger(this.javaClass.name)
#Value("\${client_p12_base64_encoded_string}")
private val clientP12: String = ""
#Value("\${client_p12_password}")
private val clientP12Pass: String = ""
#Bean
fun feignClient(): Client {
val sslSocketFactory= getSSLSocketFactory()
log.info("CUSTOM FEIGN CLIENT CALLED")
return Client.Default(sslSocketFactory, DefaultHostnameVerifier())
}
private fun getSSLSocketFactory(): SSLSocketFactory {
val decoder = java.util.Base64.getDecoder()
val p12 = decoder.decode(clientP12)
val p12File = File("clientCer.p12")
p12File.writeBytes(p12)
try {
val sslContext = SSLContexts
.custom()
.loadKeyMaterial(p12File, clientP12Pass.toCharArray(), clientP12Pass.toCharArray())
.build()
return sslContext.socketFactory
} catch (exception: Exception) {
throw RuntimeException(exception)
}
}
}
The FeignClient interface that is using the configuration has to load this specifically
#FeignClient(name = "client", configuration = [CustomFeignConfiguration::class], url = "\${url}")
interface Client {
....
....
}
The SSLContexts library can only use p12 certificates and we have to convert the certificates and keys in PEM format to the P12 format.
Create a p12 certificate from your PEM certificate and key using the following SSL command:
openssl pkcs12 -export -inkey domain.key -in domain.crt -out domain.p12
Please record the password that you enter after you run this command.
Convert this p12 certificate to a base64 string using the following command
base64 domain.p12 > domain.p12.base64
Convert this multiline string to a single line string using the following command:
tr -d "\n\r" < domain.p12.base64 > domain.p12.base64.singleline
Use the single line string from this command and the password that you recorded earlier in your application.properties.

SSL peer failed hostname validation in Spring SAML

I'm trying to configure my Spring Boot project to use SAML authentication against a third party IDP. I've already achieved to make the configuration from vdenotaris work with the SSOCircle provider and now I want to switch it to the other provider.
The SAML metadata endpoint is HTTPS enabled and I've already created a keystore with both the certificate given in metadata (which is used for signing and encryption) and the one provided by the HTTP endpoint (based in this answer). Then, I save them in a cert file ($CERTIFICATE_FILE) and I use this script to generate my keystore:
keytool -delete -alias third-party -keystore $KEYSTORE_FILE -storepass $KEYSTORE_PASSWORD
keytool -import -alias third-party -file $CERTIFICATE_FILE -keystore $KEYSTORE_FILE -storepass $KEYSTORE_PASSWORD -noprompt
keytool -genkeypair -alias mycompany -keypass mycompanypass -keystore $KEYSTORE_FILE
Then, when using this keystore to retrieve the SAML metadata, I get this error:
org.opensaml.saml2.metadata.provider.MetadataProviderException: org.opensaml.saml2.metadata.provider.MetadataProviderException: Error retrieving metadata from https://third.party.provider/metadata
at org.opensaml.saml2.metadata.provider.HTTPMetadataProvider.fetchMetadata(HTTPMetadataProvider.java:274)
at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.refresh(AbstractReloadingMetadataProvider.java:267)
at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.doInitialization(AbstractReloadingMetadataProvider.java:236)
at org.opensaml.saml2.metadata.provider.AbstractMetadataProvider.initialize(AbstractMetadataProvider.java:407)
at org.springframework.security.saml.metadata.ExtendedMetadataDelegate.initialize(ExtendedMetadataDelegate.java:167)
at org.springframework.security.saml.metadata.MetadataManager.initializeProvider(MetadataManager.java:412)
at org.springframework.security.saml.metadata.MetadataManager.refreshMetadata(MetadataManager.java:238)
at org.springframework.security.saml.metadata.CachingMetadataManager.refreshMetadata(CachingMetadataManager.java:86)
at org.springframework.security.saml.metadata.MetadataManager$RefreshTask.run(MetadataManager.java:1040)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Caused by: org.opensaml.saml2.metadata.provider.MetadataProviderException: Error retrieving metadata from https://third.party.provider/metadata
at org.opensaml.saml2.metadata.provider.HTTPMetadataProvider.fetchMetadata(HTTPMetadataProvider.java:274)
at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.refresh(AbstractReloadingMetadataProvider.java:255)
... 9 common frames omitted
Caused by: javax.net.ssl.SSLPeerUnverifiedException: SSL peer failed hostname validation for name: null
at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.verifyHostname(TLSProtocolSocketFactory.java:233)
at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:186)
at org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:97)
at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1361)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
at org.opensaml.saml2.metadata.provider.HTTPMetadataProvider.fetchMetadata(HTTPMetadataProvider.java:250)
... 10 common frames omitted
These ones are the relevant parts of my configuration based in the linked project by vdenotaris:
// Setup TLS Socket Factory
#Bean
public TLSProtocolConfigurer tlsProtocolConfigurer() {
return new TLSProtocolConfigurer();
}
#Bean
public ProtocolSocketFactory socketFactory() {
return new TLSProtocolSocketFactory(keyManager(), null, "allowAll");
}
#Bean
public Protocol socketFactoryProtocol() {
return new Protocol("https", socketFactory(), 443);
}
#Bean
public MethodInvokingFactoryBean socketFactoryInitialization() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(Protocol.class);
methodInvokingFactoryBean.setTargetMethod("registerProtocol");
Object[] args = { "https", socketFactoryProtocol() };
methodInvokingFactoryBean.setArguments(args);
return methodInvokingFactoryBean;
}
// Central storage of cryptographic keys
#Bean
public KeyManager keyManager() {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource storeFile = loader.getResource("classpath:/saml/mySamlKeystore.jks");
String storePass = "storepass";
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("mycompany", "mycompanypass");
String defaultKey = "mycompany";
return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
}
However, here I found some misconceptions. As far as I know, the TLSProtocolConfigurer creates a TLSProtocolSocketFactory itself, why is the sample project creating both beans then? According to the docs using TLSProtocolConfigurer should be enough, but how to create socketFactoryProtocol()?
I would be grateful to have some light in here.
Here is my JKS key-manager bean configuration.
#Bean
public ProtocolSocketFactory socketFactory() {
return new TLSProtocolSocketFactory(keyManager(), null, "default");
}
#Bean
public KeyManager keyManager() {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource storeFile = loader.getResource("classpath:/saml/samlKeystore.jks");
String storePass = keyStorePwd;
Map<String, String> passwords = new HashMap<String, String>();
passwords.put(keyStoreAlias, keyStorePwd);
String defaultKey = keyStoreAlias;
return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
}
Solution:
Looks like the IDP has changed their Public certificate which is not available in our local keystore (samlKeystore.jks). I manually downloaded their public certificate using OpenSSL command and imported the same using keytool utility.
Get the public certificate using OpenSSL command:
openssl s_client -showcerts -connect iam-sso.google.net:443 </dev/null 2>/dev/null|openssl x509 -outform PEM >mycertfile.pem
Import it into the Keystore:
keytool -import -alias "new-public-cert" -keystore /usr/share/tomcat8/webapps/ROOT/WEB-INF/classes/saml/samlKeystore.jks
I wasn't providing the password for the imported cert file:
#Bean
public KeyManager keyManager() {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource storeFile = loader.getResource("classpath:/saml/mySamlKeystore.jks");
String storePass = "storepass";
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("mycompany", "mycompanypass");
passwords.put("third-party", "mycompanypass");
String defaultKey = "mycompany";
return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
}
With this, the application can read the certs from the keystore and trust them, without the need of installing them in the JDK cacerts.
#Bean
#Qualifier("idp-ssocircle")
public ExtendedMetadataDelegate ssoCircleExtendedMetadataProvider()
throws MetadataProviderException {
String idpSSOCircleMetadataURL = "https://idp.ssocircle.com/idp-meta.xml";
HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider(
this.backgroundTaskTimer, httpClient(), idpSSOCircleMetadataURL);
httpMetadataProvider.setParserPool(parserPool());
ExtendedMetadataDelegate extendedMetadataDelegate =
new ExtendedMetadataDelegate(httpMetadataProvider, extendedMetadata());
extendedMetadataDelegate.setMetadataTrustCheck(false);
extendedMetadataDelegate.setMetadataRequireSignature(false);
backgroundTaskTimer.purge();
return extendedMetadataDelegate;
}
extendedMetadataDelegate.setMetadataTrustCheck(false);
Just remove TLSProtocolConfigurer bean and set metadata trust check to false

Resources