Échecs de handshake SSL – Certificat client incorrect

Vous consultez la documentation Apigee Edge.
Accédez à la documentation**Apigee X**.
info

Problème constaté

L'application cliente reçoit un code d'état HTTP de 503 avec le message "Service Unavailable" en réponse à une requête API. Dans la trace de l'interface utilisateur, vous verrez que error.cause est Received fatal alert: bad_certificate dans le flux de requêtes cibles pour la requête API défaillante.

Si vous avez accès aux journaux du processeur de messages, vous remarquerez le message d'erreur comme Received fatal alert: bad_certificate pour la requête API défaillante. Cette erreur est observée lors du processus de handshake SSL entre le processeur de messages et le serveur backend dans une configuration TLS bidirectionnelle.

Message d'erreur

L'application cliente reçoit le code de réponse suivant :

HTTP/1.1 503 Service Unavailable

Vous pouvez également observer le message d'erreur suivant :

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

Les utilisateurs du cloud privé verront l'erreur suivante pour la requête API spécifique dans les journaux du processeur de messages /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

Causes possibles

Les causes possibles de ce problème sont les suivantes :

Cause Description Instructions de dépannage applicables
Aucun certificat client Le keystore utilisé dans le point de terminaison cible du serveur cible ne contient aucun certificat client. Utilisateurs du cloud privé et public Edge
Incompatibilité de l'autorité de certification L'autorité de certification du certificat final (le premier certificat de la chaîne de certificats) dans le keystore du processeur de messages ne correspond à aucune des autorités de certification acceptées par le serveur backend. Utilisateurs du cloud privé et public Edge

Étapes de diagnostic courantes

  1. Activez le suivi dans l'interface utilisateur Edge, effectuez l'appel d'API et reproduisez le problème.
  2. Dans les résultats de la trace de l'interface utilisateur, parcourez chaque phase et déterminez où l'erreur s'est produite. L'erreur s'est produite dans le flux de requêtes cibles.
  3. Examinez le flux qui affiche l'erreur. Vous devriez l'observer comme indiqué dans l'exemple de trace ci-dessous :

    alt_text

  4. Comme vous pouvez le voir dans la capture d'écran ci-dessus, error.cause est "Received fatal alert: bad_certificate".
  5. Si vous êtes un utilisateur du cloud privé, suivez les instructions ci-dessous :
    1. Vous pouvez obtenir l'ID de message pour la requête API défaillante en déterminant la valeur de l'en-tête d'erreur "X-Apigee.Message-ID" dans la phase indiquée par AX dans la trace.
    2. Recherchez cet ID de message dans le journal du processeur de messages /opt/apigee/var/log/edge-message-processor/system.log et déterminez si vous pouvez trouver d'autres informations sur l'erreur :
      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]

      Le journal du processeur de messages contenait une trace de la pile pour l'erreur Received fatal alert: bad_certificate, mais ne contient aucune autre information indiquant la cause de ce problème.

  6. Pour examiner ce problème plus en détail, vous devez capturer les paquets TCP/IP à l'aide de tcpdump l'outil.
    1. Si vous êtes un utilisateur du cloud privé, vous pouvez capturer les paquets TCP/IP sur le serveur backend ou le processeur de messages. Il est préférable de les capturer sur le serveur backend, car les paquets y sont déchiffrés sur le serveur backend.
    2. Si vous êtes un utilisateur du cloud public, capturez les paquets TCP/IP sur le serveur backend.
    3. Une fois que vous avez décidé où vous souhaitez capturer les paquets TCP/IP, utilisez la commande tcpdump ci-dessous pour les capturer.
    4. tcpdump -i any -s 0 host <IP address> -w <File name>

      Si vous récupérez les paquets TCP/IP sur le processeur de messages, utilisez l' adresse IP publique du serveur backend dans la tcpdump commande.

      S'il existe plusieurs adresses IP pour le serveur backend/processeur de messages, alors vous devez utiliser une autre commande tcpdump. Pour en savoir plus sur cet outil et sur d'autres variantes de cette commande, consultez tcpdump.

  7. Analysez les paquets TCP/IP à l'aide de l'outil Wireshark ou d'un outil similaire que vous connaissez.

