Python 3.13 certificate verify failed
Python 3.13 włączył ścisłe sprawdzanie OpenSSL. Certyfikat główny firmy albo inspekcji, który starsze Pythony przyjmowały, teraz może zostać odrzucony za to, jak go zrobiono.
Co to znaczy
Od Pythona 3.13 domyślny kontekst TLS ustawia flagę OpenSSL VERIFY_X509_STRICT (dokumentacja Pythona). Z nią OpenSSL odrzuca certyfikaty, które łamią reguły standardu, nawet gdy łańcuch prowadzi do zaufanego certyfikatu głównego: certyfikat urzędu, którego rozszerzenie Basic Constraints nie jest oznaczone jako krytyczne, certyfikat bez Authority Key Identifier i podobne.
Publiczne urzędy wystawiają certyfikaty, które przechodzą. Certyfikaty zrobione ręcznie, przez stary wewnętrzny urząd albo przez niektóre produkty do inspekcji TLS mogą nie przejść, więc ten sam adres działa w Pythonie 3.12 i pada w 3.13.
Ustal, który certyfikat łamie którą regułę
certdoctor https://adres-ktory-nie-dziala/
Każdy Python w PATH ma własny wiersz w macierzy zaufania. Na Pythonie z OpenSSL w wersji 3 certdoctor stosuje te same ścisłe reguły do łańcucha, który zbudowałby OpenSSL, a wiersz nazywa certyfikat i regułę, którą łamie, zamiast samej odmowy. Pozostałe wiersze pokazują, czy ten sam certyfikat główny jest zaufany przez całą resztę, co zwykle jest prawdą.
Napraw to
Trwałą naprawą jest certyfikat zgodny z regułami: kto prowadzi urząd, wystawia go ponownie z Basic Constraints oznaczonym jako krytyczne i z Authority Key Identifier. Dla firmowego certyfikatu głównego albo produktu do inspekcji to prośba do działu IT albo do producenta, a wiersz raportu jest dowodem.
Dodanie certyfikatu głównego do magazynu zaufania Pythona nie pomaga, gdy jest on już zaufany: odmowa dotyczy tego, jak zrobiono certyfikat, a nie tego, komu ufa Python.
We własnym kodzie, zanim certyfikat zostanie wystawiony ponownie, kontekst może zdjąć ścisłą flagę tylko dla tego połączenia:
import ssl
context = ssl.create_default_context()
context.verify_flags &= ~ssl.VERIFY_X509_STRICT
To zostawia każde inne sprawdzenie, w tym łańcuch i nazwę.