Não foi possível verificar a assinatura da folha


142

Estou usando o node.js request.js para acessar uma API. Estou recebendo este erro

[Erro: UNABLE_TO_VERIFY_LEAF_SIGNATURE]

Todas as minhas credenciais são precisas e válidas, e o servidor está bem. Fiz o mesmo pedido com o carteiro.

request({
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});

Este código está sendo executado apenas em um script executável ex. node ./run_file.js, É por isso que? Ele precisa ser executado em um servidor?


É um tiro no escuro, mas será que a API não está reconhecendo o agente do usuário que está sendo transmitido pelo seu programa de nó?
— perfil completo de Hector Correa


@HectorCorrea Consegui ler perfeitamente a API no carteiro. Por que o nó não pode fazer isso? Eu tentei mudar o agente do usuário, sem sorte.
— ThomasReggi

Respostas:


157

Nota : o seguinte é perigoso e permitirá que o conteúdo da API seja interceptado e modificado entre o cliente e o servidor.

Isso também funcionou

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';


22
Modifiquei isso e obrigado por responder, mas isso é prejudicial à sua segurança. Você deve adicionar a CA ausente conforme a resposta do @ CoolAJ86 abaixo.
— Mikemaccana 02/06

4
Eu estou usando os NodeJS plugin chamado nodemailere nodemailer-smtp-transporte o mesmo comando geral funcionou. Você precisa adicionar isso ao seu createTransportobjeto:tls:{rejectUnauthorized: false}
— LukeP 15/09

3
@LukeP igualmente inseguro com o nodemailer, eu acho. Há uma pista no nome: se de algo Un autorizado, geralmente você quer rejeitá-la, por definição. O que você precisa é encontrar uma maneira de autorizá-lo corretamente (configurando os certificados da CA corretamente, como outras respostas já disseram).
— Bruno

@ Bruno Eu concordo, você deve configurá-lo da maneira certa com certificados. Eu apenas queria configurar um teste rápido para uma demonstração, para que o código que publiquei seja uma solução rápida. Eu deveria ter precedido isso no meu comentário.
— LukeP

1
@mikemaccana Não há problemas de segurança se a solicitação estiver no mesmo servidor e você for o único proprietário.
— Binar Web

89

Não é um problema com o aplicativo, mas com o certificado assinado por uma CA intermediária. Se você aceitar esse fato e ainda quiser continuar, adicione o seguinte para solicitar opções:

rejectUnauthorized: false

Pedido completo:

request({
    "rejectUnauthorized": false,
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});

Eu tenho esse problema agora no trabalho. Enviei um tíquete de TI informando que o SSL pode estar mal configurado - eles me disseram que eu era louco. Há mais informações que eu possa fornecer para resolver esse problema?
— blakev

Na verdade, isso não está correto: como mencionam CoolAJ86 e hectorcorrea, o certificado é válido, mas é assinado por uma CA intermediária.
— Mikemaccana

80

A solução segura

Em vez de desativar a segurança, você pode adicionar os certificados necessários à cadeia. Primeiro instale o pacote ssl-root-cas a partir do npm:

npm install ssl-root-cas

Este pacote contém muitos certificados intermediários nos quais os navegadores confiam, mas o nó não.

var sslRootCAs = require('ssl-root-cas/latest')
sslRootCAs.inject()

Irá adicionar os certificados ausentes. Veja aqui para mais informações:

https://git.coolaj86.com/coolaj86/ssl-root-cas.js

Veja também a próxima resposta abaixo


2
O cliente Http não usa o armazenamento de certificados das Autoridades de Certificação Raiz Confiáveis ​​do Windows?
— 21416 Richard Collette

1
O nó usa os certificados mozilla agrupados no binário e os substitui sempre que você fornece sua própria camatriz. Não sei se o módulo http também procurará a cadeia do sistema operacional. No entanto, a ondulação no OS X parece usar apenas a cadeia do SO e não permitir certificados manualmente especificados.
— coolaj86

Isso precisa ser executado para cada processo ou posso executá-lo uma vez e atualizar meus certificados globalmente?
— 1937 Joshua Snider #

Os certificados são armazenados potencialmente em dois locais: (1) embutido no binário node.js (2) no keystore do sistema operacional. Se seus certificados estão desatualizados, você precisará incluí-lo no seu código de execução. Ele não altera o binário do nó nem o sistema operacional - apenas a pasta do projeto.
— coolaj86

