Nieudane uzgadnianie połączenia SSL – nieprawidłowy certyfikat klienta

Przeglądasz dokumentację Apigee Edge.
Otwórz dokumentację Apigee X.
Informacje

Krótki opis problemu

W odpowiedzi na żądanie do interfejsu API aplikacja kliencka otrzymuje kod stanu HTTP 503 z komunikatem „Usługa niedostępna”. W śledzeniu interfejsu użytkownika zauważysz, że wartość error.cause w docelowym przepływie żądania to Received fatal alert: bad_certificate dla nieudanego żądania do interfejsu API.

Jeśli masz dostęp do logów procesora wiadomości, w przypadku nieudanego żądania do interfejsu API zobaczysz komunikat o błędzie jako Received fatal alert: bad_certificate. Ten błąd pojawia się podczas uzgadniania połączenia SSL między procesorem wiadomości a serwerem backendu w ramach dwukierunkowej konfiguracji TLS.

Komunikat o błędzie

Aplikacja kliencka pobiera ten kod odpowiedzi:

HTTP/1.1 503 Service Unavailable

Oprócz tego może pojawić się ten komunikat o błędzie:

{
 "fault": {
    "faultstring":"The Service is temporarily unavailable",
    "detail":{
        "errorcode":"messaging.adaptors.http.flow.ServiceUnavailable"
    }
 }
}

Użytkownicy chmury prywatnej zobaczą w logach procesora wiadomości /opt/apigee/var/log/edge-message-processor/system.log w przypadku konkretnego żądania interfejsu API ten błąd:

2017-10-23 05:28:57,813 org:org-name env:env-name api:apiproxy-name rev:revision-number messageid:message_id NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() : SSLClientChannel[C:IP address:port # Remote host:IP address:port #]@65461 useCount=1 bytesRead=0 bytesWritten=0 age=529ms lastIO=529ms handshake failed, message: Received fatal alert: bad_certificate

Możliwe przyczyny

Możliwe przyczyny tego problemu:

Przyczyna Opis Instrukcje dotyczące rozwiązywania problemów
Brak certyfikatu klienta Magazyn kluczy używany w docelowym punkcie końcowym serwera docelowego nie ma żadnego certyfikatu klienta. Użytkownicy chmury prywatnej i publicznej Cloud
Niezgodność urzędu certyfikacji Urząd certyfikacji, w którym znajduje się certyfikat liścia (pierwszy certyfikat w łańcuchu certyfikatów) w magazynie kluczy podmiotu przetwarzającego wiadomości, nie pasuje do żadnego z urzędów certyfikacji zaakceptowanych przez serwer backendu. Użytkownicy chmury prywatnej i publicznej Cloud

Najczęstsze kroki diagnostyki

  1. Włącz śledzenie w interfejsie użytkownika Edge, wywołaj interfejs API i odtwórz problem.
  2. Przejdź przez poszczególne fazy w wynikach śledzenia interfejsu użytkownika i ustal, gdzie wystąpił błąd. Ten błąd mógłby wystąpić w docelowym przepływie żądania.
  3. Sprawdź proces, w którym pokazuje się błąd. Powinien on zostać wyświetlony tak, jak w tym przykładowym śladzie poniżej:

    alt_text

  4. Jak widać na zrzucie ekranu powyżej, wartość error.cause to error.cause .
  5. Jeśli jesteś użytkownikiem Private Cloud, wykonaj te czynności:
    1. Możesz uzyskać identyfikator wiadomości dla nieudanego żądania do interfejsu API, określając wartość nagłówka błędu „X-Apigee.Message-ID” w fazie wskazywanej przez AX w logu czasu.
    2. Wyszukaj ten identyfikator wiadomości w logu /opt/apigee/var/log/edge-message-processor/system.log procesora wiadomości i sprawdź, czy znajdziesz więcej informacji o błędzie:
      2017-10-23 05:28:57,813 org:org-name env:env-name api:apiproxy-name
      rev:revision-number messageid:message_id NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() :
      SSLClientChannel[C:IP address:port # Remote host:IP address:port #]@65461 useCount=1
      bytesRead=0 bytesWritten=0 age=529ms lastIO=529ms handshake failed, message: Received fatal alert: bad_certificate
      2017-10-23 05:28:57,813 org:org-name env:env-name api:apiproxy-name
      rev:revision-number messageid:message_id NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() : SSLInfo:
      KeyStore:java.security.KeyStore@52de60d9 KeyAlias:KeyAlias TrustStore:java.security.KeyStore@6ec45759
      2017-10-23 05:28:57,814 org:org-name env:env-name api:apiproxy-name
      rev:revision-number messageid:message_id NIOThread@0 ERROR ADAPTORS.HTTP.FLOW - RequestWriteListener.onException() :
      RequestWriteListener.onException(HTTPRequest@6071a73d)
      javax.net.ssl.SSLException: Received fatal alert: bad_certificate
      at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) ~[na:1.8.0_101]
      at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1666) ~[na:1.8.0_101]
      at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1634) ~[na:1.8.0_101]
      at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1800) ~[na:1.8.0_101]
      at com.apigee.nio.NIOSelector$SelectedIterator.findNext(NIOSelector.java:496) [nio-1.0.0.jar:na]
      at com.apigee.nio.util.NonNullIterator.computeNext(NonNullIterator.java:21) [nio-1.0.0.jar:na]
      at com.apigee.nio.util.AbstractIterator.hasNext(AbstractIterator.java:47) [nio-1.0.0.jar:na]
      at com.apigee.nio.NIOSelector$2.findNext(NIOSelector.java:312) [nio-1.0.0.jar:na]
      at com.apigee.nio.NIOSelector$2.findNext(NIOSelector.java:302) [nio-1.0.0.jar:na]
      at com.apigee.nio.util.NonNullIterator.computeNext(NonNullIterator.java:21) [nio-1.0.0.jar:na]
      at com.apigee.nio.util.AbstractIterator.hasNext(AbstractIterator.java:47) [nio-1.0.0.jar:na]
      at com.apigee.nio.handlers.NIOThread.run(NIOThread.java:59) [nio-1.0.0.jar:na]
      

      W logu procesora wiadomości znajdował się zrzut stosu błędu Received fatal alert: bad_certificate, ale nie ma żadnych dodatkowych informacji, które wskazywałyby na przyczynę tego problemu.

  6. Aby dokładniej zbadać ten problem, musisz przechwycić pakiety TCP/IP za pomocą narzędzia tcpdump.
    1. Jeśli jesteś użytkownikiem Private Cloud, możesz przechwytywać pakiety TCP/IP na serwerze backendu lub procesorze wiadomości. Najlepiej przechwytywać je na serwerze backendu, gdy pakiety są odszyfrowywane na serwerze backendu.
    2. Jeśli jesteś użytkownikiem chmury publicznej, przechwyć pakiety TCP/IP na serwerze backendu.
    3. Gdy już określisz, gdzie chcesz przechwytywać pakiety TCP/IP, użyj poniższego polecenia tcpdump, aby przechwycić pakiety TCP/IP.
    4. tcpdump -i any -s 0 host <IP address> -w <File name>

      Jeśli przyjmujesz pakiety TCP/IP przez procesor wiadomości, użyj publicznego adresu IP serwera backendu w poleceniu tcpdump.

      Jeśli jest wiele adresów IP dla serwera backendu/procesora wiadomości, musisz użyć innego polecenia tcpdump. Więcej informacji o tym narzędziu i jego innych wariantach znajdziesz w tcpdump.

  7. Przeanalizuj pakiety TCP/IP za pomocą narzędzia Wireshark lub podobnego, które znasz.

