Como soluciono problemas de erros HTTP 403 Forbidden de um nome de domínio personalizado do API Gateway que requer TLS mútuo?

8 minuto de leitura
0

Meu nome de domínio personalizado do Amazon API Gateway que utiliza autenticação Transport Layer Security (TLS) mútua ativada retorna erros HTTP 403 Forbidden. Não sei por que isso está acontecendo.

Breve descrição

Observação: o API Gateway pode retornar erros 403 Forbidden por vários motivos. Este artigo aborda somente erros 403 Forbidden relacionados ao TLS mútuo. Para obter informações sobre como solucionar problemas de outros tipos de erros 403 Forbidden, consulte Como solucionar problemas de erros HTTP 403 Forbidden do API Gateway?

Para invocar uma API do API Gateway usando um nome de domínio personalizado que requer TLS mútuo, os clientes devem apresentar um certificado confiável na solicitação da API. Quando um cliente tenta invocar a API, o API Gateway procura o emissor do certificado do cliente em sua truststore.

As condições a seguir fazem com que o API Gateway falhe na conexão TLS e retorne um código de status 403:

  • O API Gateway não consegue encontrar o emissor do certificado do cliente em sua truststore.
  • O certificado do cliente está usando um algoritmo de assinatura inseguro.
  • O certificado do cliente é autoassinado.

Se o log do Amazon CloudWatch estiver ativado para sua API, uma mensagem de erro indicando a causa do erro será exibida nos logs de execução.

Importante: se a solicitação da API não produzir CloudWatch Logs depois que o log for ativado, o erro 403 Forbidden não estará relacionado ao TLS mútuo.

Para APIs REST

Se você configurar o log do Amazon CloudWatch para a API REST, uma das seguintes mensagens de erro também será exibida nos logs de execução:

  • Acesso negado. Motivo: não foi possível encontrar o emissor para o certificado
  • Acesso negado. Motivo: o certificado do cliente usa um algoritmo de assinatura inseguro
  • Acesso negado. Motivo: certificado autoassinado

Para operações de API HTTP

As APIs HTTP não oferecem suporte a logs de execução. Para solucionar problemas de erros 403 Forbidden retornados por um nome de domínio personalizado que requer TLS mútuo e invoca uma API HTTP, é necessário fazer o seguinte:

1.    Crie um novo mapeamento de API para seu nome de domínio personalizado que invoca uma API REST apenas para fins de teste.
Observação: se você não tiver uma API REST disponível para teste, use a API REST PetStore de exemplo. Em seguida, implante a API de exemplo em um novo estágio e crie um novo mapeamento de API que use seu nome de domínio personalizado.

2.    Siga as instruções na seção Resolução deste artigo usando o novo mapeamento de API que você criou para a API REST.

3.    Depois que o erro for identificado e resolvido, redirecione o mapeamento da API do seu nome de domínio personalizado de volta para a API HTTP.

Resolução

Confirme a causa do erro

1.   Ative o registro em log do CloudWatch para sua API REST. Em seguida, configure o registro em log de execuções e acessos.

Ao configurar o log de acesso para esse caso de uso, é uma prática recomendada usar as variáveis $context a seguir. Essas variáveis têm duas funções:

  • Informar ao API Gateway para gerar CloudWatch Logs quando o nome de domínio personalizado que requer TLS mútuo retorna um erro 403 Forbidden.
  • Facilitar a identificação do chamador que tentou invocar sua operação de API quando você revisar o CloudWatch Logs.

Variáveis $context recomendadas para o log de acesso do CloudWatch que permitirão ao API Gateway gerar logs de execução e acesso

{ "accountId":"$context.accountId", "apiId":"$context.apiId", "domainName":"$context.domainName", "domainPrefix":"$context.domainPrefix", "error.message":"$context.error.message", "error.responseType":"$context.error.responseType", "extendedRequestId":"$context.extendedRequestId", "httpMethod":"$context.httpMethod", "identity.sourceIp":"$context.identity.sourceIp", "identity.clientCert.clientCertPem":"$context.identity.clientCert.clientCertPem", "identity.clientCert.subjectDN":"$context.identity.clientCert.subjectDN", "identity.clientCert.issuerDN":"$context.identity.clientCert.issuerDN", "identity.clientCert.serialNumber":"$context.identity.clientCert.serialNumber", "identity.clientCert.validity.notBefore":"$context.identity.clientCert.validity.notBefore", "identity.clientCert.validity.notAfter":"$context.identity.clientCert.validity.notAfter", "identity.userAgent":"$context.identity.userAgent", "path":"$context.path", "protocol":"$context.protocol", "requestId":"$context.requestId", "requestTime":"$context.requestTime", "requestTimeEpoch":"$context.requestTimeEpoch", "resourceId":"$context.resourceId", "resourcePath":"$context.resourcePath", "stage":"$context.stage", "responseLatency":"$context.responseLatency", "responseLength":"$context.responseLength", "status":"$context.status" }

2.    Identifique o que está causando os erros 403 Forbidden visualizando os logs de execução da API REST no CloudWatch. Se um erro 403 Forbidden relacionado ao TLS mútuo for registrado, você receberá uma mensagem de erro semelhante à seguinte:

