Impossible de vérifier la signature de la feuille

142

J'utilise node.js request.js pour accéder à une API. J'obtiens cette erreur

[Erreur: UNABLE_TO_VERIFY_LEAF_SIGNATURE]

Toutes mes informations d'identification sont exactes et valides, et le serveur va bien. J'ai fait la même demande avec le facteur.

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);
});

Ce code est juste en cours d'exécution dans un script exécutable ex. node ./run_file.js, Ç'est pourquoi? Doit-il fonctionner sur un serveur?

ThomasReggi
la source
C'est long, mais se pourrait-il que l'API ne reconnaisse pas l'agent utilisateur transmis par votre programme de nœud?
Hector Correa
1
Hum ... voir aussi ceci: blog.gaeremynck.com/fixing-unable_to_verify_leaf_signature
Hector Correa
@HectorCorrea J'ai pu lire parfaitement l'api dans Postman. Pourquoi le nœud ne peut-il pas le faire? J'ai essayé de changer l'agent utilisateur, pas de chance.
ThomasReggi

Réponses:

157

Remarque : ce qui suit est dangereux et permettra au contenu de l'API d'être intercepté et modifié entre le client et le serveur.

Cela a également fonctionné

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

ThomasReggi
la source
22
J'ai modifié ceci et merci d'avoir répondu, mais cela nuit activement à votre sécurité. Vous devez ajouter l'autorité de certification manquante selon la réponse de @ CoolAJ86 ci-dessous.
mikemaccana
4
J'utilise le plugin appelé NodeJS nodemaileret nodemailer-smtp-transportet la même commande générale a fonctionné. Vous devez ajouter ceci à votre createTransportobjet:tls:{rejectUnauthorized: false}
LukeP
3
@LukeP tout aussi peu sûr avec nodemailer, je suppose. Il y a un indice dans le nom: si quelque chose de Un autorisé, vous voulez généralement de le rejeter, par définition. Ce dont vous avez besoin est de trouver un moyen de l'autoriser correctement (en configurant correctement les certificats CA, comme d'autres réponses l'ont déjà dit).
Bruno
@Bruno Je suis d'accord, vous devriez le configurer correctement avec des certificats. Je voulais simplement configurer un test rapide pour une démo afin que le code que j'ai publié soit une solution rapide. J'aurais dû commencer par cela dans mon commentaire.
LukeP
1
@mikemaccana Il n'y a pas de problème de sécurité si la requête est sur le même serveur et que vous êtes le seul propriétaire.
Binar Web
89

Ce n'est pas un problème avec l'application, mais avec le certificat qui est signé par une autorité de certification intermédiaire. Si vous acceptez ce fait et que vous souhaitez continuer, ajoutez ce qui suit aux options de demande:

rejectUnauthorized: false

Demande complète:

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);
});
Andrei Karpushonak
la source
J'ai ce problème en ce moment au travail. J'ai soumis un ticket informatique leur disant que SSL était peut-être mal configuré - ils m'ont dit que j'étais fou. Puis-je leur fournir d'autres informations pour résoudre ce problème?
blakev
Ce n'est pas vraiment correct: comme le mentionnent CoolAJ86 et hectorcorrea, le certificat est valide, mais il est signé par une autorité de certification intermédiaire.
mikemaccana
80

La solution sécurisée

Plutôt que de désactiver la sécurité, vous pouvez ajouter les certificats nécessaires à la chaîne. Installez d'abord le package ssl-root-cas à partir de npm:

npm install ssl-root-cas

Ce package contient de nombreux certificats intermédiaires auxquels les navigateurs font confiance, mais pas le nœud.

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

Ajoutera les certificats manquants. Voir ici pour plus d'informations:

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

Voir également la réponse suivante ci-dessous

coolaj86
la source
2
Le client Http n'utilise-t-il pas le magasin de certificats des autorités de certification racine de confiance Windows?
Richard Collette
1
node utilise les certificats mozilla regroupés dans le binaire et les remplace chaque fois que vous fournissez votre propre catableau. Je ne sais pas si son module http se penchera également sur la chaîne OS. Cependant, curl sur OS X semble n'utiliser que la chaîne du système d'exploitation et ne pas autoriser les certificats spécifiés manuellement.
coolaj86
Dois-je l'exécuter pour chaque processus ou puis-je l'exécuter une seule fois et mettre à jour mes certificats globalement?
Joshua Snider
Les certificats sont stockés à deux endroits potentiels: (1) intégré au binaire node.js (2) au fichier de clés du système d'exploitation. Si vos certificats ne sont pas à jour, vous devrez les inclure dans votre code en cours d'exécution. Cela ne change pas le binaire du nœud ni votre système d'exploitation - juste le dossier du projet.
coolaj86
1
@Sunkas C'est exactement ce que disent les messages d'erreur. Je ne sais pas comment l'expliquer plus simplement. C'est un fichier en lecture seule et ne peut pas être modifié.
coolaj86
45