Analiza przykładowych danych pakietów TCP/IP za pomocą narzędzia Wireshark:

alt_text

  1. Komunikat nr 4 w powyższym pliku tcpdump pokazuje, że procesor wiadomości (źródło) wysłał komunikat „Client Hello” do serwera backendu (docelowego).
  2. Komunikat nr 5 oznacza, że serwer backendu akceptuje komunikat Client Hello od podmiotu przetwarzającego wiadomości.
  3. Serwer backendu wysyła wiadomość „Cześć serwera” wraz z certyfikatem, a następnie żąda od klienta wysłania certyfikatu w wiadomości 7.
  4. Procesor wiadomości kończy weryfikację certyfikatu i potwierdza komunikat ServerHello w wiadomości nr 8 serwera backendu.
  5. Procesor wiadomości wysyła swój certyfikat do serwera backendu w wiadomości nr 9.
  6. Serwer backendu potwierdza odbiór certyfikatu procesora wiadomości w wiadomości nr 11.
  7. Natychmiast jednak wysyła do procesora wiadomości komunikat Fatal Alert: Bad Certificate (Błąd krytyczny: nieprawidłowy certyfikat) do procesora wiadomości (komunikat 12). Wskazuje to, że certyfikat wysłany przez procesor wiadomości był nieprawidłowy i dlatego weryfikacja certyfikatu nie powiodła się na serwerze backendu. Z tego powodu uzgadnianie połączenia SSL nie powiodło się i połączenie zostanie zamknięte.


    alt_text

  8. Przyjrzyjmy się teraz wiadomościom nr 9, aby sprawdzić zawartość certyfikatu wysłanego przez procesor wiadomości:


    alt_text

  9. Jak widać, serwer backendu nie otrzymał od klienta żadnego certyfikatu (Długość certyfikatu: 0). Z tego powodu serwer backendu wysyła alert krytyczny: nieprawidłowy certyfikat.
  10. Zwykle dzieje się tak, gdy klient, tj. procesor wiadomości (proces oparty na Javie):
    1. nie ma żadnego certyfikatu klienta w swoim magazynie kluczy lub
    2. Nie można wysłać certyfikatu klienta. Przyczyną może być to, że nie można znaleźć certyfikatu wystawionego przez jeden z akceptowanych urzędów certyfikacji serwera backendu. Oznacza to, że jeśli urząd certyfikacji certyfikatu klienta (czyli pierwszy certyfikat w łańcuchu) nie pasuje do żadnego z urzędów certyfikacji serwera backendu, podmiot przetwarzający wiadomości nie wyśle certyfikatu.

