Using Gradle wrapper behind a proxy server with self-signed SSL certificates

Today, I wanted to add a Gradle Wrapper to my Java project but had a few issues. I am behind a proxy and it changes the SSL certificates to be able to scan traffic for viruses.

My first attempt to start gradlew build resulted in:

    Exception in thread "main" java.net.UnknownHostException: services.gradle.org
            at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
            at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
            at java.net.Socket.connect(Socket.java:589)
            at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:668)
            at sun.security.ssl.BaseSSLSocketImpl.connect(BaseSSLSocketImpl.java:173)
            ...

Gradle didn’t use the proxy server and tried to connect to the internet directly. This was solved by setting the proxy server in %GRADLE_USER_HOME%\gradle.properties (see Gradlew behind a proxy):

    systemProp.http.proxyHost=192.168.1.1
    systemProp.http.proxyPort=80
    systemProp.http.proxyUser=userid
    systemProp.http.proxyPassword=password
    systemProp.https.proxyHost=192.168.1.1
    systemProp.https.proxyPort=80
    systemProp.https.proxyUser=userid
    systemProp.https.proxyPassword=password

The next try lead to:

    Downloading https://services.gradle.org/distributions/gradle-2.11-bin.zip

    Exception in thread "main" 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:1949)
            at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
            at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
            at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
            ....

The reason for the SSLHandshakeException were the proxy’s selft-signed certificates, that could not be validated. I had to add them to the Java keystore (see Java: Ignore/Trust an invalid SSL cert for https communication and Cacerts default password? -> the default password for the Java keystore is changeit):

    "%JAVA_HOME%\bin\keytool" -import -trustcacerts -alias MY_ALIAS -file MY_CERT.crt -keystore "%JAVA_HOME%\jre\lib\security\cacerts"

Now, Gradle was able to connect to gradle.org to download the distribution. However, the proxy server would not let the ZIP file through:

    Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: https://downloads.gradle.org/distributions/gradle-2.11-bin.zip
            at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1840)
            at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
            at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
            ...

So I configured Gradle to “download” the ZIP file from the local hard drive in %GRADLE_USER_HOME%\gradle.properties (see How to use gradle zip in local system without downloading when using gradle-wrapper):

    distributionBase=GRADLE_USER_HOME
    distributionPath=wrapper/dists
    zipStoreBase=GRADLE_USER_HOME
    zipStorePath=wrapper/dists
    distributionUrl=gradle-2.11-bin.zip

I manually downloaded the distribution file and put it into %GRADLE_USER_HOME%\wrapper\dists\gradle-2.11-bin\[SOME_HASH]\.

And finally the build was successful! 😀

    D:\MY_PROJECT>gradlew build
    Unzipping D:\GradleUserHome\wrapper\dists\gradle-2.11-bin\452syho4l32rlk2s8ivdjogs8\gradle-2.11-bin.zip to D:\GradleUserHome\wrapper\dists\gradle-2.11-bin\452syho4l32rlk2s8ivdjogs8
    Starting a new Gradle Daemon for this build (subsequent builds will be faster).
    Parallel execution with configuration on demand is an incubating feature.
    :compileJava UP-TO-DATE
    ...