La solution de CoolAJ86 est correcte et ne compromet pas votre sécurité comme la désactivation de toutes les vérifications en utilisant rejectUnauthorizedouNODE_TLS_REJECT_UNAUTHORIZED . Néanmoins, vous devrez peut-être injecter explicitement le certificat d'une autorité de certification supplémentaire.

J'ai d'abord essayé les CA racine inclus par le module ssl-root-cas :

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

J'ai toujours fini avec l' UNABLE_TO_VERIFY_LEAF_SIGNATUREerreur. Ensuite, j'ai découvert qui a émis le certificat pour le site Web auquel je me connectais par l' analyseur SSL COMODO, j'ai téléchargé le certificat de cette autorité et j'ai essayé de n'ajouter que celui-là:

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

Je me suis retrouvé avec une autre erreur: CERT_UNTRUSTED. Enfin, j'ai injecté les autorités de certification racine supplémentaires et inclus "mon" (apparemment intermédiaire) CA, qui a fonctionné:

require('ssl-root-cas/latest')
  .inject()
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');
Ferdinand Prantl
la source
1
Je me connectais à un site Web avec un certificat délivré par la CA COMODO High-Assurance Secure Server. J'ai téléchargé le certificat depuis leur page de téléchargement .
Ferdinand Prantl
2
Je vous remercie! Pour mon problème, j'avais besoin d'ajouter toute la chaîne de certificats pour contourner cette erreur. Pour d'autres références, cet article m'a montré comment exporter facilement les fichiers pem nécessaires via Firefox: superuser.com/a/97203
mfink
Eh bien merci pour l'aide. Dans mon cas, au final c'était une mauvaise configuration du serveur SSL, pas du nœud. Tous les certificats intermédiaires n'ont pas été installés sur le serveur.
Scott Jungwirth
si vous obtenez le certificat en cours d' .cerexécution ceci openssl x509 -inform DER -in YOUR_CERTIFICATE.cer -out YOUR_CERTIFICATE.crtpour le convertir .crtau préalable
0x1gene
8

Pour Create React App (où cette erreur se produit également et cette question est le résultat n ° 1 de Google), vous utilisez probablement HTTPS=true npm startet un proxy(danspackage.json ) qui va à une API HTTPS qui est elle-même auto-signée, lorsqu'elle est en développement.

Si tel est le cas, envisagez de changer proxycomme ceci:

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

secure décide si le proxy WebPack vérifie la chaîne de certificats ou non et la désactivation qui garantit que le certificat auto-signé de l'API n'est pas vérifié afin que vous obteniez vos données.

Tomáš Hübelbauer
la source
4

Il peut être très tentant de faire rejectUnauthorized: falseouprocess.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; ne pas le faire! Cela vous expose à l'homme au milieu des attaques.

Les autres réponses sont correctes dans la mesure où le problème réside dans le fait que votre certificat est «signé par une autorité de certification intermédiaire». Il existe une solution simple à cela, qui ne nécessite pas de bibliothèque tierce commessl-root-cas ou d'injection de CA supplémentaires dans le nœud.

La plupart des clients https dans le nœud prennent en charge les options qui vous permettent de spécifier une autorité de certification par requête, ce qui résoudra UNABLE_TO_VERIFY_LEAF_SIGNATURE. Voici un exemple simple utilisant le httpsmodule intégré de node .

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
})

Si, cependant, vous pouvez configurer les paramètres ssl dans votre serveur d'hébergement, la meilleure solution serait d'ajouter les certificats intermédiaires à votre fournisseur d'hébergement. De cette façon, le demandeur client n'a pas besoin de spécifier une autorité de certification, car elle est incluse dans le serveur lui-même. J'utilise personnellement namecheap + heroku. L'astuce pour moi était de créer un fichier .crt avec cat yourcertificate.crt bundle.ca-bundle > server.crt. J'ai ensuite ouvert ce fichier et ajouté une nouvelle ligne après le premier certificat. Vous pouvez en savoir plus sur

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

