web-dev-qa-db-fra.com

Comment utiliser un certificat auto-signé pour un serveur HTTPS Node.js?

J'ai commencé à écrire un wrapper pour une API qui requiert que toutes les demandes soient via HTTPS. Au lieu de faire des demandes à l'API réelle pendant que je développe et teste celle-ci, j'aimerais exécuter mon propre serveur localement, qui se moque des réponses.

Je ne comprends pas comment générer les certificats dont j'ai besoin pour créer un serveur HTTPS et lui envoyer des demandes.

Mon serveur ressemble à ceci:

var options = {
  key: fs.readFileSync('./key.pem'),
  cert: fs.readFileSync('./cert.pem')
};

https.createServer(options, function(req, res) {
  res.writeHead(200);
  res.end('OK\n');
}).listen(8000);

Les fichiers pem ont été générés avec:

openssl genrsa 1024 > key.pem
openssl req -x509 -new -key key.pem > cert.pem

Et une demande ressemble à ceci:

var options = {
  Host: 'localhost',
  port: 8000,
  path: '/api/v1/test'
};

https.request(options, function(res) {
  res.pipe(process.stdout);
}).end();

Avec cette configuration, je reçois Error: DEPTH_ZERO_SELF_SIGNED_CERT, je pense donc avoir besoin d’ajouter une option ca pour la requête.

Ma question est donc de savoir comment générer les éléments suivants:

  1. Le serveur key?
  2. Le serveur cert?
  3. Le ca pour la demande?

J'ai lu quelques informations sur la génération de certificats auto-signés avec openssl, mais je n'arrive pas à comprendre ce qui se passe et à déterminer les clés et les certificats à utiliser dans le code de mon nœud.

Mise à jour

L'API fournit un certificat de CA à utiliser à la place des valeurs par défaut. Le code suivant fonctionne avec leur certificat et c’est ce que je veux reproduire localement.

var ca = fs.readFileSync('./certificate.pem');

var options = {
  Host: 'example.com',
  path: '/api/v1/test',
  ca: ca
};
options.agent = new https.Agent(options);

https.request(options, function(res) {
  res.pipe(process.stdout);
}).end();
48
Brett

Mise à jour (nov. 2018): Avez-vous besoin de certificats de signature auto-signés?

Ou de vrais certificats feraient-ils le travail mieux? Avez-vous considéré l'un de ces?

(Remarque: Encrypt peut également émettre des certificats vers des réseaux privés)

ScreenCast

https://coolaj86.com/articles/how-to-create-a-csr-for-https-tls-ssl-rsa-pems/

Complet, exemple de travail

  • crée des certificats
  • exécute le serveur node.js
  • aucun avertissement ou erreur dans le client node.js
  • aucun avertissement ou erreur dans cURL

https://github.com/coolaj86/nodejs-self-signed-certificate-example

En utilisant localhost.greenlock.domains _ à titre d'exemple (il pointe vers 127.0.0.1):

server.js

'use strict';

var https = require('https')
  , port = process.argv[2] || 8043
  , fs = require('fs')
  , path = require('path')
  , server
  , options
  ;

require('ssl-root-cas')
  .inject()
  .addFile(path.join(__dirname, 'server', 'my-private-root-ca.cert.pem'))
  ;

options = {
  // this is ONLY the PRIVATE KEY
  key: fs.readFileSync(path.join(__dirname, 'server', 'privkey.pem'))
  // You DO NOT specify `ca`, that's only for peer authentication
//, ca: [ fs.readFileSync(path.join(__dirname, 'server', 'my-private-root-ca.cert.pem'))]
  // This should contain both cert.pem AND chain.pem (in that order) 
, cert: fs.readFileSync(path.join(__dirname, 'server', 'fullchain.pem'))
};


function app(req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello, encrypted world!');
}

server = https.createServer(options, app).listen(port, function () {
  port = server.address().port;
  console.log('Listening on https://127.0.0.1:' + port);
  console.log('Listening on https://' + server.address().address + ':' + port);
  console.log('Listening on https://localhost.greenlock.domains:' + port);
});

client.js

'use strict';

var https = require('https')
  , fs = require('fs')
  , path = require('path')
  , ca = fs.readFileSync(path.join(__dirname, 'client', 'my-private-root-ca.cert.pem'))
  , port = process.argv[2] || 8043
  , hostname = process.argv[3] || 'localhost.greenlock.domains'
  ;

var options = {
  Host: hostname
, port: port
, path: '/'
, ca: ca
};
options.agent = new https.Agent(options);

https.request(options, function(res) {
  res.pipe(process.stdout);
}).end();

