Falhas no handshake de SSL: certificado de cliente inválido

Você está vendo a documentação do Apigee Edge.
Acesse a documentação da Apigee X.
informações

Sintoma

O aplicativo cliente recebe um código de status HTTP 503 com a mensagem "Serviço indisponível" como resposta a uma solicitação de API. No rastro da IU, você observará que error.cause é Received fatal alert: bad_certificate no fluxo de solicitação de destino para a solicitação de API com falha.

Se você tiver acesso aos registros do processador de mensagens, verá a mensagem de erro como Received fatal alert: bad_certificate para a solicitação de API com falha. Esse erro é observado durante o processo de handshake de SSL entre o processador de mensagens e o servidor de back-end em uma configuração de TLS bidirecional.

Mensagem de erro

O aplicativo cliente recebe este código de resposta:

HTTP/1.1 503 Service Unavailable

Além disso, talvez você veja a seguinte mensagem de erro:

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

Os usuários da nuvem privada verão o seguinte erro para a solicitação de API específica nos registros /opt/apigee/var/log/edge-message-processor/system.log do processador de mensagens:

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 possíveis

As possíveis causas desse problema são as seguintes:

Causa Descrição Instruções de solução de problemas aplicáveis a
Nenhum certificado do cliente O keystore usado no endpoint de destino do servidor de destino não tem nenhum certificado do cliente. Usuários de nuvem privada e pública de borda
Incompatibilidade entre a autoridade de certificação A autoridade certificadora do certificado folha (o primeiro certificado na cadeia de certificados) no keystore do processador de mensagens não corresponde a nenhuma das autoridades de certificação aceitas pelo servidor de back-end. Usuários de nuvem privada e pública de borda

Etapas comuns de diagnóstico

  1. Ativar o rastreamento na interface do Edge, fazer a chamada de API e reproduzir o problema.
  2. Nos resultados do rastreamento da interface, navegue por cada fase e determine onde o erro ocorreu. O erro teria ocorrido no fluxo de solicitações de segmentação.
  3. Examine o fluxo que mostra o erro. Observe o erro conforme mostrado no rastro de exemplo abaixo:

    alt_text

  4. Como você vê na captura de tela acima, o error.cause é error.cause .
  5. Se você for um usuário da nuvem privada, siga as instruções abaixo:
    1. Você pode ver o ID da mensagem para a solicitação de API com falha determinando o valor do cabeçalho de erro "X-Apigee.Message-ID" na fase indicada pelo AX no rastro.
    2. Pesquise esse ID de mensagem no registro /opt/apigee/var/log/edge-message-processor/system.log do processador de mensagens e determine se é possível encontrar mais informações sobre o erro:
      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]
      

      O registro do processador de mensagens tinha um stack trace para o erro Received fatal alert: bad_certificate, mas não tem mais informações que indicam a causa desse problema.

  6. Para investigar esse problema mais a fundo, você precisará capturar pacotes TCP/IP usando a ferramenta tcpdump.
    1. Se você for um usuário da nuvem privada, poderá capturar os pacotes TCP/IP no servidor de back-end ou no processador de mensagens. De preferência, capture-os no servidor de back-end à medida que os pacotes são descriptografados no servidor de back-end.
    2. Se você for um usuário da nuvem pública, capture os pacotes TCP/IP no servidor de back-end.
    3. Depois de decidir onde você quer capturar os pacotes TCP/IP, use o comando tcpdump abaixo para capturar pacotes TCP/IP.
    4. tcpdump -i any -s 0 host <IP address> -w <File name>

      Se você estiver recebendo os pacotes TCP/IP no processador de mensagens, use o endereço IP público do servidor de back-end no comando tcpdump.

      Se houver vários endereços IP para o servidor de back-end/processador de mensagens, será necessário usar um comando tcpdump diferente. Consulte tcpdump para mais informações sobre essa ferramenta e outras variantes desse comando.

  7. Analise os pacotes TCP/IP usando a ferramenta Wireshark ou uma ferramenta similar que você conheça.