1
@ Sunkas É exatamente o que as mensagens de erro dizem. Eu não sei como explicar isso de maneira mais simples. É um arquivo somente leitura e não pode ser editado.
— coolaj86 13/03

45

A solução do CoolAJ86 está correta e não compromete sua segurança, como desativar todas as verificações usando rejectUnauthorizedou NODE_TLS_REJECT_UNAUTHORIZED. Ainda assim, pode ser necessário injetar explicitamente um certificado de autoridade de certificação adicional.

Tentei primeiro as autoridades de certificação raiz incluídas no módulo ssl-root-cas :

require('ssl-root-cas/latest')
  .inject();

Eu ainda acabei com o UNABLE_TO_VERIFY_LEAF_SIGNATUREerro. Em seguida, descobri quem emitiu o certificado para o site ao qual estava me conectando pelo COMODO SSL Analyzer , baixei o certificado dessa autoridade e tentei adicionar apenas aquele:

require('ssl-root-cas/latest')
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');

Acabei com outro erro: CERT_UNTRUSTED. Por fim, injetei as CAs raiz adicionais e incluí a CA "minha" (aparentemente intermediária), que funcionou:

require('ssl-root-cas/latest')
  .inject()
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');

1
Eu estava me conectando a um site com um certificado emitido pela CA do servidor seguro COMODO High-Assurance. Eu baixei o certificado da página de downloads .
— Ferdinand Prantl

2
Obrigado! Para o meu problema, eu precisava adicionar toda a cadeia de certificados para superar esse erro. Para outros referência, este post me mostrou como é fácil exportar os arquivos PEM necessários via Firefox: superuser.com/a/97203
— mfink

Bem, obrigado pela ajuda. No meu caso, no final, era uma configuração ruim do servidor SSL, não do nó. Nem todos os certificados intermediários foram instalados no servidor.
— 22415 Scott Jungwirth

se você receber o certificado como .cerexecutar este openssl x509 -inform DER -in YOUR_CERTIFICATE.cer -out YOUR_CERTIFICATE.crtpara convertê-lo ta .crtde antemão
— 0x1gene

8

Para o Create Create React App (onde esse erro também ocorre e esta pergunta é o principal resultado do Google), você provavelmente está usando HTTPS=true npm startum proxy(in package.json) que vai para alguma API HTTPS que é autoassinada quando está em desenvolvimento.

Se for esse o caso, considere mudar proxyassim:

"proxy": {
  "/api": {
    "target": "https://localhost:5001",
    "secure": false
  }
}

secure decide se o proxy WebPack verifica ou não a cadeia de certificados e desativa, o que garante que o certificado autoassinado da API não seja verificado para que você obtenha seus dados.


4

Pode ser muito tentador fazer rejectUnauthorized: falseou process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';não fazê-lo! Expõe você ao homem nos ataques do meio.

As outras respostas estão corretas, pois o problema está no fato de o seu certificado ser "assinado por uma CA intermediária". Existe uma solução fácil para isso, que não requer uma biblioteca de terceiros, como ssl-root-casinjeta CAs adicionais no nó.

A maioria dos clientes https no nó suporta opções que permitem especificar uma CA por solicitação, que será resolvida UNABLE_TO_VERIFY_LEAF_SIGNATURE. Aqui está um exemplo simples usando o httpsmódulo interno do nó .

import https from 'https';

const options = {
  host: '<your host>',
  defaultPort: 443,
  path: '<your path>',
  // assuming the bundle file is co-located with this file
  ca: readFileSync(__dirname + '/<your bundle file>.ca-bundle'),
  headers: {
    'content-type': 'application/json',
  }
};
https.get(options, res => {
  // do whatever you need to do
})

Se, no entanto, você puder definir as configurações de SSL no servidor de hospedagem, a melhor solução seria adicionar os certificados intermediários ao seu provedor de hospedagem. Dessa forma, o solicitante do cliente não precisa especificar uma CA, pois está incluída no próprio servidor. Eu pessoalmente uso namecheap + heroku. O truque para mim foi criar um arquivo .crt com cat yourcertificate.crt bundle.ca-bundle > server.crt. Abri esse arquivo e adicionei uma nova linha após o primeiro certificado. Você pode ler mais em

https://www.namecheap.com/support/knowledgebase/article.aspx/10050/33/installing-an-ssl-certificate-on-heroku-ssl


