본문 바로가기
Spring

Spring - ldap unable to find valid certification path to requested target 에러

by 오늘부터개발시작 2022. 8. 18.

 

 

 

 

 

 

규모가 있는 기업에서는 LDAP을 많이 사용한다. LDAP이 단순하면서도 부서를 나누는게 효율적이기 때문이다. 오늘은 LDAP에 대한 이야기가 아니라 Spring에서 ldap을 연동할 때 발생하는 에러에 대해서 원인과 해결하는 방법을 알아보도록하겠다. 

 

사내 LDAP 서버에 평문 통신을 할 때는 문제가 없었는데 SSL 요청을 날렸더니 아래와 같은 에러를 만나게 되었다.

javax.naming.CommunicationException: simple bind failed: 서버URL 
[Root exception is javax.net.ssl.SSLHandshakeException: 
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target]

 

에러 원인

에러의 원인은 인증서이다. JVM은 신뢰할 수 있는 인증 기관의 목록을 자체 보관하고 있고 SSL 인증서를 통한 요청이 들어오면 가지고 있는 인증 기관의 인증을 받은 인증서만 통신을 허락해준다.

 

다시 본론으로 돌아와서 에러의 현재 사용하고 있는 JVM의 신뢰하는 인증기관 목록에 요청하는 서버의 인증서 정보가 들어있지 않아서이다. 보통 공인 인증서가 아닌 사설 인증서를 쓰면 이런 경우가 있다.

 

그렇다면 이 문제를 어떻게 해결해 줄 수 있을까? 다행히도 JVM에 인증서를 등록할 수 있는 기능이 있다. 생각보다 간단하니 아래에서 차근차근 정리해보도록하겠다.

 

 

 

 

 

 

해결 순서

1. 인증서 추출

2. 인증정보 저장

3. JVM에 등록

 

1. Cert 인증서 추출

 

먼저 해당 서버와 통신을 할 때 받을 수 있는 cert 파일을 추출해야 한다. SSL 통신을 할 때는 비대칭키와 대칭키를 모두 사용하는데 최초에 요청을 하면 비대칭키 영역인 공개키를 전달 받을 수 있다. 그것으로 .crt파일을 만들어 준다. 아래 openssl 명령어를 입력해준다.

 

openssl s_client -showcerts -connect [서버도메인]
예시: openssl s_client -showcerts -connect ldapserver:636

 

2. 인증정보 저장

 

 

그러면 꽤 긴 응답이 터미널에 보일텐데 그 중에서 BEGIN 과 END 부분을 복사해서 원하는 이름대로 {아무이름}.crt 파일을 만든다. 만드는 방법은 메모장이나 아무 텍스트 프로그램을 열고 ----BEGIN ... --END .. --- 부분을 복사해서 넣는다.

 

-----BEGIN CERTIFICATE-----
aklfhskfadljasdl1340234234ASDSDFSDFSDFSDFSD
....
-----END CERTIFICATE-----

 

3. JVM에 등록

이제 .crt 파일도 준비가 됐으니 JVM에 등록하면 된다. JVM은 $JAVA_HOME/lib/security/cacerts 경로에 인증서들을 저장하고 있는다. 인증서들 중에서도 trustedCert가 있는데 우리는 이 타입의 인증서를 추가해준다.

 

참고

- permission error시 나면 앞에 sudo를 붙여주기

- 비밀번호를 설정한 적이 없는데 비밀번호를 물어본다면 default 비밀번호는 changeit

- 마지막에는 등록할건지 물어보는 프롬프트가 뜨면 y를 입력

- 아래 명령에서 pass가 들어간 부분은 비밀번호이다.

- alias는 별칭인데 기억하기 쉬운 것으로 하길 추천한다.

- keypass는 등록한 키의 비밀번호이고 

- storepass는 java key store의 비밀번호이다.

- hierarchy는 store에 key가 들어있는 구조이다.

keytool -import -v -trustcacerts -alias ldap_test -file ldap.crt 
-keystore $JAVA_HOME/jre/lib/security/cacerts -keypass changeit -storepass changeit

 

 

등록이 완료되었다는 메세지가 나오면 확인해보기 위해서 다음 명령어를 한 번 입력해보자. 명령어를 입력하면 store의 비밀번호를 입력하라고 나올 수도 있는데 우리가 만든 store가 아니라 JVM default 이기 때문에 비밀번호를 바꾸지 않았다면 changeit이다.

 

keytool -list -keystore "$JAVA_HOME/jre/lib/security/cacerts" | grep {alias 이름}
keytool -list -keystore "$JAVA_HOME/jre/lib/security/cacerts" | grep ldap