본문 바로가기

트러블슈팅

JAVA SSL 인증서 문제 - PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException

문제

Postman에서는 문제 없이 호출되었던 URL이, 자바에서 FeignClient를 이용해 호출하려고 하니 아래와 같이 javax.net.ssl.SSLHandshakeException 등으로 인한 feign.RetryableException이 났다.

SSL이 있어서 인증서 문제라고 생각했다.

java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	... 생략 ...
    
Caused by: feign.RetryableException: 
PKIX path building failed: 
sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target executing 
GET '호출한 서비스 URL'
	at feign.FeignException.errorExecuting(FeignException.java:268)
	... 생략 ...
    
Caused by: javax.net.ssl.SSLHandshakeException: 
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target
	... 생략 ...

Caused by: sun.security.validator.ValidatorException: 
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target
	... 생략 ...
    
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target
	... 생략 ...

문제 원인

문제를 원인을 찾아보니,
1. 대중적으로 신뢰할 수 있는 인증 기관이지만 Java에서 신뢰를 하지 못하는 경우
2. 인증서를 회사 전용으로 가지고 있는 경우

이다.

 

Postman에서는 되지만, JAVA에서 안되는 것으로 보아 1번의 경우라 생각했다.

 

SSL HandShake는 서버에서 클라이언트에게 SSL 인증서를 전달하고, 클라이언트가 루트 CA(Certificate Authority, 인증기관) 인증서를 통해 서버가 보낸 SSL 인증서가 신뢰 가능한지 확인하는 단계이다.

 

 

JAVA는 서버로 부터 전달 받은 SSL 인증서를 루트 인증 저장소(cacerts)에 있는 루트 CA 인증서로 서버가 보낸 SSL 인증서의 신뢰성을 검증한다. 그러므로 JAVA에서 SSLHandshakeException 에러가 일어난 이유는, 서비스를 제공하는 서버의 SSL 인증서를 검증할 루트 CA 인증서가 루트 인증 저장소에 없기 때문이다. 

 

그러므로 JAVA의 루트 인증 저장소(cacerts)에 서버의 SSL 인증서를 발급한 인증 기관의 루트 CA 인증서를 등록하면 문제가 해결된다.

해결 방법

java 라이브러리의 security에 있는 루트 인증 저장소(cacerts)에, 서비스를 제공하는 서버의 SSL 인증서를 발급한 인증 기관의 루트 CA 인증서를 등록하면 된다.

루트 CA 인증서를 다운로드 받기 위해, InstallCert.java 파일을 활용한다.

아래 InstallCert.java 파일을 다운받는다.

InstallCert.java
0.01MB

 

터미널을 열어 InstallCert.java 파일 위치로 가서, javac로 컴파일 한다.

그러면 installCert.class가 생성된다.

 

installCert.class를 터미널로 실행시킨다.

java InstallCert '서비스 url의 host'

그러면 아래와 같이 진행하면 된다.

C:\dev>java InstallCert test.api.com
    
    ...
   
    Enter certificate to add to trusted keystore or 'q' to quit: [1]
    >> 나오면 1 입력   
    
    ...
    
    Added certificate to keystore 'jssecacerts' using alias 'test.api.com-1'
    >> CA 인증서의 alias인 test.api.com-1 따로 저장해두기

C:\dev>keytool -exportcert -keystore jssecacerts -storepass changeit -file output.cert -alias test.api.com-1
    >> -alias 뒤에 위에서 생성한 CA 인증서의 alias 입력
    

C:\dev>keytool -importcert -keystore C:/dev/jdk/jdk-11/lib/security/cacerts -storepass changeit -file output.cert -alias test.api.com-1
    >> -keystore 뒤에 ocal pc 의 java 설치 경로안에 있는 ../security/cacerts 경로
    >>  -alias 뒤에 위에서 생성한 CA 인증서의 alias 입력

    Trust this certificate? [no]:  
    >> 나오면 yes 입력

 

JAVA의 library 내 security의 cacert의 수정한 날짜가 변경된 것을 보아, 루트 CA 인증서가 저장된 것을 확인할 수 있다.

 

 

 

어플리케이션을 재부팅하면 문제가 해결된 것을 확인할 수 있다.

 

참고 자료

https://cert.crosscert.com/ssl%EC%9D%B8%EC%A6%9D%EC%84%9C-java-ca%EC%9D%B8%EC%A6%9D%EC%84%9C%EC%97%90-%EB%A3%A8%ED%8A%B8-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%B6%94%EA%B0%80%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95/

 

SSL인증서 JAVA CA인증서에 루트 인증서 추가하는 방법 - SSL 인증서 발급,종류,가격비교 | 한국전자

안녕하세요 한국전자인증 입니다. ​ JAVA CA인증서에 루트 인증서 추가하는 방법을 알려드립니다. 서버는 클라이언트에게 인증서를 전달해주며, 클라이언트는 서버로부터 전달받은 인증서를 루

cert.crosscert.com

 

https://deersoul6662.tistory.com/35

 

Java cacerts 인증서 추가(keytool 이용)

인증서 파일을 이용해 TLS를 적용하다보면, 클라이언트 단에서 문제가 생길 경우가 많이 발생한다. SSLHandshakeException 이라거나, PKIX Exception 이라거나. 문제가 생기는 경우는 여러가지 있을수 있는

deersoul6662.tistory.com

 

https://marindie.github.io/java/Java-CA-CACERTS-KR/#

 

JAVA Certificate 추가 방법. CACERTS, KEYTOOL

JAVA Certificate 추가 방법. CACERTS, KEYTOOL

marindie.github.io