PKIX path building failed 원인과 해결 - 자바 truststore에 CA 체인 등록하기

PKIX path building failed 원인과 해결 - 자바 truststore에 CA 체인 등록하기

1. 문제 상황

  • Java 애플리케이션(JDK 1.8)에서 Keycloak(HTTPS)로 토큰 요청 시 TLS Handshake 도중 서버 인증서 체인을 신뢰하지 못해 실패함

2. 발생 에러

  • 최초 에러: truststore에 CA 인증서 없음 → PKIX path building failed
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
  • 2차 에러: fullchain.pem을 keytool로 import했으나, keytool은 PEM 안의 첫 번째 인증서(Leaf)만 등록하기 때문에 상위 CA가 빠져 동일 오류 발생
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.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)

3. 문제 원인

  • TLS Handshake 시 서버(Keycloak)는 서버 인증서(Leaf) 를 클라이언트(Java)에게 전달함. 클라이언트는 truststore에 저장된 Root CA 및 Intermediate CA 공개키로 해당 인증서의 위조 여부를 검증해야 함
  • 하지만 Java truststore에 서버 인증서를 서명한 상위 CA 인증서(Root/Intermediate) 가 없어서 인증서 Chain이 신뢰 기준(Root)까지 이어지지 못했고 결과적으로 PKIX path building failed 오류가 발생
Leaf → Intermediate → Root ↑ (truststore에 없음 → Chain 단절)
즉,
시도
조치
실패 원인
결과
1차
truststore 비어 있음
CA 정보 없음
PKIX 오류
2차
fullchain.pem 통째 추가
Leaf만 추가되었고 CA 누락
동일 오류

4. 해결 방법

1) Keycloak 서버에서 인증서 체인 직접 추출

  • 운영 신뢰성을 위해 Keycloak 서버와 통신하여 실제 인증서 Chain을 추출한 뒤 Root / Intermediate / Leaf 인증서를 분리 저장
openssl s_client -connect <keycloak-host>:443 -servername <keycloak-host> -showcerts </dev/null 2>/dev/null \ | awk ' /-----BEGIN CERTIFICATE-----/{ n++; fn = sprintf("cert-%02d.pem", n); writing=1 } writing{ print > fn } /-----END CERTIFICATE-----/{ close(fn); writing=0 }'

2) Root + Intermediate CA만 truststore에 등록

  • Leaf 인증서는 truststore 등록 불필요 (서버가 Handshake 과정에서 전달함)
# Root CA 등록 keytool -importcert \ -alias root-ca \ -file isrgrootx1.pem \ -keystore custom-truststore.jks \ -storepass <password> \ -noprompt # Intermediate CA 등록 keytool -importcert \ -alias intermediate-ca \ -file cert-02.pem \ -keystore custom-truststore.jks \ -storepass <password> \ -noprompt

3) JVM 실행 옵션에 커스텀 truststore 설정

-Djavax.net.ssl.trustStore=/path/to/custom-truststore.jks -Djavax.net.ssl.trustStorePassword=<password> -Djavax.net.ssl.trustStoreType=JKS

4) 서비스 재기동 후 정상 동작 확인

  • TLS Handshake 및 PKIX 검증 정상 완료
  • OAuth2 토큰 요청 성공

5. 마무리

서버 인증서(Leaf) 전달 → CA 공개키(truststore)로 서명 검증 → 암호화 채널 성립 → 요청/응답 수행