0

So I'm able to disable the SBA Admin server from validating SSL certs from the clients it tries to connect to - for SBA version 2.6.2 it is more or less outlined right from their documentation: https://codecentric.github.io/spring-boot-admin/current/#_using_mutual_tls

Here is the complete configuration overriding bean:

package com.markham.mkmappadmin.config;

import javax.net.ssl.SSLException;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;

import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import reactor.netty.http.client.HttpClient;

/**
 * Custom http client class which overrides Spring Boot Admin's server default client.<br>
 * The custom client will bypass any SSL Validation by configuring an instance of
 *  {@link InsecureTrustManagerFactory}
 * @author Hanif Rajabali
 * @see <a href="https://codecentric.github.io/spring-boot-admin/current/#_using_mutual_tls">Spring Boot Admin 2.6.2 Using Mutual TLS</a>
 */
@Configuration
public class CustomHttpClientConfig {

    @Bean
    public ClientHttpConnector customHttpClient() throws SSLException {
        SslContext sslContext = SslContextBuilder
              .forClient()
              .trustManager(InsecureTrustManagerFactory.INSTANCE)
              .build();
        HttpClient httpClient = HttpClient.create().secure(
            ssl -> ssl.sslContext(sslContext)
        );
        return new ReactorClientHttpConnector(httpClient);
    }

}

What I still haven't figured out is how to disable it from the SBA client. I have a custom RestTemplate Config defined below, but the SBA client doesn't seem to be picking it up even though I see that the SBA client code is using the BlockingRegistrationClient i.e) RestTemplate

package com.markham.mkmemailerws.config;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

/**
 * Need to explicitly build Spring Boot's auto configured
 * {@link #restTemplate(RestTemplateBuilder)}
 *
 * @author Hanif Rajabali
 *
 */
@Configuration
public class RestTemplateConfig {

//   @Bean
//   public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
//      return restTemplateBuilder.build();
//   }


    /**
     * The following will bypass ssl validation altogether. Not ideal.
     */
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder)
            throws NoSuchAlgorithmException, KeyManagementException {

        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
            }

            public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
            }
        } };
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext)
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
        HttpComponentsClientHttpRequestFactory customRequestFactory = new HttpComponentsClientHttpRequestFactory();
        customRequestFactory.setHttpClient(httpClient);
        return builder.requestFactory(() -> customRequestFactory).build();
    }
}
ustad
  • 459
  • 1
  • 6
  • 21
  • check if this helps: https://stackoverflow.com/questions/30770280/spring-boot-ssl-client and https://www.baeldung.com/httpclient-ssl – pringi Mar 07 '22 at 15:19
  • Are you sure your SBA client is using this rest template ? Could you share the code where you make the call ? – sixrandanes Mar 09 '22 at 01:56
  • Thanks @sixrandanes.. I don't make any calls from the client to the admin server.. the sba client does it automatically. I just expose the actuator endpoints in the client and have the following config values: # Admin Server to register with spring.boot.admin.client.url=http://localhost:8446 # This client instance spring.boot.admin.client.instance.service-base-url=https://localhost:8444 My rest template override is above but the SBA client code is not using it.... TIA! – ustad Mar 09 '22 at 02:10
  • Maybe you should override the Webclient onstead of resttemplate cause the version of spring-boot you use should be based on webClient. – sixrandanes Mar 09 '22 at 02:24
  • Thanks again @sixrandanes I'm pretty sure its using a BlockingRegistrationClient as opposed to a reactive one when I traced it through. In any event, my code for the CustomHttpClientConfig above which I obtained from their docs doesn't work in the client side. The io.netty.* imports do not resolve. I'm using SB 2.6.4. If the SBA folks could only post the code for client side as they have done for the admin server side.... would you happen to know how to override the webclient on the SBA client side? I think it is using 'InstanceWebClient' as a wrapper... – ustad Mar 09 '22 at 04:44
  • Have you aleeady checked this thread ? https://stackoverflow.com/questions/50320573/how-avoid-the-certificate-validation-in-spring-boot-admin/55258603#55258603 – sixrandanes Mar 09 '22 at 06:27
  • Hey @sixrandanes, I have - you can see my comments to it as well. Problem is the io.netty.* imports do not resolve for me.. – ustad Mar 09 '22 at 15:37

1 Answers1

0

In our case (Spring Boot Admin 2.7.10) the first issue was, that the configuration class was not picked up, if you start SBA with the Template that is given in the default docs. Add a @ComponentScan Annotation and the config will be used.

@Configuration
@EnableAutoConfiguration
@EnableAdminServer
public class SpringBootAdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootAdminApplication.class, args);
    }
}

Then the customHttpClient bean in your question works as expected. If you do not want to invalidate the whole certificate checking process but just the Subject Alternative Name check, because you are using IPs instead of hostnames for SBA, you can use the following, to do so.

    @Bean
    public ClientHttpConnector customHttpClient() throws SSLException {

        SslContext sslContext = SslContextBuilder.forClient()
                .build();

        var httpClient = reactor.netty.http.client.HttpClient.create().secure(
                ssl -> ssl.sslContext(sslContext)
                        .handlerConfigurator(sslHandler -> {
                            SSLEngine engine = sslHandler.engine();
                            SSLParameters params = new SSLParameters();
                            params.setEndpointIdentificationAlgorithm("");
                            engine.setSSLParameters(params);
                        }));
        return new ReactorClientHttpConnector(httpClient);
    }
}

In our case, it was important to use setEndpointIdentificationAlgorithm(""); here, because if we used null, another Algorithm was actually set up internally.