DEV-NOTES|Gradle: Use gradle wrapper with self-signed / organization local certificates

Automated provisioning of the required build environment is one of the great promises by gradle. Using gradle wrapper allows the rapid workspace setup for a new developer or on a new machine.

In organizations there are sometimes restrictions in accessing public networks and it local hosting becomes inevitable. The actual example is based on the idea hosting the gradle distribution inside the local document management system which is accessible using https only.

# gradle-wrapper.properties
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

distributionUrl=https://provisioning-url/gradle-2.2-bin.zip

Unfortunately the server identity is assured by a self-signed resp. signed by a local authority certificate. Running the gradle wrapper screws up yielding the following exception:

<br />> gradlew tasks
Downloading https://provisioning-url/gradle-2.2-bin.zip

Exception in thread "main" java.lang.RuntimeException: 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
        at org.gradle.wrapper.ExclusiveFileAccessManager.access(ExclusiveFileAccessManager.java:78)
        at org.gradle.wrapper.Install.createDist(Install.java:44)
        at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:126)
        at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:58)
Caused by: 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
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1341)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java
:185)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1300)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
        at org.gradle.wrapper.Download.downloadInternal(Download.java:56)
        at org.gradle.wrapper.Download.download(Download.java:42)
        at org.gradle.wrapper.Install$1.call(Install.java:57)
        at org.gradle.wrapper.Install$1.call(Install.java:44)
        at org.gradle.wrapper.ExclusiveFileAccessManager.access(ExclusiveFileAccessManager.java:65)
        ... 3 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
        at sun.security.validator.Validator.validate(Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1323)
        ... 19 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
        ... 25 more

The problem is that the HTTPS connection could not be validated because there is no trusted certificate for the provisioning url available.

The solution is to enhance the truststore with the certificate or the authority used in the provisioning url:

#create or copy an existing truststore eq. form jdk
> cp $JAVA_HOME/jre/lib/security/cacerts certs.jks
# import your certifiact into certs.jks
> keytool -importcert -file self-signed.pem -keystore certs.jks

and tell gradlew to use this truststore instead of the original one. Gradles behavior can be adjusted by modifying the gradle.properties file in the root directory of your gradle project (for more information see „The Build Environment“ from the user guide).

# gradle.properties
systemProp.javax.net.ssl.trustStore=certs.jks
# could set password as well
# javax.net.ssl.trustStorePassword=changeit

Calling gradlew again should kick off downloading the gradle distribution and running your tasks like a charm.


Update 27/10/2016

Changed password property to match the truststore. Thanks to Thomas for his advice.

3 Gedanken zu „DEV-NOTES|Gradle: Use gradle wrapper with self-signed / organization local certificates“

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

11 + 15 =