Exemplo de mensagem de erro do CloudWatch Logs quando um nome de domínio personalizado que requer TLS mútuo retorna um erro 403 Forbidden

Extended Request Id: {extendedRequestId} 
Access denied. Reason: {reason} 
ForbiddenException Forbidden: {requestId}

Para resolver erros "Acesso negado. Motivo: não foi possível encontrar o emissor do certificado"

Verifique se o emissor do certificado do cliente na solicitação da API está incluído na truststore do nome de domínio personalizado

O emissor do certificado do cliente (client.pem) na solicitação da API deve ser incluído na truststore do seu nome de domínio personalizado. O emissor também deve ser incluído como parte do pacote de certificados (bundle.pem) no Amazon Simple Storage Service (Amazon S3).

Para verificar se o emissor do certificado do cliente está incluído no truststore necessário, execute o seguinte comando OpenSSL:

$ openssl verify -CAfile bundle.pem client.pem
  • ou -

Se o pacote de certificados contiver autoridades de certificação intermediárias, execute o seguinte comando OpenSSL:

$ openssl verify -CAfile rootCA.pem -untrusted intCA.pem client.pem

O comando retornará uma resposta OK se o emissor do certificado do cliente na solicitação da API estiver incluído no truststore necessário.

Se o emissor do certificado do cliente não estiver incluído no truststore necessário, o comando retornará o seguinte erro: "erro X na profundidade de pesquisa Y: não é possível obter o certificado do emissor local"

Verifique se todos os certificados de cliente no truststore do seu nome de domínio personalizado são válidos

Se um dos certificados de cliente no truststore do seu nome de domínio personalizado não for válido, alguns clientes talvez não consigam acessar sua API.

Para verificar se todos os certificados de cliente em seu truststore são válidos, faça o seguinte:

1.    Abra o console do API Gateway.

2.    No painel de navegação esquerdo, escolha Nomes de domínio personalizados. Em seguida, escolha seu nome de domínio personalizado que requer TLS mútuo.

3.    Na seção Details (Detalhes), verifique se a seguinte mensagem de erro é exibida:There is an invalid certificate in your truststore bundle (Há um certificado inválido no seu pacote de truststore).

4.    Se a mensagem de erro estiver presente, você deverá decodificar os certificados em seu armazenamento confiável para identificar qual certificado produziu o aviso.
Observação: o seguinte comando OpenSSL exibe o conteúdo de um certificado, incluindo o assunto:

$ openssl x509 -in certificate.crt -text -noout

5.    Atualize ou remova os certificados que produziram o aviso. Em seguida, carregue um novo truststore para o Amazon S3.

Para obter mais informações, consulte Solução de problemas de avisos de certificados.

Observação: se a cadeia de certificados for preservada, o API Gateway aceitará certificados de cliente assinados diretamente pela autoridade de certificação raiz ou qualquer outra intermediária. Para validar certificados de cliente assinados apenas pela última autoridade de certificação intermediária, use um AWS Lambda Authorizer baseado em parâmetros de solicitação. Você pode usar seu algoritmo de validação personalizado no nível da função do Lambda aceitando o certificado do cliente como entrada da solicitação da API.

Para resolver erros "Acesso negado. Motivo: o certificado do cliente usa um algoritmo de assinatura inseguro

Verifique se o arquivo de texto do truststore usa um algoritmo de hash compatível

O API Gateway é compatível com os seguintes algoritmos de hash no truststorel:

  • SHA-256 ou mais forte
  • RSA-2048 ou mais forte
  • ECDSA-256 ou mais forte

Para verificar se o arquivo de texto do truststore usa um algoritmo de hash compatível, execute o seguinte comando OpenSSL:

$ openssl x509 -in client.crt -text -noout | grep 'Signature Algorithm'

A resposta do comando retorna o algoritmo de assinatura do seu truststore.

Para obter mais informações, consulte Configuração do truststore.

Para resolver erros "Acesso negado. Motivo: certificado autoassinado"

Verifique se o certificado de cliente autoassinado na solicitação da API não foi alterado nem está corrompido

Os seguintes itens devem corresponder exatamente:

  • O módulo da chave privada (private.key) usado para assinar o certificado autoassinado no armazenamento confiável no S3 (bundle.crt ou bundle.pem).
  • O módulo do certificado do cliente passado na solicitação da API (client.crt).

Para comparar os dois módulos, execute os seguintes comandos OpenSSL:

$ openssl rsa -noout -modulus -in private.key
$ openssl x509 -noout -modulus -in bundle.crt
$ openssl x509 -noout -modulus -in client.crt

Observação: para produzir um valor de hash mais curto a fim de facilitar a comparação, você pode fazer o PIPE do módulo de saída em uma função de hash criptográfica. Veja o seguinte exemplo do openssl sha1:

$ openssl [operation] -noout -modulus -in [data] | openssl sha1

Exemplo de saídas de comando válidas

2143831a73a8bb28467860df18550c696c03fbcb
2143831a73a8bb28467860df18550c696c03fbcb
2143831a73a8bb28467860df18550c696c03fbcb

Para confirmar a integridade dos dados, verifique se não houve nenhuma modificação de dados no nível do conteúdo executando o seguinte comando diff:

$ diff client.crt bundle.crt

Para obter mais informações, consulte Configuração do truststore.