NodeJS et les certificats

08 mai 2015 - truc&astuce http nodejs

J’ai été récemment confronté au problème de la sécurisation du lien entre 2 instances NodeJS dans un projet personnel. L’idée est d’avoir une instance centrale (central) sur un réseau privé et des instances déportées sur internet (sondes). Le central doit pouvoir communiquer avec les sondes mais rien n’empêche que les sondes soient également utilisées par plusieurs centrals.

Evidement, j’ai pensé HTTPS avec certificat client et avec NodeJS ça se fait assez simplement comme expliqué sur ce blog.

Le gros soucis c’est que je suis un gros fainéant et je veux pouvoir lancer les sondes en une seule ligne de commande type nodejs app.js. Il fallait donc que la création des certificats soit incluse dans l’appli NodeJS. Au miracle, j’ai trouvé la librairie pem qui est simple d’utilisation.

La création des clés et certificats

Pour faire le moins moche possible, le démarrage de la sonde se fait en 3 étapes :

  • création d’un certificat d’autorité (CA)
  • création d’un certificat pour le serveur signé par le CA
  • création d’un certificat client signé par le CA

La signature du certificat serveur par mon CA n’est vraiment pas utile. Idéalement le certificat serveur devrait être signé par une vraie autorité de certification mais bon… ça n’a pas vocation a être utilisé dans un navigateur mais seulement dans une appli nodeJS.

Avec pem, la création d’un certificat est ultra simple.

Pour le CA :

var https = require('https'),
      pem = require('pem');
//Stockage de la clé et du certificat CA
var SSLcaCert, SSLcaKey;
pem.createCertificate({
      days:365,
      selfSigned:true,
      commonName: "Probe authority"
    },
    function(err,keys){
      //Le certificat
      SSLcaCert = keys.certificate;
      //La clé privée
      SSLcaKey = keys.clientKey;
    });

C’est quand même plus simple qu’en ligne de commande avec openssl, non ??

Et pour le certificat client :

var SSLClientCert, SSLClientKey;
pem.createCertificate({
      days:365,
      serviceKey: SSLcaKey,
      serviceCertificate: SSLcaCert,
      serial: 2,
      commonName: "Probe client"
    },
    function(err,keys){
      //Le certificat
      SSLClientCert = keys.certificate;

      //La clé privée
      SSLClientKey = keys.clientKey;

    });

Pour le serveur c’est la même chose.

L’utilisation des clés et certificats

On utilise le package https pour communiquer du central à la sonde avec https.request() ou https.get().

L’exemple fourni sur nodejs.org est assez parlant :

var options = {
  hostname: 'encrypted.google.com',
  port: 443,
  path: '/',
  method: 'GET',
  key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'),
  rejectUnauthorized: false
};
options.agent = new https.Agent(options);

var req = https.request(options, function(res) {
  ...
}

On aura juste pris soin de stocker la valeur de SSLClientKey dans test/fixtures/keys/agent2-key.pem et SSLClientCert dans test/fixtures/keys/agent2-cert.pem.

L’option rejectUnauthorized est nécessaire car notre certificat serveur n’est pas signé par un vrai CA (Trusted CA).



Voir aussi :

Gérer les accès à plusieurs clusters kunernetes

30 octobre 2018 - docker truc&astuce k8s -

Mon utilisation de Traefik

30 octobre 2018 - docker truc&astuce article -

Construction d'image non x86 à base d'image officielle

31 décembre 2017 - docker truc&astuce -

Un point sur les proxys HTTP

16 octobre 2015 - http article

NodeJS et les certificats

08 mai 2015 - truc&astuce http nodejs