jrhorrocks
jrhorrocks

Reputation: 33

grails - RestClientBuilder

I am using the current version of rest client builder plugin. I tested out the uri via curl:

curl --user username:password https://localhost:8085/rest/api/latest/plan.json?os_authType=basic

I get the expected json in return. When I try to translate this to grails using the plugin like this:

RestBuilder rb = new RestBuilder()
    def response = rb.get("https://localhost:8085/rest/api/latest/plan.json?os_authType=basic"){     
            auth 'username', 'password'
        }

response.json instanceof JSONObject

I get this error:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Why does it work in curl and not with the plugin? How do I get this to work?

Thanks!

Upvotes: 3

Views: 1528

Answers (3)

Pedro Lobito
Pedro Lobito

Reputation: 98921

You need to add the root certificate to the store of the trusted ones.

http://docs.oracle.com/javase/tutorial/security/toolsign/rstep2.html


Import the Certificate as a Trusted Certificate

Before you can grant the signed code permission to read a specified file, you need to import Susan's certificate as a trusted certificate in your keystore.

Suppose that you have received from Susan

  • the signed JAR file sCount.jar, which contains the Count.class file, and
  • the file Example.cer, which contains the public key certificate for the public key corresponding to the private key used to sign the JAR file.

Even though you created these files and they haven't actually been transported anywhere, you can simulate being someone other than the creater and sender, Susan. Pretend that you are now Ray. Acting as Ray, you will create a keystore named exampleraystore and will use it to import the certificate into an entry with an alias of susan.

A keystore is created whenever you use a keytool command specifying a keystore that doesn't yet exist. Thus we can create the exampleraystore and import the certificate via a single keytool command. Do the following in your command window.

  1. Go to the directory containing the public key certificate file Example.cer. (You should actually already be there, since this lesson assumes that you stay in a single directory throughout.)
  2. Type the following command on one line:

    keytool -import -alias susan -file Example.cer -keystore exampleraystore

Since the keystore doesn't yet exist, it will be created, and you will be prompted for a keystore password; type whatever password you want.

The keytool command will print out the certificate information and ask you to verify it, for example, by comparing the displayed certificate fingerprints with those obtained from another (trusted) source of information. (Each fingerprint is a relatively short number that uniquely and reliably identifies the certificate.) For example, in the real world you might call up Susan and ask her what the fingerprints should be. She can get the fingerprints of the Example.cer file she created by executing the command

keytool -printcert -file Example.cer

If the fingerprints she sees are the same as the ones reported to you by keytool, the certificate has not been modified in transit. In that case you let keytool proceed with placing a trusted certificate entry in the keystore. The entry contains the public key certificate data from the file Example.cer and is assigned the alias susan.

Upvotes: 1

Vadim
Vadim

Reputation: 1131

Mb too late but have a look here. https://gist.github.com/thomastaylor312/80fcb016020e4115aa64320b98fb0017

I do have it as separate method in my Integration test

 def static disableSSLCheck() {
    def nullTrustManager = [
            checkClientTrusted: { chain, authType -> },
            checkServerTrusted: { chain, authType -> },
            getAcceptedIssuers: { null }
    ]

    def nullHostnameVerifier = [
            verify: { hostname, session -> true }
    ]

    SSLContext sc = SSLContext.getInstance("SSL")
    sc.init(null, [nullTrustManager as X509TrustManager] as TrustManager[], null)
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory())
    HttpsURLConnection.setDefaultHostnameVerifier(nullHostnameVerifier as HostnameVerifier)
}

And then just

void "test authentication"(){
    given:
    String url = "j_spring_security_check"
    MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>()
    form.add("grant_type", "password")
    form.add("j_username", "[email protected]")
    form.add("j_password", "notSecure")
    form.add("_spring_security_remember_me", "true")
    //TODO SET username and pass
    //todo get token back
    disableSSLCheck()
    when:
    RestResponse response = rest.post(host + url){
        accept("application/json")
        contentType("application/x-www-form-urlencoded")
        body(form)
    }
    response
    then:
    response.status == 200
}

Upvotes: 0

Yaroslav
Yaroslav

Reputation: 466

You can just disable SSL check for RestBuilder.

See an example of code:

static Scheme disableSSLCheck() {

        def sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, [new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] certs, String authType) {}

            public void checkServerTrusted(X509Certificate[] certs, String authType) {}

            @Override
            X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0]
            }
        }] as TrustManager[], new SecureRandom())
        def sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
        def httpsScheme = new Scheme("https", sf, 443)
        httpsScheme

    }

And register this Scheme to the RestClient:

Scheme httpsScheme = disableSSLCheck()
restClient.client.connectionManager.schemeRegistry.register(httpsScheme)

Upvotes: 0

Related Questions