Veja a seguir a análise de exemplos de dados de pacotes TCP/IP usando a ferramenta Wireshark:

alt_text

  1. A mensagem 4 no tcpdump acima mostra que o processador de mensagens (origem) enviou uma mensagem "Client Hello" para o servidor de back-end (destino).
  2. A mensagem 5 mostra que o servidor de back-end reconhece a mensagem Client Hello do processador de mensagens.
  3. O servidor de back-end envia a mensagem "Server Hello" com o certificado e solicita que o cliente envie o certificado na mensagem 7.
  4. O processador de mensagens conclui a verificação do certificado e confirma a mensagem ServerHello do servidor de back-end na mensagem 8.
  5. O processador de mensagens envia o certificado para o servidor de back-end na Mensagem 9.
  6. O servidor de back-end confirma o recebimento do certificado do processador de mensagens na mensagem 11.
  7. No entanto, ele envia imediatamente um Alerta fatal: certificado inválido para o processador de mensagens (mensagem no 12). Isso indica que o certificado enviado pelo processador de mensagens era inválido e, consequentemente, a verificação do certificado falhou no servidor de back-end. Como resultado, o handshake de SSL falhou, e a conexão será encerrada.


    alt_text

  8. Vamos conferir agora a Mensagem 9 para verificar o conteúdo do certificado enviado pelo processador de mensagens:


    alt_text

  9. Como é possível notar, o servidor de back-end não recebeu nenhum certificado do cliente (Comprimento do certificado: 0). Portanto, o servidor de back-end envia o alerta fatal: certificado inválido.
  10. Normalmente, isso acontece quando o cliente, ou seja, o processador de mensagens (um processo baseado em Java):
    1. Não tiver nenhum certificado do cliente no keystore ou
    2. Não foi possível enviar um certificado do cliente. Isso poderá acontecer se ele não encontrar um certificado emitido por uma das autoridades de certificação aceitáveis do servidor de back-end. Ou seja, se a autoridade de certificação do certificado de folha do cliente (ou seja, o primeiro certificado na cadeia) não corresponder a nenhuma das autoridades de certificação aceitáveis do servidor de back-end, o processador de mensagens não enviará o certificado.

Vamos analisar cada uma dessas causas separadamente, da seguinte forma:

Causa: nenhum certificado do cliente

Diagnóstico

Se não houver nenhum certificado no keystore especificado na seção de informações de SSL do endpoint de destino ou no servidor de destino usado no endpoint de destino, essa será a causa do erro.

Siga as etapas abaixo para determinar se essa é a causa:

  1. Siga as etapas abaixo para determinar o keystore que está sendo usado no endpoint ou no servidor de destino do proxy de API específico:
    1. Consiga o nome de referência do Keystore do elemento Keystore na seção SSLInfo no endpoint ou no servidor de destino.

      Vejamos um exemplo de seção SSLInfo em uma configuração de endpoint de destino:

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. No exemplo acima, o nome de referência do Keystore é myKeystoreRef.
    3. Acesse a interface do Edge e selecione API Proxies -> Environment Configurations.

      Selecione a guia References e procure o nome de referência do Keystore. Anote o nome na coluna Reference da referência específica do Keystore. Este será o nome do seu Keystore.


      alt_text

    4. No exemplo acima, é possível notar que myKeystoreRef tem a referência a "myKeystore". Portanto, o nome do Keystore é myKeystore.
  2. Verifique se esse Keystore contém o certificado usando a IU do Edge ou a API List certs for keystore.
  3. Se o Keystore tiver certificado(s), siga para Causa: incompatibilidade de autoridade de certificação.
  4. Se o keystore não tiver nenhum certificado, esse é o motivo pelo qual o certificado do cliente não é enviado pelo processador de mensagens.

Resolução

  1. Verifique se a cadeia de certificados do cliente correta e completa foi enviada para o keystore específico no processador de mensagens.