Voici l'analyse des exemples de données de paquets TCP/IP à l'aide de l'outil Wireshark :

alt_text

  1. Le message n° 4 dans le tcpdump ci-dessus indique que le processeur de messages (source) a envoyé un message "Client Hello" au serveur backend (destination).
  2. Le message n° 5 indique que le serveur backend accuse réception du message Client Hello du processeur de messages.
  3. Le serveur backend envoie le message "Server Hello" avec son certificat, et demande ensuite au client d'envoyer son certificat dans le message n° 7.
  4. Le processeur de messages termine la validation du certificat et accuse réception du message ServerHello du serveur backend dans le message n° 8.
  5. Le processeur de messages envoie son certificat au serveur backend dans le message n° 9.
  6. Le serveur backend accuse réception du certificat du processeur de messages dans le message n° 11.
  7. Toutefois, il envoie immédiatement une alerte fatale : mauvais certificat au processeur de messages (message n° 12). Cela indique que le certificat envoyé par le processeur de messages était incorrect et que la validation du certificat a donc échoué sur le serveur backend. Par conséquent, le handshake SSL a échoué et la connexion sera fermée.


    alt_text

  8. Examinons maintenant le message n° 9 pour vérifier le contenu du certificat envoyé par le processeur de messages :


    alt_text

  9. Comme vous pouvez le constater, le serveur backend n'a reçu aucun certificat du client (Certificate Length: 0). Par conséquent, le serveur backend envoie l'alerte fatale : mauvais certificat.
  10. En règle générale, cela se produit lorsque le client, c'est-à-dire le processeur de messages (un processus basé sur Java) :
    1. ne possède aucun certificat client dans son keystore ; ou
    2. ne parvient pas à envoyer de certificat client. Cela peut se produire s'il ne trouve pas un certificat émis par l'une des autorités de certification acceptables du serveur backend. Autrement dit, si l'autorité de certification du certificat final du client (c'est-à-dire le premier certificat de la chaîne) ne correspond à aucune des autorités de certification acceptables du serveur backend, le processeur de messages n'enverra pas le certificat.

Examinons chacune de ces causes séparément, comme suit.

Cause : Aucun certificat client

Diagnostic

Si aucun certificat n'est présent dans le keystore spécifié dans la section "SSL Info" du point de terminaison cible ou du serveur cible utilisé dans le point de terminaison cible, c'est la cause de cette erreur.

Pour déterminer si tel est le cas, procédez comme suit :

  1. Déterminez le keystore utilisé dans le point de terminaison cible ou le serveur cible pour le proxy d'API spécifique en procédant comme suit :
    1. Obtenez le nom de référence du keystore à partir de l'élément Keystore dans la section SSLInfo du point de terminaison cible ou du serveur cible.

      Examinons un exemple de section SSLInfo dans une configuration de point de terminaison cible :

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. Dans l'exemple ci-dessus, le nom de référence du keystore est "myKeystoreRef".
    3. Accédez à l'interface utilisateur Edge et sélectionnez API Proxies -> Environment Configurations (Proxys d'API -> Configurations d'environnement).

      Sélectionnez l'onglet Références et recherchez le nom de référence du keystore. Notez le nom dans la colonne Référence pour la référence de keystore spécifique. Il s'agit du nom de votre keystore.


      alt_text

    4. Dans l'exemple ci-dessus, vous pouvez constater que myKeystoreRef fait référence à "myKeystore". Par conséquent, le nom du keystore est myKeystore.
  2. Vérifiez si ce keystore contient le certificat à l'aide de l'interface utilisateur Edge ou de la List certs for keystore API.
  3. Si le keystore contient des certificats, passez à la section Cause : Incompatibilité de l'autorité de certification.
  4. Si le keystore ne contient aucun certificat, c'est la raison pour laquelle le certificat client n'est pas envoyé par le processeur de messages.

Solution

  1. Assurez-vous que la chaîne de certificats client appropriée et complète est importée dans le keystore spécifique du processeur de messages.

Cause : Incompatibilité de l'autorité de certification

