Errori di handshake SSL - Certificato client non valido

Stai visualizzando la documentazione di Apigee Edge.
Vai alla documentazione di Apigee X.
informazioni

Sintomo

L'applicazione client riceve un codice di stato HTTP 503 con il messaggio "Servizio non disponibile" in risposta a una richiesta API. Nella traccia UI, noterai che il valore error.cause è Received fatal alert: bad_certificate nel flusso di richieste di destinazione per la richiesta API in errore.

Se hai accesso ai log del processore di messaggi, vedrai il messaggio di errore come Received fatal alert: bad_certificate per la richiesta API in errore. Questo errore viene osservato durante il processo di handshake SSL tra il processore di messaggi e il server di backend in una configurazione TLS a due vie.

Messaggio di errore

L'applicazione client riceve il seguente codice di risposta:

HTTP/1.1 503 Service Unavailable

Inoltre, potresti visualizzare il seguente messaggio di errore:

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

Gli utenti Private Cloud vedranno il seguente errore per la richiesta API specifica nei log del processore di messaggi /opt/apigee/var/log/edge-message-processor/system.log:

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

Possibili cause

Le possibili cause di questo problema sono le seguenti:

Causa Descrizione Istruzioni per la risoluzione dei problemi applicabili a
Nessun certificato client L'archivio chiavi utilizzato nell'endpoint di destinazione del server di destinazione non ha alcun certificato client. Utenti del cloud privato e pubblico Edge
Mancata corrispondenza dell'autorità di certificazione L'autorità di certificazione del certificato foglia (il primo certificato nella catena di certificati) nel keystore dell'elaboratore di messaggi non corrisponde a nessuna delle autorità di certificazione accettate dal server di backend. Utenti del cloud privato e pubblico Edge

Passaggi di diagnosi comuni

  1. Abilita la traccia nell'interfaccia utente Edge, effettua la chiamata API e riproduci il problema.
  2. Nei risultati della traccia UI, esplora ogni fase e determina dove si è verificato l'errore. L'errore si sarebbe verificato nel flusso di richiesta target.
  3. Esamina il flusso che mostra l'errore; dovresti osservare l'errore come mostrato nella traccia di esempio riportata di seguito:

    alt_text

  4. Come vedi nello screenshot sopra, il file error.cause è "Ricevuto avviso irreversibile: bad_certificate".
  5. Se sei un utente Private Cloud, segui le istruzioni riportate di seguito:
    1. Puoi ottenere l'ID messaggio per la richiesta API non riuscita determinando il valore dell'intestazione di errore "X-Apigee.Message-ID" nella fase indicata da AX nella traccia.
    2. Cerca questo ID messaggio nel log dell'elaboratore dei messaggi /opt/apigee/var/log/edge-message-processor/system.log e determina se puoi trovare ulteriori informazioni sull'errore:
      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]
      

      Il log del processore di messaggi conteneva un'analisi dello stack per l'errore Received fatal alert: bad_certificate, ma non contiene ulteriori informazioni che indichino la causa del problema.

  6. Per analizzare ulteriormente il problema, dovrai acquisire i pacchetti TCP/IP utilizzando lo strumento tcpdump.
    1. Se sei un utente Private Cloud, puoi acquisire i pacchetti TCP/IP sul server di backend o sul processore di messaggi. Preferibilmente, acquisiscili sul server di backend mentre i pacchetti vengono decriptati sul server di backend.
    2. Se sei un utente del cloud pubblico, acquisisci i pacchetti TCP/IP sul server di backend.
    3. Una volta deciso dove acquisire i pacchetti TCP/IP, utilizza il comando tcpdump riportato di seguito per acquisire i pacchetti TCP/IP.
    4. tcpdump -i any -s 0 host <IP address> -w <File name>

      Se impieghi i pacchetti TCP/IP sul processore di messaggi, utilizza l'indirizzo IP pubblico del server di backend nel comando tcpdump.

      Se sono presenti più indirizzi IP per il server di backend/il processore di messaggi, devi utilizzare un comando tcpdump diverso. Fai riferimento a tcpdump per ulteriori informazioni su questo strumento e per altre varianti di questo comando.

  7. Analizza i pacchetti TCP/IP utilizzando lo strumento Wireshark o uno strumento simile che conosci.

