Перейти к содержимому
ecdsa.com
Go crypto/tls (Go ≥ 1.20)Go

Сообщение об ошибке

tls: failed to verify certificate: x509: certificate signed by unknown authority

Go crypto/tls (Go ≥ 1.20) — wrapping x509 verification errors

Что это означает

Начиная с Go 1.20 ошибки TLS-рукопожатия оборачивают исходную ошибку x509, добавляя префикс «tls: failed to verify certificate:», поэтому в журналах видны и уровень (TLS-рукопожатие), и первопричина (не удалось построить цепочку). Суффикс бывает разным (неизвестный CA, истёкший срок действия, несовпадение имени хоста), и действовать нужно именно по нему. Префикс к тому же удобен для фильтрации журналов: поиск по нему через grep отделяет ошибки доверия TLS от ошибок уровня приложения, ради чего обёртку и добавили.

Почему это происходит

Как исправить

  1. 1.

    Передайте клиенту правильные якоря доверия

    То же решение, что и для ошибки x509 без префикса: пул корневых сертификатов с CA, выпустившим сертификат, задаётся в том транспорте, через который действительно идёт подключение.

    go
    pool := x509.NewCertPool()
    caPEM, _ := os.ReadFile("ca.pem")
    pool.AppendCertsFromPEM(caPEM)
    
    client := &http.Client{Transport: &http.Transport{
        TLSClientConfig: &tls.Config{RootCAs: pool},
    }}
    resp, err := client.Get("https://internal.example:8443/healthz")
  2. 2.

    Посмотрите, что предъявляет сервер

    Прежде чем трогать клиентский код, посмотрите отдаваемую цепочку, её издателей и сроки действия — чаще всего исправление оказывается в конфигурации цепочки на стороне сервера.

    bash
    openssl s_client -connect internal.example:8443 -servername internal.example \
      </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates
  3. 3.

    Не отключайте проверку даже в тестах

    Серверы httptest выдают заранее настроенный клиент; используйте его, а не отключайте проверку глобально.

    go
    srv := httptest.NewTLSServer(handler)
    defer srv.Close()
    resp, err := srv.Client().Get(srv.URL)   // trusts srv's cert, nothing else

Связанные ошибки

Открыть всю базу ошибок подписей