Errores de protocolo de enlace SSL: certificado de cliente incorrecto

Estás consultando la documentación de Apigee Edge.
Consulta la documentación de Apigee X.
Información

Síntoma

La aplicación cliente recibe un código de estado HTTP de 503 con el mensaje "Service AVAILABLE" como respuesta a una solicitud a la API. En el seguimiento de la IU, observarás que error.cause es Received fatal alert: bad_certificate en el flujo de solicitud de destino de la solicitud a la API que falló.

Si tienes acceso a los registros de Message Processor, verás el mensaje de error como Received fatal alert: bad_certificate para la solicitud a la API que falla. Este error se observa durante el proceso de protocolo de enlace SSL entre el procesador de mensajes y el servidor de backend en una configuración TLS bidireccional.

Mensaje de error

La aplicación cliente obtiene el siguiente código de respuesta:

HTTP/1.1 503 Service Unavailable

Además, es posible que veas el siguiente mensaje de error:

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

Los usuarios de la nube privada verán el siguiente error para la solicitud a la API específica en los registros de Message Processor /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

Causas posibles

Las posibles causas de este problema son las siguientes:

Causa Descripción Instrucciones de solución de problemas aplicables a
Sin certificado de cliente El almacén de claves que se usa en el extremo de destino del servidor de destino no tiene ningún certificado de cliente. Usuarios de la nube pública y privada perimetral
Discrepancias en la autoridad certificadora La autoridad certificadora del certificado de entidad final (el primer certificado de la cadena de certificados) del almacén de claves del procesador de mensajes no coincide con ninguna de las autoridades certificadoras que acepta el servidor de backend. Usuarios de la nube pública y privada perimetral

Pasos comunes del diagnóstico

  1. Habilita el seguimiento en la IU de Edge, realiza la llamada a la API y reproduce el problema.
  2. En los resultados del seguimiento de la IU, navega por cada fase y determina dónde ocurrió el error. El error se habría producido en el flujo de solicitud de destino.
  3. Examina el flujo que muestra el error. Deberías observar el error como se indica en el siguiente seguimiento de ejemplo:

    alt_text

  4. Como se ve en la captura de pantalla anterior, el valor error.cause es error.cause .
  5. Si eres un usuario de la nube privada, sigue estas instrucciones:
    1. Puedes obtener el ID del mensaje de la solicitud a la API que falla si determinas el valor del encabezado de error "X-Apigee.Message-ID" en la fase que indica AX en el seguimiento.
    2. Busca este ID de mensaje en el registro /opt/apigee/var/log/edge-message-processor/system.log de Message Processor y determina si puedes encontrar más información sobre el error:
      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]
      

      El registro de Message Processor tenía un seguimiento de pila para el error Received fatal alert: bad_certificate, pero no tiene más información que indique la causa de este problema.

  6. Para investigar este problema con más detalle, deberás capturar paquetes TCP/IP con la herramienta tcpdump.
    1. Si eres un usuario de la nube privada, puedes capturar los paquetes de TCP/IP en el servidor de backend o en el procesador de mensajes. Preferentemente, captúralos en el servidor de backend a medida que los paquetes se desencriptan en el servidor de backend.
    2. Si eres un usuario de la nube pública, captura los paquetes TCP/IP en el servidor de backend.
    3. Una vez que decidas dónde quieres capturar los paquetes de TCP/IP, usa el siguiente comando tcpdump para capturar los paquetes de TCP/IP.
    4. tcpdump -i any -s 0 host <IP address> -w <File name>

      Si tomas los paquetes TCP/IP en Message Processor, usa la dirección IP pública del servidor de backend en el comando tcpdump.

      Si hay varias direcciones IP para el servidor de backend o el procesador de mensajes, debes usar un comando tcpdump diferente. Consulta tcpdump para obtener más información sobre esta herramienta y otras variantes de este comando.

  7. Analiza los paquetes TCP/IP con la herramienta Wireshark o una herramienta similar que con la que conozcas.