Ecco l'analisi dei dati di pacchetti TCP/IP di esempio utilizzando lo strumento Wireshark:

alt_text

  1. Il messaggio 4 in tcpdump riportato sopra indica che il processore di messaggi (origine) ha inviato un messaggio "Client Hello" al server di backend (destinazione).
  2. Il messaggio 5 mostra che il server di backend conferma il messaggio Client Hello dal processore di messaggi.
  3. Il server di backend invia il messaggio "Server Hello" insieme al certificato, quindi richiede al client di inviare il certificato nel messaggio 7.
  4. Il processore di messaggi completa la verifica del certificato e riconosce il messaggio ServerHello del server di backend nel messaggio n. 8.
  5. Il processore di messaggi invia il proprio certificato al server di backend nel messaggio 9.
  6. Il server di backend conferma la ricezione del certificato del processore di messaggi nel messaggio 11.
  7. Tuttavia, invia immediatamente un avviso irreversibile: certificato non valido all'elaboratore di messaggi (messaggio n. 12). Questo indica che il certificato inviato dal processore di messaggi era non valido e che la verifica del certificato non è riuscita sul server di backend. Di conseguenza, l'handshake SSL non è riuscito e la connessione verrà chiusa.


    alt_text

  8. Diamo ora un'occhiata al Messaggio 9 per verificare i contenuti del certificato inviato dal processore di messaggi:


    alt_text

  9. Come puoi notare, il server di backend non ha ricevuto alcun certificato dal client (lunghezza del certificato: 0). Di conseguenza, il server di backend invia l'avviso irreversibile: certificato non valido.
  10. In genere questo accade quando il client, ovvero un processore di messaggi (un processo basato su Java):
    1. non dispone di certificati client nel proprio archivio chiavi, oppure
    2. Impossibile inviare un certificato client. Questo può accadere se non riesce a trovare un certificato emesso da una delle autorità di certificazione accettabili del server di backend. Questo significa che se l'autorità di certificazione del certificato in foglie del client (ovvero il primo certificato della catena) non corrisponde a nessuna delle autorità di certificazione accettabili del server di backend, il processore di messaggi non invierà il certificato.

Analizziamo ciascuna di queste cause separatamente nel seguente modo.

Causa: nessun certificato client

Diagnostica

Se nell'archivio chiavi specificato non è presente alcun certificato nella sezione Informazioni SSL dell'endpoint di destinazione o del server di destinazione utilizzato nell'endpoint di destinazione, questa è la causa dell'errore.

Per determinare se la causa è questa, procedi nel seguente modo:

  1. Determina l'archivio chiavi utilizzato nell'endpoint di destinazione o nel server di destinazione per il proxy API specifico seguendo questi passaggi:
    1. Recupera il nome di riferimento dell'archivio chiavi dall'elemento Keystore nella sezione SSLInfo dell'endpoint di destinazione o del server di destinazione.

      Esaminiamo una sezione SSLInfo di esempio in una configurazione di endpoint di destinazione:

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. Nell'esempio precedente, il nome di riferimento dell'archivio chiavi è "myKeystoreRef".
    3. Vai alla UI di Edge e seleziona proxy API -> Configurazioni di ambiente.

      Seleziona la scheda Riferimenti e cerca il nome di riferimento dell'archivio chiavi. Prendi nota del nome nella colonna Riferimento per il riferimento specifico all'archivio chiavi. Questo sarà il nome del tuo archivio chiavi.


      alt_text

    4. Nell'esempio precedente, puoi notare che myKeystoreRef ha il riferimento a "myKeystore". Di conseguenza, il nome dell'archivio chiavi è myKeystore.
  2. Controlla se l'archivio chiavi contiene il certificato utilizzando l'interfaccia utente Edge o l'elenco di certificati per l'API dell'archivio chiavi.
  3. Se l'archivio chiavi contiene uno o più certificati, passa a Causa: mancata corrispondenza dell'autorità di certificazione.
  4. Se l'archivio chiavi non contiene alcun certificato, è per questo motivo che il certificato client non viene inviato dal processore di messaggi.

Risoluzione

  1. Assicurati che nell'archivio chiavi specifico del processore di messaggi sia stata caricata la catena di certificati client corretta e completa.