Esse bug ocorre principalmente no ambiente local, não na produção. Portanto, se você estiver no local, é bom fazê-lo: process.env ['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
— Vivex #

@Vivex - não é permitido fazer isso em um ambiente local, se o objetivo principal é testar como seus certificados SSL funcionam e como eles são transmitidos ...
— dwanderson

2

Colocando isso aqui, caso isso ajude alguém, meu caso foi diferente e um pouco estranho. Eu estava recebendo isso em uma solicitação acessada via superagent - o problema não tinha nada a ver com certificados (que foram configurados corretamente) e tudo relacionado ao fato de eu estar passando o resultado do superagent pelo retorno de chamada em cascata do módulo assíncrono . Para corrigir: em vez de passar o resultado inteiro, basta passar result.bodypelo retorno de chamada da cachoeira.


2

Eu tive os mesmos problemas. Segui as soluções @ThomasReggi e @ CoolAJ86 e funcionou bem, mas não estou satisfeito com a solução.

Porque o problema "UNABLE_TO_VERIFY_LEAF_SIGNATURE" ocorreu devido ao nível de configuração da certificação.

Eu aceito a solução @thirdender, mas sua solução parcial. Conforme o site oficial da nginx , eles mencionaram claramente que o certificado deve ser a combinação de O certificado do servidor e os certificados encadeados.

insira a descrição da imagem aqui


1

Você também pode tentar configurando strictSSL para false, assim:

{  
   url: "https://...",
   method: "POST",
   headers: {
        "Content-Type": "application/json"},
   strictSSL: false
}

0

Eu tive um problema com minha configuração do Apache depois de instalar um certificado do GoDaddy em um subdomínio. Originalmente, pensei que poderia haver um problema com o Node não enviar um SNI (Server Name Indicator), mas esse não foi o caso. A análise do certificado SSL do subdomínio com https://www.ssllabs.com/ssltest/ retornou o erro Problemas de cadeia: incompleto .

Depois de adicionar o gd_bundle-g2-g1.crtarquivo fornecido pelo GoDaddy por meio da SSLCertificateChainFilediretiva Apache, o Node conseguiu se conectar por HTTPS e o erro desapareceu.


0

Você precisa incluir o certificado intermediário no seu servidor. Isso resolve o [Erro: UNABLE_TO_VERIFY_LEAF_SIGNATURE]


0

Outra abordagem para solucionar isso com segurança é usar o módulo a seguir.

node_extra_ca_certs_mozilla_bundle

Este módulo pode funcionar sem nenhuma modificação de código, gerando um arquivo PEM que inclui todos os certificados raiz e intermediários confiáveis ​​pelo Mozilla. Você pode usar a seguinte variável de ambiente (Works with Nodejs v7.3 +),

NODE_EXTRA_CA_CERTS

Para gerar o arquivo PEM para usar com a variável de ambiente acima. Você pode instalar o módulo usando:

npm install --save node_extra_ca_certs_mozilla_bundle

e, em seguida, inicie o script do nó com uma variável de ambiente.

NODE_EXTRA_CA_CERTS=node_modules/node_extra_ca_certs_mozilla_bundle/ca_bundle/ca_intermediate_root_bundle.pem node your_script.js

Outras maneiras de usar o arquivo PEM gerado estão disponíveis em:

https://github.com/arvind-agarwal/node_extra_ca_certs_mozilla_bundle

NOTA: Eu sou o autor do módulo acima.


0

Se você chegar a esse encadeamento porque está usando o módulo postgres / pg do nó, há uma solução melhor que a configuração NODE_TLS_REJECT_UNAUTHORIZEDou rejectUnauthorized, que levará a conexões inseguras.

Em vez disso, configure a opção "ssl" para corresponder aos parâmetros para tls.connect :

{
  ca: fs.readFileSync('/path/to/server-ca.pem').toString(),
  cert: fs.readFileSync('/path/to/client-cert.pem').toString(),
  key: fs.readFileSync('/path/to/client-key.pem').toString(),
  servername: 'my-server-name' // e.g. my-project-id/my-sql-instance-id for Google SQL
}

Eu escrevi um módulo para ajudar com a análise dessas opções de variáveis de ambiente como PGSSLROOTCERT, PGSSLCERT, e PGSSLKEY:

https://github.com/programmarchy/pg-ssl


0

Os seguintes comandos funcionaram para mim:

> npm config set strict-ssl false
> npm cache clean --force

O problema é que você está tentando instalar um módulo a partir de um repositório com um certificado SSL [Secure Sockets Layer] inválido ou não confiável. Depois de limpar o cache, esse problema será resolvido. Talvez seja necessário transformá-lo em verdadeiro mais tarde.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.