1
votes

I am trying to consume a Rest API using Groovy and here it is the code I am using :

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
    
        CloseableHttpClient client = HttpClients.createDefault();
        HttpResponse response = null;

        HttpPost request = new HttpPost("http://path_to_my_server/rest_api_path");
        String auth = "login:password";
        String encoding = auth.bytes.encodeBase64().toString()
        request.setHeader("Authorization", "Basic " + encoding);
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.addPart("postVar",  new StringBody("value",ContentType.MULTIPART_FORM_DATA));
        HttpEntity entity = builder.build();
        request.setEntity(entity);
        response = client.execute(request);

the problem is that every time I execute it, it shows me an error :

error javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I did some reaserch and I tested some Codes like :

https://gist.github.com/barata0/63705c0bcdd1054af2405e90c06f6b71

https://github.com/jgritman/httpbuilder/wiki/SSL

How to use SSL with a self-signed certificate in groovy?

All of those did not work , any help please?

1

1 Answers

1
votes

Although I am not recommending this option as you should not ignore ssl verification. The better approach would be creating a truststore.jks containing the trusted certificates and loading it into your http client.

However it is possible what you are trying to do. What you can do is similar to this answer here: Disabling SSL verification for Elastic search Restclient not working in Java

I would advise to use the X509ExtenderTrustManager instead of the X509TrustManager as it might behave differently in these kind of use cases.

Can you try the following snippet:

Create a custom TrustManager

import javax.net.ssl.SSLEngine;
import javax.net.ssl.X509ExtendedTrustManager;
import java.net.Socket;
import java.security.cert.X509Certificate;

public final class UnsafeX509ExtendedTrustManager extends X509ExtendedTrustManager {

    private static final X509ExtendedTrustManager INSTANCE = new UnsafeX509ExtendedTrustManager();
    private static final X509Certificate[] EMPTY_CERTIFICATES = new X509Certificate[0];

    private UnsafeX509ExtendedTrustManager() {}

    public static X509ExtendedTrustManager getInstance() {
        return INSTANCE;
    }

    @Override
    public void checkClientTrusted(X509Certificate[] certificates, String authType) {}

    @Override
    public void checkClientTrusted(X509Certificate[] certificates, String authType, Socket socket) {}

    @Override
    public void checkClientTrusted(X509Certificate[] certificates, String authType, SSLEngine sslEngine) {}

    @Override
    public void checkServerTrusted(X509Certificate[] certificates, String authType) {}

    @Override
    public void checkServerTrusted(X509Certificate[] certificates, String authType, Socket socket) {}

    @Override
    public void checkServerTrusted(X509Certificate[] certificates, String authType, SSLEngine sslEngine) {}

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return EMPTY_CERTIFICATES;
    }

}

Apply it to your Http Client

HostnameVerifier hostnameVerifier = (host, sslSession) -> true;
TrustManager[] trustManagers = new TrustManager[]{UnsafeX509ExtendedTrustManager.getInstance()};

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, null);

LayeredConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
CloseableHttpClient httpClient = HttpClients.custom()
        .setSSLSocketFactory(socketFactory)
        .build();

See my reference to the other stackoverflow for more detailed explanation here: https://stackoverflow.com/a/64982379/6777695