Przyjrzyjmy się każdej z tych przyczyn oddzielnie.

Przyczyna: brak certyfikatu klienta

Diagnostyka

Jeśli w magazynie kluczy nie ma certyfikatu podanego w sekcji informacji o protokole SSL docelowego punktu końcowego lub serwera docelowego używanego w docelowym punkcie końcowym, to jest przyczyną tego błędu.

Aby sprawdzić, czy jest ono przyczyną problemu, wykonaj te czynności:

  1. Aby określić magazyn kluczy używany w docelowym punkcie końcowym lub serwerze docelowym konkretnego serwera proxy interfejsu API, wykonaj te czynności:
    1. Pobierz nazwę odwołania do magazynu kluczy z elementu Keystore w sekcji SSLInfo docelowego punktu końcowego lub serwera docelowego.

      Spójrzmy na przykładową sekcję SSLInfo w konfiguracji docelowego punktu końcowego:

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. W powyższym przykładzie nazwa odniesienia do magazynu kluczy to „myKeystoreRef”.
    3. Otwórz interfejs użytkownika Edge i wybierz Proxies API -> Konfiguracje środowiska.

      Wybierz kartę Pliki referencyjne i wyszukaj nazwę odwołania do magazynu kluczy. Zapisz nazwę w kolumnie Dokumentacja, aby znaleźć odpowiednie odwołanie do magazynu kluczy. Będzie to nazwa magazynu kluczy.


      alt_text

    4. W przykładzie powyżej można zwrócić uwagę, że odniesienie do magazynukluczy ma odwołanie do „mojego magazynu kluczy”. Dlatego nazwa magazynu kluczy to myKeystore.
  2. Sprawdź, czy ten magazyn kluczy zawiera certyfikat za pomocą interfejsu użytkownika Edge lub Wyświetl listę certyfikatów dla interfejsu API magazynu kluczy.
  3. Jeśli magazyn kluczy zawiera certyfikaty, przejdź do sekcji Przyczyna: niezgodność urzędu certyfikacji.
  4. Jeśli magazyn kluczy nie zawiera żadnego certyfikatu, jest to powodem, dla którego certyfikat klienta nie jest wysyłany przez procesor wiadomości.

Rozdzielczość

  1. Sprawdź, czy do określonego magazynu kluczy w procesorze wiadomości został przesłany prawidłowy i kompletny łańcuch certyfikatów klienta.

Przyczyna: niezgodność urzędu certyfikacji

Zwykle, gdy serwer żąda od klienta wysłania certyfikatu, wskazuje zbiór zaakceptowanych wydawców lub urzędów certyfikacji. Jeśli wystawca/urząd certyfikacji certyfikatu liścia (tzn. pierwszy certyfikat w łańcuchu certyfikatów) w magazynie kluczy podmiotu przetwarzającego wiadomości nie pasuje do żadnego z urzędów certyfikacji zaakceptowanych przez serwer backendu, podmiot przetwarzający wiadomości (proces oparty na Javie) nie wyśle certyfikatu do serwera backendu.