A continuación, se muestra el análisis de datos de paquetes TCP/IP de muestra con la herramienta Wireshark:

alt_text

  1. El mensaje n.o 4 del tcpdump anterior muestra que Message Processor (fuente) envió un mensaje “Client Hello” al servidor de backend (destino).
  2. El mensaje 5 muestra que el servidor de backend confirma el mensaje de Hello del cliente de Message Processor.
  3. El servidor de backend envía el mensaje “Server Hello” junto con su certificado y, luego, solicita al cliente que envíe su certificado en el mensaje núm. 7.
  4. El procesador de mensajes completa la verificación del certificado y confirma el mensaje ServerHello del servidor de backend en el mensaje n.o 8.
  5. Message Processor envía su certificado al servidor de backend en el mensaje n.o 9.
  6. El servidor de backend acusa recibo del certificado del procesador de mensajes en el mensaje 11.
  7. Sin embargo, envía inmediatamente una alerta irrecuperable: certificado incorrecto al procesador de mensajes (mensaje n.o 12). Esto indica que el certificado enviado por Message Processor era incorrecto y, por lo tanto, la verificación del certificado falló en el servidor de backend. Como resultado, el protocolo de enlace SSL falló y la conexión se cerrará.


    alt_text

  8. Veamos ahora el mensaje 9 para verificar el contenido del certificado que envió Message Processor:


    alt_text

  9. Como puedes observar, el servidor de backend no recibió ningún certificado del cliente (Longitud del certificado: 0). Por lo tanto, el servidor de backend envía la alerta Fatal Alert: Bad Certificate.
  10. Por lo general, esto sucede cuando el cliente, es decir, Message Processor (un proceso basado en Java):
    1. No tenga ningún Certificado de cliente en su almacén de claves.
    2. No puede enviar un certificado de cliente. Esto puede suceder si no puede encontrar un certificado emitido por una de las autoridades certificadoras aceptables del servidor de backend. Es decir, si la autoridad certificadora del certificado de hoja del cliente (es decir, el primer certificado de la cadena) no coincide con ninguna de las autoridades certificadoras aceptables del servidor de backend, el procesador de mensajes no enviará el certificado.

Veamos cada una de estas causas por separado, de la siguiente manera.

Causa: no hay certificado de cliente.

Diagnóstico

Si no hay ningún certificado en el almacén de claves especificado en la sección de información de SSL del extremo de destino o en el servidor de destino utilizado en el extremo de destino, entonces esa es la causa del error.

Sigue estos pasos para determinar si esta es la causa:

  1. Sigue estos pasos a fin de determinar el almacén de claves que se usa en el extremo de destino o el servidor de destino para el proxy de API específico:
    1. Obtén el nombre de referencia del almacén de claves del elemento Keystore en la sección SSLInfo en el extremo de destino o en el servidor de destino.

      Veamos una sección SSLInfo de muestra en una configuración de extremo de destino:

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. En el ejemplo anterior, el nombre de referencia del almacén de claves es "myKeystoreRef".
    3. Ve a la IU de Edge y selecciona Proxies de API -> Configuración del entorno.

      Selecciona la pestaña References y busca el nombre de referencia del almacén de claves. Anota el nombre en la columna Reference para la referencia específica del almacén de claves. Este será el nombre de tu almacén de claves.


      alt_text

    4. En el ejemplo anterior, puedes observar que myKeystoreRef tiene la referencia a "myKeystore". Por lo tanto, el nombre del almacén de claves es myKeystore.
  2. Verifica si este almacén de claves contiene el certificado mediante la IU de Edge o la lista de certificados para la API del almacén de claves.
  3. Si el almacén de claves contiene certificados, ve a Causa: Discrepancia en la autoridad certificadora.
  4. Si el almacén de claves no contiene ningún certificado, ese es el motivo por el que el procesador de mensajes no envía el certificado de cliente.

Resolución

  1. Asegúrate de que la cadena de certificados de cliente adecuada y completa se suba al almacén de claves específico en Message Processor.

Causa: no coincide con la autoridad certificadora

