11

i am trying to get issue details from jira server using my username and password but i am getting an ssl error saying unable to validate certificate

so how to validate certificate

url: http:local/8080/frr/hello

Getting error:

nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for

"https://jira.example.com/rest/api/2/issue/id":

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] with root cause sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

my Service.class code

@Controller
public class Service{


    @RequestMapping("/hello")


     public String Data(ModelMap model){

        RestTemplate restTemplate = new RestTemplate();

        ResponseEntity<String> result = restTemplate.exchange("https://jira.example.com/rest/api/2/issue/id",  HttpMethod.GET, new HttpEntity<String>(createHeaders("username", "password")), String.class);

        model.addAttribute("message", result);


        return "helloworld";
    }

    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders createHeaders( String username, String password ){
        HttpHeaders header =  new HttpHeaders();
        String auth = username + ":" + password;
        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")) );
        String base64Creds = "Basic " + new String( encodedAuth );
        header.add("Authorization", "Basic " + base64Creds);
        return header;
    }   
}
TFrost
  • 769
  • 2
  • 12
  • 31
Labeo
  • 5,831
  • 13
  • 47
  • 77

4 Answers4

21

The problem you are facing is that your application cannot validate the external server you are trying to connect to as its certificate is not trusted.

What happening in short is:

  • your application tries to connect to the a Jira instance over a secure (HTTPS) channel
  • to establish the secure connection the application downloads the certificate
  • the application checks the validity of the certificate by trying to trace it back to a known CA (kept in the JRE cert-store)
  • certificate check fails because the cert is self-signed (most likely) or expired, etc.

If this Jira instance is on-premise (hosted by your company) then having a self-signed certificate is not at all unlikely. In this case the certificate is not issued by a known CA, so if you wish to trust it, you need to manually register it.

First obtain the certificate:

openssl s_client -connect jira.example.com:443 < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt

Then import it into your own keystore:

$JAVA_HOME/keytool -import -alias <server_name> -keystore $JAVA_HOME/lib/security/cacerts -file public.crt

Note: the commands above are for Unix environment. Under Windows I would suggest using similarly openssl from command line, but there are also GUI tools available for the same purpose.

Gergely Bacso
  • 14,243
  • 2
  • 44
  • 64
  • after getting certificate how to use it to validate the server certificate – Labeo Aug 17 '15 at 16:09
  • After you got the cert file, you just need to import it into the keystore which is being used by your application. Find the Java installation you use, then go to: JAVA_DIR/lib/security/cacerts . – Gergely Bacso Aug 17 '15 at 17:40
  • i have included the certificate and tried to authenticate but i am not able to authenticate getting 401 status see http://stackoverflow.com/questions/32064672/unable-to-authenticate-server-even-after-including-keystore-certificate-in-sprin – Labeo Aug 18 '15 at 06:28
  • Status 401 is a different problem. Getting that means that your app-level authentication has failed,but it also means that the HTTPS handshake was successful, so the problem in this particular post is solved. – Gergely Bacso Aug 18 '15 at 07:58
  • Yeah i know i am asking if you can solve that problem – Labeo Aug 18 '15 at 08:16
  • @GergelyBacso The character " is to spare – joninx Jan 26 '17 at 11:51
  • 1
    Remember that default password for the keystore is: changeit – Diego Palomar May 31 '17 at 16:45
  • 1
    Since the program ```keytool``` usually is in the ```bin``` folder and ```$JAVA_HOME``` usually points to the folder one level above, the call should be ```$JAVA_HOME/bin/keytool [...]```. Also note that the command may need to be executed as root. – SaschaH Jun 03 '19 at 15:37
2

If you are still facing issues with certificates even after importing the certificate as indicated by @Gergely Bacso then make sure that the java.exe or javaw.exe binaries you have linked to your IDE or in your command line used to run your Java application are those from JRE not the JDK, I got certificate errors even after installing the certificate in cacerts keystore until I realised the binaries I was using were from the JDK. After I switched path to JRE everything went as expected and I was able to connect successfully. I hope it saves someone's time trying to debug the problem.

AguThadeus
  • 310
  • 2
  • 10
0

Check if the file $JAVA_HOME/lib/security/cacerts exists! In my case it was not a file but a link to /etc/ssl/certs/java/cacerts and also this was a link to itself (WHAT???) so due to it JVM can't find the file.

Solution: Copy the real cacerts file (I did it from another JDK) to /etc/ssl/certs/java/ directory and it'll solve your problem :)

0x7E1
  • 41
  • 1
  • 5
-6

You can Replace

String base64Creds = "Basic " + new String( encodedAuth );

with

String base64Creds = new String( encodedAuth ); //"Basic " String duplicated
melwil
  • 2,547
  • 1
  • 19
  • 34