En règle générale, lorsque le serveur demande au client d'envoyer son certificat, il indique l'ensemble des émetteurs ou des autorités de certification acceptés. Si l'émetteur/l'autorité de certification du certificat final (c'est-à-dire le premier certificat de la chaîne de certificats) dans le keystore du processeur de messages ne correspond à aucune des autorités de certification acceptées par le serveur backend, le processeur de messages (qui est un processus basé sur Java) n'enverra pas le certificat au serveur backend.

Pour vérifier si tel est le cas, procédez comme suit :

  1. Répertoriez les certificats pour l'API keystore.
  2. Obtenez les détails de chaque certificat obtenu à l'étape 1 ci-dessus à l'aide de l' API Get cert for keystore.
  3. Notez l'émetteur du certificat final (c'est-à-dire le premier certificat de la chaîne de certificats) stocké dans le keystore.

    Exemple de certificat final

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

    Dans l'exemple ci-dessus, l'émetteur/l'autorité de certification est "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com"

  4. Déterminez la liste des émetteurs ou des autorités de certification acceptés par le serveur backend à l'aide de l'une des techniques suivantes :

    Technique 1 : Utilisez la commande openssl ci-dessous :

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

    Reportez-vous à la section intitulée "Acceptable Client Certificate CA names" (Noms d'autorités de certification de certificats clients acceptables) dans le résultat de cette commande, comme indiqué ci-dessous :

    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

    Technique 2 : Vérifiez le paquet Certificate Request dans les paquets TCP/IP, où le serveur backend demande au client d'envoyer son certificat :

    Dans les exemples de paquets TCP/IP ci-dessus, le paquet Certificate Request est le message n° 7. Reportez-vous à la section "Distinguished Names" (Noms uniques), qui contient les autorités de certification acceptables du serveur backend.

    alt_text

  5. Vérifiez si l'autorité de certification obtenue à l'étape 3 correspond à la liste des émetteurs ou des autorités de certification acceptés par le serveur backend obtenue à l'étape 4. En cas d'incompatibilité, le processeur de messages n'enverra pas le certificat client au serveur backend.

    Dans l'exemple ci-dessus, vous pouvez constater que l'émetteur du certificat final du client dans le keystore du processeur de messages ne correspond à aucune des autorités de certification acceptées du serveur backend. Par conséquent, le processeur de messages n'envoie pas le certificat client au serveur backend. Le handshake SSL échoue et le serveur backend envoie le message "Fatal alert: bad_certificate".

Solution

  1. Assurez-vous que le certificat dont l'émetteur/l'autorité de certification correspond à l'émetteur/l'autorité de certification du certificat final du client (premier certificat de la chaîne) est stocké dans le truststore du serveur backend.
  2. Dans l'exemple décrit dans ce guide, le certificat dont l'émetteur est "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com" a été ajouté au truststore du serveur backend pour résoudre le problème.

Si le problème persiste, consultez la page Vous devez collecter des informations de diagnostic.

Vous devez collecter des informations de diagnostic

Si le problème persiste, même après avoir suivi les instructions ci-dessus, veuillez collecter les informations de diagnostic suivantes. Contactez l'assistance Apigee Edge et partagez-les avec elle : :

  1. Si vous êtes un utilisateur du cloud public, fournissez les informations suivantes :
    1. Nom de l'organisation
    2. Nom de l'environnement
    3. Nom du proxy d'API
    4. Commande curl complète pour reproduire l'erreur
    5. Fichier de suivi indiquant l'erreur
    6. Paquets TCP/IP capturés sur le serveur backend
  2. Si vous êtes un utilisateur du cloud privé, fournissez les informations suivantes :
    1. Message d'erreur complet observé
    2. Bundle de proxy d'API
    3. Fichier de suivi indiquant l'erreur
    4. Journaux du processeur de messages /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. Paquets TCP/IP capturés sur le serveur backend ou le processeur de messages.
    6. Résultat de l'API Get cert for keystore.
  3. Détails sur les sections de ce guide que vous avez essayées et toute autre information qui nous aidera à accélérer la résolution de ce problème.