Aby to sprawdzić:

  1. Wyświetl listę certyfikatów interfejsu API magazynu kluczy
  2. Pobierz szczegóły każdego certyfikatu uzyskanego w kroku 1 powyżej za pomocą narzędzia Pobierz certyfikat dla interfejsu API magazynu kluczy.
  3. Zanotuj wystawcę certyfikatu liścia (tj. pierwszego certyfikatu w łańcuchu certyfikatów) zapisanego w magazynie kluczy.

    Przykładowy certyfikat liścia

    {
      "certInfo" : [ {
        "basicConstraints" : "CA:FALSE",
        "expiryDate" : 1578889324000,
        "isValid" : "Yes",
        "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com",
        "publicKey" : "RSA Public Key, 2048 bits",
        "serialNumber" : "65:00:00:00:d2:3e:12:d8:56:fa:e2:a9:69:00:06:00:00:00:d2",
        "sigAlgName" : "SHA256withRSA",
        "subject" : "CN=nonprod-api.mycompany.com, OU=ITS, O=MyCompany, L=MELBOURNE, ST=VIC, C=AU",
        "subjectAlternativeNames" : [ ],
        "validFrom" : 1484281324000,
        "version" : 3
      } ],
      "certName" : "nonprod-api.mycompany.com.key.pem-cert"
    }
    

    W tym przykładzie wydawca/urząd certyfikacji to "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com"

  4. Określ listę wydawców lub urzędów certyfikacji dozwoloną przez serwer backendu, korzystając z jednej z tych metod:

    Technika 1. Użyj tego polecenia opensl:

    openssl s_client -host <backend server host name> -port <Backend port#> -cert <Client Certificate> -key <Client Private Key>
    

    Zapoznaj się z sekcją „Akceptowane nazwy certyfikatów klienta” w danych wyjściowych tego polecenia, jak pokazano poniżej:

    Acceptable client certificate CA names
    /C=AU/ST=VIC/L=MELBOURNE/O=MyCompany/OU=ITS/CN=nonprod-api.mycompany.com
    /C=AU/ST=VIC/L=MELBOURNE/O=MyCompany/OU=ITS/CN=nonprod-api.mycompany.com
    

    Technika 2. Sprawdź pakiet Certificate Request w pakietach TCP/IP, gdy serwer backendu prosi klienta o wysłanie certyfikatu:

    W przykładowych pakietach TCP/IP pokazanych powyżej pakiet Certificate Request to komunikat nr 7. Zapoznaj się z sekcją „Nazwy wyróżniające”, która zawiera dopuszczalne urzędy certyfikacji serwera backendu.

    alt_text

  5. Sprawdź, czy urząd certyfikacji uzyskany w kroku 3 jest zgodny z listą zaakceptowanych wydawców lub urzędów certyfikacji zaakceptowanych w kroku 4. W przypadku niezgodności procesor wiadomości nie wyśle certyfikatu klienta do serwera backendu.

    W powyższym przykładzie można zauważyć, że wystawca certyfikatu liścia klienta w magazynie kluczy podmiotu przetwarzającego wiadomości nie pasuje do żadnego z zaakceptowanych urzędów certyfikacji serwera backendu. Z tego powodu procesor wiadomości nie wysyła certyfikatu klienta do serwera backendu. Spowoduje to niepowodzenie uzgadniania połączenia SSL, a serwer backendu wyśle komunikat „Fatal alert: bad_certificate”.

Rozdzielczość

  1. Sprawdź, czy w Truststore przechowywany jest certyfikat u wystawcy / urzędu certyfikacji zgodnego z wystawcą lub urzędem certyfikacji certyfikatu liścia klienta (pierwszy certyfikat w łańcuchu).
  2. W przykładzie opisanym w tym scenariuszu do obiektu Truststore serwera backendu został dodany certyfikat u wydawcy "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com", aby rozwiązać problem.

Jeśli problem nadal występuje, przejdź do artykułu Must Gather Diagnostic Information (Wymagane zbieranie informacji diagnostycznych).

Musi gromadzić informacje diagnostyczne

Jeśli po wykonaniu powyższych instrukcji problem nie ustąpi, zbierz poniższe informacje diagnostyczne. Skontaktuj się z zespołem pomocy Apigee Edge i udostępnij je:

  1. Jeśli jesteś użytkownikiem chmury publicznej, podaj te informacje:
    1. Nazwa organizacji
    2. Nazwa środowiska
    3. Nazwa serwera proxy interfejsu API
    4. Wykonaj polecenie curl, aby odtworzyć błąd
    5. Plik śledzenia pokazujący błąd
    6. Pakiety TCP/IP przechwycone na serwerze backendu
  2. Jeśli jesteś użytkownikiem Private Cloud, podaj te informacje:
    1. Zarejestrowano pełny komunikat o błędzie
    2. Pakiet proxy API
    3. Plik śledzenia pokazujący błąd
    4. Procesor wiadomości loguje /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. Pakiety TCP/IP przechwycone na serwerze backendu lub procesorze wiadomości.
    6. Dane wyjściowe Get cert for keystore API.
  3. Informacje o wypróbowanych przez Ciebie sekcjach tego poradnika oraz o innych statystykach, które pomogą nam przyspieszyć rozwiązanie tego problemu.