Por lo general, cuando el servidor solicita al cliente que envíe su certificado, indica el conjunto de entidades emisoras o entidades emisoras aceptadas. Si la autoridad certificadora o emisora del certificado de entidad final (es decir, el primer certificado de la cadena de certificados) del almacén de claves del procesador de mensajes no coincide con ninguna de las autoridades certificadoras aceptadas por el servidor de backend, Message Processor (que es un proceso basado en Java) no enviará el certificado al servidor de backend.

Sigue estos pasos para confirmar si este es el caso:

  1. Enumera certificados para la API del almacén de claves.
  2. Obtén los detalles de cada certificado obtenido en el paso 1 anterior con la API de obtención del certificado para la API del almacén de claves.
  3. Anota la entidad emisora del certificado de entidad final (es decir, el primer certificado de la cadena de certificados) almacenado en el almacén de claves.

    Ejemplo de certificado de Hojas

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

    En el ejemplo anterior, la entidad emisora o la autoridad certificadora es "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com"

  4. Determina la lista aceptada de emisores o autoridades certificadoras del servidor de backend utilizando una de las siguientes técnicas:

    Técnica n.o 1: Usa el siguiente comando openssl:

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

    Consulta la sección titulada "Nombres de CA del certificado de cliente aceptable" en el resultado de este comando, como se muestra a continuación:

    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
    

    Técnica 2: Verifica el paquete Certificate Request en los paquetes TCP/IP, en los que el servidor de backend solicita al cliente que envíe su certificado:

    En los paquetes de TCP/IP de muestra anteriores, el paquete Certificate Request es el mensaje n.o 7. Consulta la sección "Nombres distinguidos", que contiene las autoridades certificadoras aceptables del servidor de backend.

    alt_text

  5. Verifica si la autoridad certificadora que se obtuvo en el paso 3 coincide con la lista de entidades emisoras o autoridades certificadoras aceptadas del servidor de backend que se obtuvieron en el paso 4. Si no coinciden, Message Processor no enviará el certificado de cliente al servidor de backend.

    En el ejemplo anterior, puedes observar que la entidad emisora del Certificado de hoja del cliente en el almacén de claves del procesador de mensajes no coincide con ninguna de las autoridades certificadas aceptadas del servidor de backend. Por lo tanto, Message Processor no envía el certificado de cliente al servidor de backend. Esto hace que el protocolo de enlace SSL falle y el servidor de backend envíe el mensaje "Fatal alert: bad_certificate".

Resolución

  1. Asegúrate de que el certificado con la entidad emisora o la autoridad certificadora que coincida con la entidad emisora o la autoridad certificadora del certificado de hoja del cliente (primer certificado de la cadena) se almacene en el almacén de confianza del servidor de backend.
  2. En el ejemplo descrito en esta guía, se agregó el certificado con el emisor "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com" al almacén de confianza del servidor de backend para resolver el problema.

Si el problema persiste, ve a Debes recopilar información de diagnóstico.

Se debe recopilar información de diagnóstico

Si el problema persiste, incluso después de seguir las instrucciones anteriores, recopila la siguiente información de diagnóstico. Comunícate con ellos y compártelos en el equipo de asistencia de Apigee Edge:

  1. Si eres usuario de la nube pública, proporciona la siguiente información:
    1. Nombre de la organización
    2. Nombre del entorno
    3. Nombre de proxy de API
    4. Completa el comando curl para reproducir el error
    5. Archivo de seguimiento que muestra el error
    6. Paquetes TCP/IP capturados en el servidor de backend
  2. Si eres usuario de una nube privada, proporciona la siguiente información:
    1. Se observó un mensaje de error completo
    2. Paquete de proxy de API
    3. Archivo de seguimiento que muestra el error
    4. Registros del procesador de mensajes /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. Paquetes TCP/IP capturados en el servidor de backend o en el procesador de mensajes
    6. Resultado de Get cert for keystore API.
  3. Detalles sobre las secciones de esta guía que probaste y cualquier otra información que nos ayude a acelerar la resolución de este problema.