Causa: mancata corrispondenza dell'autorità di certificazione

In genere, quando il server richiede al client di inviare il proprio certificato, indica l'insieme di emittenti o autorità di certificazione accettati. Se l'emittente/l'autorità di certificazione del certificato foglia (ovvero il primo certificato nella catena di certificati) nel Keystore dell'elaboratore dei messaggi non corrisponde a nessuna delle autorità di certificazione accettate dal server di backend, il processore di messaggi (ovvero un processo basato su Java) non invierà il certificato al server di backend.

Per verificare se è così:

  1. Elenca i certificati per l'API Keystore.
  2. Ottieni i dettagli di ogni certificato ottenuto nel passaggio 1 precedente utilizzando la pagina Ottieni un certificato per l'API Keystore.
  3. Prendi nota dell'emittente del certificato foglia (ovvero il primo certificato nella catena di certificati) archiviato nell'archivio chiavi.

    Esempio di certificato Fogliolina

    {
      "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"
    }
    

    Nell'esempio precedente, l'emittente/l'autorità di certificazione è "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com"

  4. Determina l'elenco di emittenti o autorità di certificazione accettati dal server di backend utilizzando una delle seguenti tecniche:

    Tecnica 1: utilizza il comando beginsl di seguito:

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

    Fai riferimento alla sezione "Nomi CA certificati client accettabili" nell'output di questo comando, come mostrato di seguito:

    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
    

    Tecnica 2: controlla il pacchetto Certificate Request nei pacchetti TCP/IP, in cui il server di backend richiede al client di inviare il proprio certificato:

    Nei pacchetti TCP/IP di esempio mostrati sopra, il pacchetto Certificate Request è il messaggio 7. Fai riferimento alla sezione "Nomi distinti", che contiene le autorità di certificazione accettabili del server di backend.

    alt_text

  5. Verifica se l'autorità di certificazione ottenuta al passaggio 3 corrisponde all'elenco degli emittenti o delle autorità di certificazione accettati del server di backend ottenuto nel passaggio 4. In caso di mancata corrispondenza, il processore di messaggi non invierà il certificato client al server di backend.

    Nell'esempio precedente, puoi notare che l'emittente del certificato Fogliolina del client nel Keystore dell'elaboratore di messaggi non corrisponde a nessuna delle Autorità di certificazione accettate del server di backend. Pertanto, il processore di messaggi non invia il certificato client al server di backend. Questo causa la mancata riuscita dell'handshake SSL e il server di backend invia il messaggio "Fatal alert: bad_certificate".

Risoluzione

  1. Assicurati che il certificato con l'autorità emittente/l'autorità di certificazione corrispondente all'autorità di certificazione o all'autorità di certificazione del certificato Fogliolina del client (primo certificato della catena) sia archiviato nel Truststore del server di backend.
  2. Nell'esempio descritto in questo playbook, il certificato con l'emittente "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com" è stato aggiunto all'archivio attendibilità del server di backend per risolvere il problema.

Se il problema persiste, vai alla pagina Devi raccogliere informazioni diagnostiche.

Raccogliere informazioni diagnostiche

Se il problema persiste anche dopo aver seguito le istruzioni riportate sopra, raccogli le seguenti informazioni diagnostiche. Contatta e condividili con l'assistenza Apigee Edge:

  1. Se sei un utente del cloud pubblico, fornisci le seguenti informazioni:
    1. Nome organizzazione
    2. Nome ambiente
    3. Nome proxy API
    4. Completa il comando curl per riprodurre l'errore
    5. File di traccia che mostra l'errore
    6. Pacchetti TCP/IP acquisiti sul server di backend
  2. Se sei un utente del cloud privato, fornisci le seguenti informazioni:
    1. Rilevato messaggio di errore completo
    2. Bundle del proxy API
    3. File di traccia che mostra l'errore
    4. Log del processore di messaggi /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. Pacchetti TCP/IP acquisiti sul server di backend o sul processore di messaggi.
    6. Output di Ottieni un certificato per l'API Keystore.
  3. Dettagli sulle sezioni di questo Playbook che hai provato e su eventuali altri insight che ci aiuteranno a risolvere il problema in tempi rapidi.