Causa: incompatibilidade de autoridade de certificação

Geralmente, quando o servidor solicita que o cliente envie o certificado, ele indica o conjunto de emissores ou autoridades de certificação aceitos. Se o emissor/autoridade de certificação do certificado de folha (ou seja, o primeiro certificado na cadeia de certificados) no keystore do processador de mensagens não corresponder a nenhuma das autoridades de certificação aceitas pelo servidor de back-end, o processador de mensagens (que é um processo baseado em Java) não enviará o certificado para o servidor de back-end.

Siga as etapas abaixo para confirmar se esse é o caso:

  1. Liste certificados para a API keystore
  2. Consulte os detalhes de cada certificado recebido na etapa 1 usando a API Get cert for keystore.
  3. Anote o emissor do certificado secundário (ou seja, o primeiro da cadeia de certificados) armazenado no Keystore.

    Exemplo de certificado de folha

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

    No exemplo acima, o emissor/Autoridade de certificação é "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com".

  4. Determine a lista aceita de emissores ou autoridades de certificação do servidor de back-end usando uma destas técnicas:

    Técnica no 1: use o comando openssl abaixo:

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

    Consulte a seção "Nomes de CA de certificado de cliente aceitáveis" na saída desse comando, conforme mostrado abaixo:

    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 no 2: verifique o pacote Certificate Request nos pacotes TCP/IP, em que o servidor de back-end solicita que o cliente envie o certificado:

    No exemplo de pacotes TCP/IP mostrado acima, o pacote Certificate Request é a mensagem no 7. Consulte a seção "Nomes diferenciados", que contém as autoridades de certificação aceitáveis do servidor de back-end.

    alt_text

  5. Verifique se a autoridade certificadora recebida na etapa 3 corresponde à lista de emissores ou autoridades de certificação aceitos do servidor de back-end da etapa 4. Se houver incompatibilidade, o processador de mensagens não enviará o certificado do cliente para o servidor de back-end.

    No exemplo acima, é possível observar que o emissor do certificado de folha do cliente no keystore do processador de mensagens não corresponde a nenhuma das autoridades de certificação aceitas do servidor de back-end. Portanto, o processador de mensagens não envia o certificado do cliente para o servidor de back-end. Isso faz com que o handshake de SSL falhe e o servidor de back-end envie a mensagem "Fatal alert: bad_certificate".

Resolução

  1. Verifique se o certificado com o emissor/autoridade de certificação que corresponde ao emissor/autoridade de certificação do certificado de folha do cliente (primeiro certificado na cadeia) está armazenado no Truststore do servidor de back-end.
  2. No exemplo descrito neste manual, o certificado com o emissor "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com" foi adicionado ao Truststore do servidor de back-end para resolver o problema.

Se o problema persistir, acesse Precisa coletar informações de diagnóstico.

É necessário coletar informações de diagnóstico

Se o problema persistir mesmo depois de seguir as instruções acima, colete as seguintes informações de diagnóstico. Entre em contato e compartilhe com o suporte do Apigee Edge:

  1. Se você for usuário da nuvem pública, forneça as seguintes informações:
    1. Nome da organização
    2. Nome do ambiente
    3. Nome de proxy da API
    4. Concluir o comando curl para reproduzir o erro
    5. Arquivo de rastreamento mostrando o erro
    6. Pacotes TCP/IP capturados no servidor de back-end
  2. Se você é um usuário da nuvem privada, forneça as seguintes informações:
    1. Mensagem de erro concluída observada
    2. Pacote de proxy de API
    3. Arquivo de rastreamento mostrando o erro
    4. Registros do processador de mensagens /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. Pacotes TCP/IP capturados no servidor de back-end ou no processador de mensagens.
    6. Saída de Get cert for keystore API.
  3. Detalhes sobre quais seções deste manual você experimentou e quaisquer outros insights que nos ajudarão a agilizar a resolução desse problema.