Сообщение об ошибке
remote error: tls: bad certificate
Серверы на Go записывают в журнал «http: TLS handshake error from <client>: remote error: tls: bad certificate». Клиенты на базе OpenSSL при таком же отказе отправляют другие оповещения (unknown_ca с TLS 1.2), поэтому текст на стороне сервера зависит от TLS-библиотеки клиента.
Go crypto/tls — TLS alert 42 received from the peer; typically logged by a Go server whose certificate a Go client rejected
Что это означает
Другая сторона отправила TLS-оповещение 42 (bad_certificate). В журнале сервера на Go («http: TLS handshake error from …: remote error: tls: bad certificate») это значит, что клиент отверг сертификат сервера: клиенты на Go отправляют это оповещение при любой ошибке проверки (неизвестный центр сертификации, истёкший срок действия, неверное имя). В клиенте на Go это значит, что сервер отверг клиентский сертификат при взаимной TLS-аутентификации. Настоящая причина видна только на той стороне, которая отправила оповещение.
Почему это происходит
Клиент на Go не доверяет сертификату сервера
частоСамоподписанные сертификаты или сертификаты частного CA, недостающие промежуточные сертификаты, истёкшие сертификаты или неверное имя; в журнале самого клиента будет «x509: …».
Взаимная TLS-аутентификация: сервер отверг клиентский сертификат
частоОшибка видна на стороне клиента, если срок действия его сертификата истёк, сертификат выпущен недоверенным CA или в нём нет назначения clientAuth.
Admission-вебхуки и операторы Kubernetes
иногдаAPI-сервер (клиент на Go) отвергает сертификат вебхука, если caBundle не совпадает, а сервер вебхука записывает это в журнал как bad certificate.
Как исправить
- 1.
Найдите клиента, который отвергает сертификат, и прочитайте его ошибку
Адрес клиента в журнале показывает, какой сервис нужно смотреть, а его ошибка называет настоящую причину сбоя проверки.
bash # The log line names the client; its own error message says why it rejected the certificate journalctl -u myservice | grep 'remote error: tls: bad certificate' | grep -oE 'from [0-9a-f.:]+' | sort | uniq -c - 2.
Отдавайте полную доверенную цепочку
Дайте серверу на Go PEM-файл с полной цепочкой, выпущенной CA, которому доверяют все клиенты.
go // Serve the full chain: leaf first, then intermediates, in one PEM file log.Fatal(http.ListenAndServeTLS(":443", "fullchain.pem", "server.key", nil)) - 3.
Kubernetes: проверьте caBundle вебхука
caBundle должен содержать CA, выпустивший серверный сертификат вебхука; CA injector из cert-manager поддерживает их синхронизацию.
bash # Kubernetes webhooks: the API server verifies the webhook's certificate with caBundle kubectl get validatingwebhookconfiguration my-webhook -o jsonpath='{.webhooks[0].clientConfig.caBundle}' \ | base64 -d | openssl x509 -noout -subject -enddate