Сообщение об ошибке
The remote certificate is invalid because of errors in the certificate chain: PartialChain
Часто сочетается с другими флагами, например «PartialChain, RevocationStatusUnknown». HttpClient оборачивает её в «The SSL connection could not be established, see inner exception.»
.NET SslStream / HttpClient — X509ChainStatusFlags.PartialChain: the chain could not be built up to a root
Что это означает
.NET не смог построить цепочку от сертификата сервера ни до одного корневого: не хватает промежуточного сертификата. Даже если корневому сертификату доверяют (как в воспроизведении), разрыв между конечным и корневым сертификатом не даёт пройти проверку. .NET умеет загружать недостающий промежуточный сертификат по URL из расширения Authority Information Access в сертификате, если такой URL есть и доступен, поэтому ошибка возникает в основном с частными CA, в закрытых сетях и в контейнерах.
Почему это происходит
Сервер отправляет только свой конечный сертификат
частоKestrel, привязки IIS или обратные прокси, настроенные с файлом сертификата или PFX, где есть только конечный сертификат.
Промежуточный сертификат не удаётся загрузить
иногдаУ частных CA часто нет URL в AIA, а хосты или контейнеры за межсетевым экраном не могут добраться до публичных, поэтому .NET не может сам восполнить пробел.
Промежуточный сертификат есть только на других машинах
иногдаВ Windows промежуточные сертификаты, закешированные или установленные в хранилище CertificateAuthority, позволяют цепочке строиться на одних машинах, но на новых серверах или в Linux-контейнерах она не строится.
Как исправить
- 1.
Проверьте, что отправляет сервер
Проблему подтверждает один-единственный сертификат в рукопожатии, выпущенный промежуточным CA.
bash openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:' - 2.
Отправляйте с сервера полную цепочку
В нашей проверке Kestrel (.NET 10), получив PEM с полной цепочкой только через ServerCertificate, отправлял лишь конечный сертификат, а промежуточный начал отправлять, когда ServerCertificateChain задали, как показано в примере. Для IIS установите промежуточный сертификат в хранилище «Промежуточные центры сертификации» (Intermediate Certification Authorities) на сервере, чтобы Windows его отправляла.
csharp // Kestrel sends intermediates only when they are given as ServerCertificateChain builder.WebHost.ConfigureKestrel(k => k.ConfigureHttpsDefaults(o => { o.ServerCertificate = X509Certificate2.CreateFromPemFile("fullchain.pem", "server.key"); var chain = new X509Certificate2Collection(); chain.ImportFromPemFile("fullchain.pem"); // leaf + intermediates o.ServerCertificateChain = chain; })); - 3.
Найдите недостающий промежуточный сертификат
Расширение AIA в конечном сертификате указывает на сертификат издателя; добавьте его в конфигурацию сервера.
bash # The leaf names where its issuer can be downloaded (Authority Information Access) openssl x509 -in server.pem -noout -ext authorityInfoAccess