Simon
la source
Ce bogue vient principalement dans l'environnement local, pas en production, donc si vous êtes en local, c'est bien à faire: process.env ['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
Vivex
@Vivex - ce n'est pas correct de le faire dans un environnement local si le point entier est de tester le fonctionnement de vos certificats SSL et comment ils sont transmis ...
dwanderson
2

Mettre cela ici au cas où cela aiderait quelqu'un, mon cas était différent et un peu étrange. J'obtenais cela sur une demande accessible via superagent - le problème n'avait rien à voir avec les certificats (qui étaient correctement configurés) et tout à voir avec le fait que je passais ensuite le résultat du superagent via le rappel en cascade du module async . Pour corriger: au lieu de transmettre le résultat entier, passez simplement result.bodypar le rappel de la cascade.

k00k
la source
2

J'ai eu les mêmes problèmes. J'ai suivi la solution @ThomasReggi et @ CoolAJ86 et j'ai bien travaillé mais je ne suis pas satisfait de la solution.

Parce que le problème "UNABLE_TO_VERIFY_LEAF_SIGNATURE" est survenu en raison du niveau de configuration de la certification.

J'accepte la solution @thirdender mais sa solution partielle.Comme le site officiel de nginx , le certificat clairement mentionné doit être une combinaison du certificat de serveur et des certificats chaînés.

entrez la description de l'image ici

Sharathi RB
la source
2

Vous pouvez également essayer en définissant strictSSL sur false, comme ceci:

{  
   url: "https://...",
   method: "POST",
   headers: {
        "Content-Type": "application/json"},
   strictSSL: false
}
SUBHAJIT GANGULI
la source
Cela fonctionne si votre envoi depuis l'application Node JS, génial !!
Ally Makongo il y a
0

J'ai eu un problème avec ma configuration Apache après l'installation d'un certificat GoDaddy sur un sous-domaine. Au départ, je pensais que cela pourrait être un problème avec Node n'envoyant pas d'indicateur de nom de serveur (SNI), mais ce n'était pas le cas. L'analyse du certificat SSL du sous-domaine avec https://www.ssllabs.com/ssltest/ a renvoyé l'erreur Problèmes de chaîne: incomplets .

Après avoir ajouté le gd_bundle-g2-g1.crtfichier fourni par GoDaddy via la SSLCertificateChainFiledirective Apache, Node a pu se connecter via HTTPS et l'erreur a disparu.

tiers
la source
0

Vous devez inclure le certificat intermédiaire dans votre serveur. Cela résout l '[Erreur: UNABLE_TO_VERIFY_LEAF_SIGNATURE]


la source
0

Une autre approche pour résoudre ce problème en toute sécurité consiste à utiliser le module suivant.

node_extra_ca_certs_mozilla_bundle

Ce module peut fonctionner sans aucune modification de code en générant un fichier PEM qui comprend tous les certificats racine et intermédiaires approuvés par Mozilla. Vous pouvez utiliser la variable d'environnement suivante (Fonctionne avec Nodejs v7.3 +),

NODE_EXTRA_CA_CERTS

Pour générer le fichier PEM à utiliser avec la variable d'environnement ci-dessus. Vous pouvez installer le module en utilisant:

npm install --save node_extra_ca_certs_mozilla_bundle

puis lancez votre script de nœud avec une variable d'environnement.

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

D'autres façons d'utiliser le fichier PEM généré sont disponibles sur:

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

REMARQUE: je suis l'auteur du module ci-dessus.

arva
la source
0

Si vous arrivez à ce fil parce que vous utilisez le module node postgres / pg, il existe une meilleure solution que de définir NODE_TLS_REJECT_UNAUTHORIZEDou rejectUnauthorized, ce qui conduira à des connexions non sécurisées.

Au lieu de cela, configurez l'option "ssl" pour qu'elle corresponde aux paramètres de 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
}

J'ai écrit un module d'aide à l' analyse de ces options de variables d'environnement comme PGSSLROOTCERT, PGSSLCERTet PGSSLKEY:

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

Donald
la source
-1

Les commandes suivantes ont fonctionné pour moi:

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

Le problème est que vous essayez d'installer un module à partir d'un référentiel avec un certificat SSL [Secure Sockets Layer] incorrect ou non approuvé. Une fois que vous aurez nettoyé le cache, ce problème sera résolu. Vous devrez peut-être l'activer ultérieurement.

Shagun Pruthi
la source