Errores de protocolo de enlace SSL: certificado de cliente incorrecto

Estás viendo la documentación de Apigee Edge.
Ir a la documentación de Apigee X.
info

Síntoma

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

Si tienes acceso a los registros de Message Processor, notarás el mensaje de error como Received fatal alert: bad_certificate para la solicitud a la API con errores. Este error se observa durante el proceso de protocolo de enlace SSL entre Message Processor y el servidor de backend en una configuración de 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 observes 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 siguientes son las posibles causas de este problema:

Causa Descripción Instrucciones de solución de problemas aplicables para
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 de Edge
Incompatibilidad de la autoridad certificadora La autoridad certificadora del certificado de hoja (el primer certificado de la cadena de certificados) en el almacén de claves de Message Processor no coincide con ninguna de las autoridades certificadoras aceptadas por el servidor de backend. Usuarios de la nube pública y privada de Edge

Pasos comunes de 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 se produjo 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 muestra en el siguiente seguimiento de ejemplo:

    alt_text

  4. Como puedes ver en la captura de pantalla anterior, error.cause es "Received fatal alert: bad_certificate".
  5. Si eres usuario de la nube privada, sigue las instrucciones que se indican a continuación:
    1. Para obtener el ID del mensaje de la solicitud a la API con errores, determina el valor del encabezado de error "X-Apigee.Message-ID" en la fase indicada por AX en el seguimiento.
    2. Busca este ID de mensaje en el registro de Message Processor /opt/apigee/var/log/edge-message-processor/system.log 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 más a fondo este problema, deberás capturar paquetes TCP/IP con la herramienta tcpdump.
    1. Si eres usuario de la nube privada, puedes capturar los paquetes TCP/IP en el servidor de backend o en Message Processor. Es preferible capturarlos en el servidor de backend, ya que los paquetes se desencriptan en el servidor de backend.
    2. Si eres usuario de la nube pública, captura los paquetes TCP/IP paquetes en el servidor de backend.
    3. Una vez que decidas dónde deseas capturar paquetes TCP/IP, usa el siguiente tcpdump para capturarlos.
    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 tcpdump comando.

      Si hay varias direcciones IP para el servidor de backend o Message Processor, entonces 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 con la que estés familiarizado.

Este es el análisis de los datos de paquetes TCP/IP de muestra con la herramienta Wireshark:

alt_text

  1. El mensaje n.° 4 en el tcpdump anterior muestra que Message Processor (origen) envió un mensaje "Client Hello" al servidor de backend (destino).
  2. El mensaje n.° 5 muestra que el servidor de backend confirma el mensaje Client Hello 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.° 7.
  4. Message Processor completa la verificación del certificado y confirma el mensaje ServerHello del servidor de backend en el mensaje n.° 8.
  5. Message Processor envía su certificado al servidor de backend en el mensaje n.° 9.
  6. El servidor de backend confirma la recepción del certificado de Message Processor en el mensaje n.° 11.
  7. Sin embargo, envía de inmediato una alerta fatal: certificado incorrecto a Message Processor (mensaje n.° 12). Esto indica que el certificado enviado por Message Processor era incorrecto y, por lo tanto, falló la verificación del certificado en el servidor de backend. Como resultado, falló el protocolo de enlace SSL y se cerrará la conexión.


    alt_text

  8. Ahora, veamos el mensaje n.° 9 para verificar el contenido del certificado enviado por Message Processor:


    alt_text

  9. Como puedes notar, el servidor de backend no obtuvo ningún certificado del cliente (Certificate Length: 0). Por lo tanto, el servidor de backend envía la alerta fatal: certificado incorrecto.
  10. Por lo general, esto sucede cuando el cliente, es decir, Message Processor (un proceso basado en Java):
    1. No tiene ningún certificado de cliente en su almacén de claves o
    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, Message Processor no enviará el certificado.

Analicemos cada una de estas causas por separado de la siguiente manera.

Causa: Sin certificado de cliente

Diagnóstico

Si no hay ningún certificado en el almacén de claves especificado en la sección SSL Info del extremo de destino o el servidor de destino que se usa en el extremo de destino, esa es la causa de este error.

Sigue los pasos que se indican a continuación para determinar si esta es la causa:

  1. Para 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, sigue los pasos que se indican a continuación:
    1. Obtén el nombre de referencia del almacén de claves del elemento Keystore en la sección SSLInfo del extremo de destino o 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 -> Configuraciones del entorno.

      Selecciona la pestaña Referencias y busca el nombre de referencia del almacén de claves. Anota el nombre en la columna Referencia para la referencia del almacén de claves específico. Este será el nombre del almacén de claves.


      alt_text

    4. En el ejemplo anterior, puedes notar 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 con la IU de Edge o la API de List certs for keystore.
  3. Si el almacén de claves contiene certificados, pasa a Causa: Incompatibilidad de la autoridad certificadora.
  4. Si el almacén de claves no contiene ningún certificado, ese es el motivo por el que Message Processor no envía el certificado de cliente.

Solució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: Incompatibilidad de la autoridad certificadora

Por lo general, cuando el servidor solicita al cliente que envíe su certificado, indica el conjunto de emisores o autoridades certificadoras aceptados. Si la entidad emisora o la autoridad certificadora del certificado de hoja (es decir, el primer certificado de la cadena de certificados) en el almacén de claves de Message Processor 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 los pasos que se indican a continuación para confirmar si este es el caso:

  1. API de List certs for keystore.
  2. Obtén los detalles de cada certificado obtenido en el paso 1 anterior con la API de Get cert for keystore.
  3. Anota el emisor del certificado de hoja (es decir, el primer certificado de la cadena de certificados) almacenado en el almacén de claves.

    Certificado de hoja de muestra

    {
      "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, el emisor 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 con una de las siguientes técnicas:

    Técnica n.° 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 "Acceptable Client Certificate CA names" 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 n.° 2: Verifica el paquete Certificate Request en los paquetes TCP/IP, en el que el servidor de backend solicita al cliente que envíe su certificado:

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

    alt_text

  5. Verifica si la autoridad certificadora obtenida en el paso 3 coincide con la lista de emisores o autoridades certificadoras aceptadas del servidor de backend obtenidas en el paso 4. Si hay una falta de coincidencia, Message Processor no enviará el certificado de cliente al servidor de backend.

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

Solució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 certificados de confianza del servidor de backend.
  2. En el ejemplo que se describe 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, consulta Se debe 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 el equipo de asistencia de Apigee Edge y compártela con ellos:

  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 del proxy de API
    4. Comando curl completo 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 la nube privada, proporciona la siguiente información:
    1. Mensaje de error completo observado
    2. Paquete de proxy de API
    3. Archivo de seguimiento que muestra el error
    4. Registros de Message Processor /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. Paquetes TCP/IP capturados en el servidor de backend o Message Processor
    6. Resultado de la API de Get cert for keystore.
  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