Вызвано: javax.net.ssl.SSLHandshakeException: Не удалось построить путь PKIX, не удалось найти допустимый путь сертификации к запрошенной цели

#java #spring #ssl #keystore

Вопрос:

Я пытаюсь вызвать службу https, размещенную в другом домене, для вызова которого требуется прокси-сервер, мне удалось загрузить сертификат в .pem формате из браузера и добавить его в свою JVM с помощью keytool, но теперь я пытаюсь добавить его в свой keystore при создании своего restTemplate объекта, но когда я пытаюсь это сделать, я все еще получаю:

 Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed unable to find valid certification path to requested target 
 

вот что я попробовал:

 @Configuration
@Slf4j
public class RestTemplateFactory {
    
    @Value("${certificate.name}")
    private String name;

    @Value("${PROXY_SERVER_HOST}")
    private String proxyServerHost;

    @Value("${PROXY_SERVER_PORT}")
    private Integer proxyServerPort;

    @Value("${NEED_PROXY}")
    private boolean isNeedProxy;

    @Value("${DOS_BASIC_AUTH_USERNAME}")
    private String basicAuthDosUsername;

    @Value("${DOS_BASIC_AUTH_PASSWORD}")
    private String basicAuthDosPassword;


    @Bean
    public RestTemplate restTemplate() throws Exception {
        return new RestTemplate(httpClientRequestFactory());
    }

    @Bean(name = "sslContext")
    public SSLContext sslContext() throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        return SSLContexts.custom()
                .loadTrustMaterial(null, new TrustSelfSignedStrategy())
                .useProtocol("TLS")
                .build();

    }

    @Bean(name = "sslSocketFactory")
    public SSLSocketFactory sslSocketFactory() throws Exception {
        log.debug("Configure CERTIFICATE NAME:----> "   name);
        return new ConnectionFactoryCreator(name, sslContext()).getSocketFactory();
    }

    @Bean(name = "httpClient")
    public CloseableHttpClient httpClient() throws Exception {
        HttpHost proxy = new HttpHost(proxyServerHost, proxyServerPort);
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
                new UsernamePasswordCredentials(basicAuthDosUsername, basicAuthDosPassword));
        return HttpClientBuilder.create().setSslcontext(sslContext())
                .setSSLSocketFactory(new SSLConnectionSocketFactory(sslSocketFactory(), new AllowAllHostnameVerifier()))
                .setProxy(isNeedProxy ? proxy : null)
                .setDefaultCredentialsProvider(credentialsProvider)
                .build();
    }


    @Bean
    public ClientHttpRequestFactory httpClientRequestFactory() throws Exception {
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }

}
 

И

 @Slf4j
public class ConnectionFactoryCreator {

    private String pemName;
    private SSLContext context;

    public ConnectionFactoryCreator(String pemName, SSLContext context) {
        this.pemName = pemName;
        this.context = context;
    }

    public SSLSocketFactory getSocketFactory() throws Exception {
        log.debug("PEM CERTIFICATE NAME:----> "   pemName);
        InputStream resourceAsStream = getClass().getResourceAsStream("/keystore/"   pemName);
        byte[] certAndKey = IOUtils.toByteArray(resourceAsStream);
        byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");

        X509Certificate cert = generateCertificateFromDER(certBytes);
        KeyStore keystore = KeyStore.getInstance("JKS");
        keystore.load(null);
        keystore.setCertificateEntry("cert-alias", cert);
        //keystore.setKeyEntry("key-alias", key, "changeit".toCharArray(), new Certificate[] { cert });
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(keystore, "changeit".toCharArray());
        KeyManager[] km = kmf.getKeyManagers();
        context.init(km, null, null);
        return context.getSocketFactory();
    }

    private byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
        String data = new String(pem);
        String[] tokens = data.split(beginDelimiter);
        tokens = tokens[1].split(endDelimiter);
        return DatatypeConverter.parseBase64Binary(tokens[0]);
    }

    private X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException, CertificateException {
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
    }
}
 

Файл YAML:

 certificate :
  name : certificate.pem
 

и файл pem добавляется в /resources/keystore/certificate.pem

Комментарии:

1. пожалуйста, обратите внимание, что сертификат авторизован Amazon