web-dev-qa-db-fra.com

nodejs ssl "impossible d'obtenir le certificat d'un émetteur local"

J'ai reçu un certificat SSL à utiliser pour signer les demandes des clients, ainsi que les certificats d'autorité de certification pertinents. Je peux le vérifier en utilisant openssl:

$ openssl s_client -CAfile /etc/ssl/foo/ca-combined.pem -servername foo.co.in -connect foo.co.in:443
CONNECTED(00000003)
... snip ...
Verify return code: 0 (ok)
---
closed

(J'ai écrasé les 2 certificats de l'autorité de certification dans un fichier). Mais quand j'essaye de le répliquer en utilisant noeud:

    var tls = require('tls');
    var fs = require('fs');

    var options = { 
        Host: 'foo.co.in',
        servername: 'foo.co.in',
        port: 443,
        key: fs.readFileSync('/etc/ssl/private/foo.key'),
        cert: fs.readFileSync('/etc/ssl/foo/cert.pem'),
        ca: [fs.readFileSync('/etc/ssl/foo/combined-ca.pem')]
    };  

    tls.connect(options, function(err) {
        done(err);
    });

Je reçois une erreur:

Uncaught Error: unable to get local issuer certificate
  at Error (native)
  at TLSSocket.<anonymous> (_tls_wrap.js:1092:38)
  at TLSSocket._finishInit (_tls_wrap.js:610:8)
  at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:440:38)

J'ai trouvé une réponse ici suggérant que je devais mettre chaque certificat de CA dans un fichier séparé:

ca: [fs.readFileSync('/etc/ssl/foo/ca.pem'), fs.readFileSync('/etc/ssl/foo/root-ca.pem')]

mais cela a toujours donné la même erreur. (J'ai aussi essayé d'inverser l'ordre). J'ai ensuite essayé de mettre le certificat intermédiaire dans celui du client, et de fournir simplement le certificat de l'autorité de certification racine en tant que ca (ce qui semble être ce que suggèrent les docs ), même erreur. À ce stade, je suis à court d'idées. Le fait que openssl soit heureux suggère que je fais quelque chose de mal, des suggestions?

$ node --version
v6.10.1

(Je me rends compte que je peux définirjectUnunhorized sur false, mais je préfère ne pas le faire)

7
grahamrhay

Il s'avère que je n'avais pas besoin de fournir le certificat de CA, car leur CA était correctement signée par une autorité "connue". Je pourrais donc simplement supprimer le champ ca de ma demande.

1
grahamrhay

J'ai créé un certificat racine-ca et un certificat intermédiaire-ca (signé par racine-ca), puis j'ai créé un serveur et un certificat client signé par intermédiaire-ca. Pour le tester, j'ai implémenté un serveur et un client https avec nodejs afin de le configurer avec les certificats et d'obtenir l'erreur suivante sur mon client:

problem with request: unable to get local issuer certificate

Pour le résoudre, je dois mettre dans mes codes nodejs, dans le champ ca, mes certificats racine-ca et intermédiaire-ca. Comme ça:

key: fs.readFileSync('path/client.privkey.pem'),
cert: fs.readFileSync('path/client.cert.pem'),
ca: [ fs.readFileSync('path/intermed-ca.cert.pem'), fs.readFileSync('path/root-ca.cert.pem') ],

ça marche pour moi.