2025. 10. 20

PKIX path building failed 원인과 해결

TLS 인증서 체인 오류의 원인을 추적하고 자바 truststore에 CA를 등록해 해결합니다

  • #INFRA

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)로 서명 검증 → 암호화 채널 성립 → 요청/응답 수행