spring-bootsslspring-securityspring-security-rest

Spring boot using https only - Test failing


I have spring boot - angular application

My server port is 1234 (example).

But now I have setup ssl

Steps:

created self signed cert using keytool and added my p12 cert file into resources folder

updated application.properties

server.ssl.key-store-type=PKCS12

server.ssl.key-store=classpath:myfile.p12

server.ssl.key-store-password=somepasswordfromenv

server.ssl.key-alias=myalias

server.ssl.enabled=true

http.port=8080

server.port=8443

Started app and tested

@SpringBootTest(classes = AppWithoutBeansApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
class AppControllerTest {

    @Value("${server.ssl.key-store}")
    private Resource trustStore;

    @Value("${server.ssl.key-store-password}")
    private String trustStorePassword;

@Test
public void givenAcceptingAllCertificatesUsing4_4_whenUsingRestTemplate_thenCorrect() 
throws ClientProtocolException, IOException {
    
    String urlOverHttps = "https://localhost:8443/";
    CloseableHttpClient httpClient
      = HttpClients.custom()
        .setSSLHostnameVerifier(new NoopHostnameVerifier())
        .build();
    HttpComponentsClientHttpRequestFactory requestFactory 
      = new HttpComponentsClientHttpRequestFactory();
    requestFactory.setHttpClient(httpClient);

    ResponseEntity<String> response 
      = new RestTemplate(requestFactory).exchange(
      urlOverHttps, HttpMethod.GET, null, String.class);
    assertThat(response.getStatusCode().value(), equalTo(200));
}   

...

Error:

org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://localhost:8443/": Certificate for doesn't match any of the subject alternative names: []; nested exception is javax.net.ssl.SSLPeerUnverifiedException: Certificate for doesn't match any of the subject alternative names: [] at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:746)

Don't understand how my integration test works


Solution

  • All answers looked similar, but this one worked

    Ignore SSL certificate validation when using Spring RestTemplate

    @Bean
    public RestTemplate restTemplate() throws GeneralSecurityException {
    
        TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", sslsf).register("http", new PlainConnectionSocketFactory()).build();
    
        BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager(
                socketFactoryRegistry);
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
                .setConnectionManager(connectionManager).build();
    
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
    
        RestTemplate restTemplate = new RestTemplate(requestFactory);
    
        return restTemplate;
    }
    

    Looks like this part made the difference

     *Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("https", sslsf).register("http", new PlainConnectionSocketFactory()).build();*
    

    DO NOT USE THIS

    //  @Bean
    //    public RestTemplate nonsslrestTemplate() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
    //         TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
    //         SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
    //         SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
    //         CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
    //         HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
    //         requestFactory.setHttpClient(httpClient);
    //       return new RestTemplate(requestFactory);
    //    }