Сообщение об ошибке
PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed
Также выводится как
- javax.net.ssl.SSLHandshakeException: (certificate_expired) PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed
JDK 21 и более поздние версии ставят в начало оповещение TLS: «(certificate_expired) PKIX path validation failed: …». Строка исходной причины — «java.security.cert.CertificateExpiredException: NotAfter: <date>» (или CertificateNotYetValidException: NotBefore: <date>), дата указана в часовом поясе JVM.
Java (JSSE) — SSLHandshakeException caused by CertPathValidatorException / CertificateExpiredException
Что это означает
Java построила путь сертификации до якоря доверия, но проверка пути сертификации не прошла контроль дат: по текущему времени JVM один из сертификатов пути находится вне срока действия. Слова «path validation» (а не «path building») означают, что с доверием всё в порядке, проблема в датах. Вложенное исключение CertificateExpiredException или CertificateNotYetValidException указывает, какая граница срока действия нарушена.
Почему это происходит
Срок действия сертификата сервера (или промежуточного) истёк
частоПродления не произошло, или продлённый сертификат не развёрнут на том эндпоинте, к которому обращается Java (часто это внутренний балансировщик нагрузки или Java-сервер с собственным хранилищем ключей).
Цепочка построена через просроченный сертификат из собственного хранилища доверенных сертификатов
иногдаЕсли в хранилище доверенных сертификатов напрямую закреплён старый промежуточный сертификат или сертификат сервера, проверка продолжает опираться на него и после истечения его срока действия.
Часы на хосте JVM показывают неверное время
иногдаНа виртуальных машинах и в контейнерах, где часы хоста разошлись с реальным временем, действующие сертификаты могут выглядеть просроченными или ещё не действительными.
Только что выпущенный сертификат и отстающие часы
редкоСертификаты, действительные «с текущего момента», не проходят проверку на клиентах, у которых часы отстают на несколько минут; поэтому большинство CA немного сдвигают notBefore в прошлое, а частные CA часто этого не делают.
Как исправить
- 1.
Найдите самую вложенную причину
По дате NotAfter или NotBefore видно, истёк ли срок действия сертификата или неверно идут часы.
text Caused by: java.security.cert.CertificateExpiredException: NotAfter: Tue Apr 01 00:00:00 UTC 2025 -> a certificate in the chain expired on that date Caused by: java.security.cert.CertificateNotYetValidException: NotBefore: ... -> not valid yet: check the clock of this machine - 2.
Проверьте каждый сертификат, который отдаёт сервер
Выведите дату окончания срока действия каждого сертификата в отдаваемой цепочке и замените тот, у которого он истёк.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts 2>/dev/null \ | awk '/BEGIN CERT/{n++; f="c" n ".pem"} /BEGIN CERT/,/END CERT/{print > f}' for f in c*.pem; do openssl x509 -in "$f" -noout -subject -enddate; done - 3.
Наведите порядок в собственных хранилищах доверенных сертификатов
Выведите записи хранилища доверенных сертификатов вместе со сроками действия и удалите или замените закреплённые в нём просроченные сертификаты.
bash # Expired or pinned certificates in a custom trust store keytool -list -v -keystore app-truststore.p12 -storepass changeit | grep -E 'Alias name|Valid until|Owner' keytool -delete -alias old-corp-root -keystore app-truststore.p12 -storepass changeit