0

I'm fairly new to Groovy & SoapUING. I hope someone can help me figure out and fix this error. Thanks!

What I'm trying to do: Iterate through each db row item in a table and use that as input to make a HTTPBuilder request (GET or POST) either as a query in path (add baseURL/path/hello) or through parameters(add baseURL/path?searchNode="hello"). The baseURL is something like this https://search-test-env.ser.com.

Where I'm getting stuck: When I try to post a request through HTTPBuilder.

Error: PKIX Path Building Failed

Other related information:

  • Using ReadyAPI to run the scripts. Code is in Groovy.
  • Recently imported the httpbuilder jar into ReadyAPI/lib folder along with some dependencies. Of the dependencies available with httpbuilder, ReadyAPI already had few so I only picked up the ones missing. Additional jar names: ojdbc6, ojdbc6_g, signpost-commonshttp4-1.2.1.1, ezmorph-1.0.6, json-lib-2.3-jdk15, xml-resolver-1.2, signpost-core-1.2.1.1, appengine-api-1.0-sdk-1.3.8, nekohtml-1.9.16, http-builder-0.7, http-builder-0.7-sources, http-builder-0.7-javadoc.
  • The Service works with a manual request without groovy (simple GET on the baseURL/path) and it also works with query by string or by parameter.
  • The certificate is already available in the Keystore. Tried using keytool (available in ReadyAPI/bin folder) command through cmd but receiving a filenotfound error). Tried to import into the ReadyAPI\jre\lib\security.

Code:

    def qryPrmRqstHTTPBldr( pBaseUrl, pPath, pQuery, pMethod ) {
    def ret = null
    def http = new HTTPBuilder()
    def meth

    if ( pMethod == 'GET') {
            meth = Method.GET
    }
    else if ( pMethod == 'POST') {
            meth = Method.POST
    }
    // perform a GET/POST request, expecting TEXT response
    http.request(pBaseUrl, meth, ContentType.TEXT) { req ->
        uri.path = pPath
        uri.query = pQuery
        /*
        headers.'User-Agent'         = 'Apache-HttpClient/4.5.1 (Java/1.8.0_66)'
        headers.'Host'               = 'xxx-xx-xxx.xxx.xxx'
        headers.'Accept-Encoding'    = 'gzip,deflate'
        headers.'Connection'         = 'Keep-Alive'
        */
        log.info System.getProperty("java.runtime.version")
        log.info System.getProperty("javax.net.ssl.trustStore")
        log.info System.getProperty("javax.net.ssl.keyStore")
        log.info System.getProperty("java.home")
        log.info System.getProperty("java.class.path")        

        // response handler for a success response code
        response.success = { resp, reader ->
                println "response status: ${resp.statusLine}"
                println 'Headers: -----------'

                ret = reader.getText()

                println 'Response data: -----'
                println ret
                println '--------------------'
            }
    }
      return ret
}

Running this code throws the PKIX Path Building Failed error (no stack trace available) and the content for each property:

System.getProperty("java.runtime.version") // 1.8.0_66-b17
System.getProperty("javax.net.ssl.trustStore") // null
System.getProperty("javax.net.ssl.keyStore") // null
System.getProperty("java.home") // c:\program files\smartbear\readyapi-1.6.0\jre 
System.getProperty("java.class.path") // C:\Program Files\SmartBear\ReadyAPI-1.6.0\.install4j\i4jruntime.jar;......
albciff
  • 18,112
  • 4
  • 64
  • 89
ssc
  • 35
  • 2
  • 9

1 Answers1

0

The problem

PKIX path building failed error is thrown when your client can not construct a trust path to your server certificate. This basically means that in your trust store there isn't the certificate authority which issues the end entity certificate or a intermediate certificate for your server certificate; and it's needed to build the certificate chain.

In your case javax.net.ssl.trustStore it's not defined, due System.getProperty("javax.net.ssl.trustStore") is null; so from JSSE

  1. If the system property: javax.net.ssl.trustStore is defined, then the TrustManagerFactory attempts to find a file using the filename specified by that system property, and uses that file for the KeyStore. If the javax.net.ssl.trustStorePassword system property is also defined, its value is used to check the integrity of the data in the truststore before opening it. If javax.net.ssl.trustStore is defined but the specified file does not exist, then a default TrustManager using an empty keystore is created.

  2. If the javax.net.ssl.trustStore system property was not specified, then if the file <java-home>/lib/security/jssecacerts exists, that file is used. (See The Installation Directory for information about what refers to.)

  3. Otherwise, If the file <java-home>/lib/security/cacerts exists, that file is used.

The solution

Then to solve the problem you need to add the required certificates to JRE_HOME/lib/security/jssecacerts if exists or to JRE_HOME/lib/security/cacerts if not from the Java which are you using to run the Groovy scripts.

The correct way: Add the certificate authority of your server certificate in the trust store. Then make sure that your server correctly serves all certificate chain until CA: intermediate certificates (if needed) until the end entity server certificate.

The brute force way: If you've some problems setting up the trust store or you're not sure if the server is pushing the chain certificates... simply put directly the server certificate in the trust store. This is not the "purist" way but since you're only testing this will works.

How to do it

Download the CA server certificate and load it to the trust store using keytool with the follow command (the default password for cacerts is changeit):

keytool -import -alias <someAlias> -file <certificatePath> -keystore <trustStorePath>

Here there is one of my answers with a bit more detail about how to load the certificate.

Community
  • 1
  • 1
albciff
  • 18,112
  • 4
  • 64
  • 89
  • Thank you very much for explaining why this issue is caused. Coming to solution - Being a novice, I have no idea how to implement this. Been using `keytool` utility but it's throwing `filenotfound` error. Also, the response is as expected when request is made manually... It's directly taking the certificate from the url and producing the response, I believe. Coming to the keystores. In both `C:\Program Files (x86)\Java\jre1.8.0_66\lib\security` & `C:\Program Files\SmartBear\ReadyAPI-1.6.0\jre\lib\security` there is no `jssecerts` file only the `cacerts` file. – ssc Oct 25 '16 at 17:51
  • @ssc I add more detail about keytool, hope this helps :). – albciff Oct 26 '16 at 07:05
  • Thank you! I have been trying to do the exact same thing and it's throwing filenotfound error. – ssc Oct 26 '16 at 12:18
  • @ssc probably the problem is due to access denied on the file, try to run the cmd in admin mode, and then run the keytool command. – albciff Oct 26 '16 at 13:57
  • Yes, tried the admin mode. Didn't work. Looking through the link your referred, someone mentioned windows defender or firewall issue but I'm guessing that is not an issue in this case. Any leads would be very helpful. I also tried loading certificate through the tool `(WS-Security)` but it's not working either. The password is correct since I was able to pull the `cacerts` file through the tool with that password & list it in the cmd as well. – ssc Oct 26 '16 at 18:33
  • @ssc can you share the complete error and the complete keytool command? – albciff Oct 26 '16 at 20:18
  • Sorry for the delayed response, I was caught up with something. I have added my edits to the question. On a different note, In light of this issue, I have changed my whole automation framework since I was not able to go anywhere forward without being able to actually implement a httprequest. For now it is working out ok to do the work through the tool features. But my first choice would always be to do it through the script/code as I can always transfer and use it on another tool. – ssc Oct 28 '16 at 14:54