Et le script qui crée les fichiers de certificat:

make-certs.sh

#!/bin/bash
FQDN=$1

# make directories to work from
mkdir -p server/ client/ all/

# Create your very own Root Certificate Authority
openssl genrsa \
  -out all/my-private-root-ca.privkey.pem \
  2048

# Self-sign your Root Certificate Authority
# Since this is private, the details can be as bogus as you like
openssl req \
  -x509 \
  -new \
  -nodes \
  -key all/my-private-root-ca.privkey.pem \
  -days 1024 \
  -out all/my-private-root-ca.cert.pem \
  -subj "/C=US/ST=Utah/L=Provo/O=ACME Signing Authority Inc/CN=example.com"

# Create a Device Certificate for each domain,
# such as example.com, *.example.com, awesome.example.com
# NOTE: You MUST match CN to the domain name or ip address you want to use
openssl genrsa \
  -out all/privkey.pem \
  2048

# Create a request from your Device, which your Root CA will sign
openssl req -new \
  -key all/privkey.pem \
  -out all/csr.pem \
  -subj "/C=US/ST=Utah/L=Provo/O=ACME Tech Inc/CN=${FQDN}"

# Sign the request from Device with your Root CA
openssl x509 \
  -req -in all/csr.pem \
  -CA all/my-private-root-ca.cert.pem \
  -CAkey all/my-private-root-ca.privkey.pem \
  -CAcreateserial \
  -out all/cert.pem \
  -days 500

# Put things in their proper place
rsync -a all/{privkey,cert}.pem server/
cat all/cert.pem > server/fullchain.pem         # we have no intermediates in this case
rsync -a all/my-private-root-ca.cert.pem server/
rsync -a all/my-private-root-ca.cert.pem client/

# create DER format crt for iOS Mobile Safari, etc
openssl x509 -outform der -in all/my-private-root-ca.cert.pem -out client/my-private-root-ca.crt

Par exemple:

bash make-certs.sh 'localhost.greenlock.domains'

Espérons que cela met le clou dans le cercueil sur celui-ci.

Et quelques autres explications: https://github.com/coolaj86/node-ssl-root-cas/wiki/Paneous-Self-Self-Signed-Certificates-in-node.js

Installer un cert privé sur iOS Mobile Safari

Vous devez créer une copie du certificat ca racine d'un format DER avec une extension .crt:

# create DER format crt for iOS Mobile Safari, etc
openssl x509 -outform der -in all/my-private-root-ca.cert.pem -out client/my-private-root-ca.crt

Ensuite, vous pouvez simplement servir ce fichier avec votre serveur Web. Lorsque vous cliquez sur le lien, on vous demandera si vous souhaitez installer le certificat.

Pour un exemple de fonctionnement, essayez d’installer l’autorité de certification du MIT: https://ca.mit.edu/mitca.crt

Exemples connexes

56
CoolAJ86

Essayez d'ajouter ceci à vos options de demande.

var options = {
  Host: 'localhost',
  port: 8000,
  path: '/api/v1/test',
  // These next three lines
  rejectUnauthorized: false,
  requestCert: true,
  agent: false
};
10
Loourr

Cette procédure vous permet de créer à la fois une autorité de certification et un certificat:

  1. prenez ceci ca.cnf fichier à utiliser comme raccourci de configuration:

    wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/ca.cnf


  1. créez une nouvelle autorité de certification à l'aide de cette configuration:

    openssl req -new -x509 -days 9999 -config ca.cnf -keyout ca-key.pem -out ca-cert.pem


  1. maintenant que nous avons notre autorité de certification en ca-key.pem et ca-cert.pem, générons une clé privée pour le serveur:

    openssl genrsa -out key.pem 4096


  1. prenez ceci server.cnf fichier à utiliser comme raccourci de configuration:

    wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/server.cnf


  1. générer la demande de signature de certificat en utilisant cette configuration:

    openssl req -new -config server.cnf -key key.pem -out csr.pem


  1. signer la demande:

    openssl x509 -req -extfile server.cnf -days 999 -passin "pass:password" -in csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem

J'ai trouvé cette procédure ici , avec plus d'informations sur l'utilisation de ces certificats.

3
John Slegers

Essayez d'ajouter

  agent: false,
  rejectUnauthorized: false
3
user1570577

Votre génération de clés a l'air bien. Vous ne devriez pas avoir besoin d'un ca car vous ne rejetez pas les demandes non signées.

Ajoutez .toString () à la fin de vos méthodes readFileSync afin que vous passiez une chaîne, pas un objet fichier.

3
binderbound