Consommer une ressource utilisant un certificat SSL/TLS auto signé

29 Mar 2021 | Développement, Node.js, Open Source, PHP

Il n’est pas rare d’avoir besoin de consommer depuis l’IBM i une ressource https auto-signée ou non reconnue, depuis un langage Open Source comme PHP ou Node.js.

C’est un cas qui arrive très souvent :

  • Pour les environnements serveur de tests, nous permettant de tester les appels avant de passer sur une ressource https de production avec un certificat « officiel ».
  • Pour les environnements internes à l’entreprise, utilisant des certificats auto-signés dont le signataire est l’entreprise elle-même : Serveurs de web services ou autres applications.

Depuis PHP 5.6 et pour des raisons de sécurité, la vérification de la validité du certificat serveur bloque par défaut la consommation si celui-ci n’est pas reconnu comme certificat de confiance. Le code PHP suivant consomme la ressource https://hostname/index.html utilisant un certificat auto-signé (hostname est à remplacer par un hostname valide) et contenant le texte « <h1>it worked!</h1> ».

<?php
ini_set('display_errors', true);

echo "<h1>CURL TEST</h1>";
// Création d'une nouvelle ressource cURL
$ch = curl_init();

// Configuration de l'URL et d'autres options
curl_setopt($ch, CURLOPT_URL, "https://hostname/index.html");

curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// Récupération de l'URL et affichage sur le navigateur
if( ! $result = curl_exec($ch))
{
    trigger_error(curl_error($ch));
}

echo $result;
// Fermeture de la session cURL

Ce code produit la PHP Notice suivante et n’affiche pas la ressource html demandée qui contient « it worked! » :

CURL TEST

Notice: SSL certificate problem: self signed certificate in /www/php7rpm/htdocs/ibm_db2_tests/consume.php on line 25

Plusieurs solutions s’offrent alors à nous :

1. Désactiver la vérification de la validité

Cela permet de tester rapidement mais cette technique comporte bien des inconvénients :

  • Nécessite de toucher le code de l’application au risque de laisser la vérification désactivée par commodité
  • Abaisse le niveau de sécurité des applications

Exemple avec le langage PHP et l’extension curl :

Pour cette solution, nous ajoutons au script précédent les instructions suivantes :

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Voici donc le nouveau résultat :

CURL TEST 

it worked!

Selon le client PHP utilisé pour consommer la ressource, la méthode peut être différente pour désactiver la vérification. Autre exemple avec la fonction PHP file_get_contents :

echo file_get_contents("https://hostname/index.html");

Ce code produit le résultat suivant :

file_get_contents test

Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed in /www/php7rpm/htdocs/ibm_db2_tests/consume.php on line 33
Warning: file_get_contents(): Failed to enable crypto in /www/php7rpm/htdocs/ibm_db2_tests/consume.php on line 33
Warning: file_get_contents(https://hostname/index.html): failed to open stream: operation failed in /www/php7rpm/htdocs/ibm_db2_tests/consume.php on line 33

Il faut lui rajouter un contexte où on désactive la vérification :

$stream_context = stream_context_create([ 'ssl' => [
    'verify_peer'       => false,
    'verify_peer_name'  => false,
    'allow_self_signed' => true ]]);

echo file_get_contents("https://hostname/index.html", false, $stream_context);

Et le nouveau résultat est :

file_get_contents test

it worked!

2. Installer le certificat du serveur pour lui indiquer qu’il est de confiance

Cette méthode est la plus sûre et la plus propre. Elle consiste à récupérer le certificat du serveur et à l’enregistrer sur l’IBM i comme certificat de confiance. Vous pourrez ensuite consommer les ressources protégées par ce certificat sans vous soucier d’avoir à désactiver les vérifications.

Une première étape est d’installer (si ce n’est pas déjà le cas), le package Open Source ca-certificates-mozilla. Ce package apporte le même magasin de certificats de confiance que celui de Mozilla Firefox. Il fait donc confiance à un plus grand nombre de certificats signés par des autorités reconnues mondialement.

En prérequis, l’environnement Open Source sur IBM i doit être installé.

Dans ACS -> Gestion de modules Open Source, sélectionnez le pour installation dans la liste des modules disponibles. Après installation, vérifiez qu’il se trouve bien dans la liste des modules installés :

Cependant, cela ne fonctionne évidemment pas pour des certificats auto-signés. Pour cela, nous aurons besoin du package p11-kit. Installez-le à l’aide d’ACS ou de la commande :

yum install p11-kit 

Maintenant, il faut récupérer le certificat du serveur auto-signé au format .cer.

A titre d’exemple, voici une récupération à l’aide du navigateur Google Chrome : https://hostname/index.html

Pour continuer et aller sur le site :

  • Paramètres avancés, puis continuer vers le site…
  • Le certificat doit apparaitre en erreur (sauf s’il est enregistré comme certificat de confiance sur votre poste).
  • Cliquez dessus et affichez le certificat.
  • Allez dans l’onglet Détails puis « Copier dans un fichier… »

Suivez les étapes d’exportation du certificat et choisissez le format X.509 binaire encodé DER (*.cer) :

Puis enregistrez-le sur votre poste.

Ensuite et avec la méthode de votre choix (système de fichiers intégré d’ACS, FTP, SFTP …), nous allons copier le résultat de l’export dans le dossier de l’IFS : /QOpenSys/etc/pki/trust/anchors

Il nous reste à mettre à jour la liste des certificats de confiance avec la commande suivante (dans une session SSH par exemple) : 

update-ca-certificates

Cette commande va enregistrer comme certificats de confiance tous les certificats déposés dans le dossier /QOpenSys/etc/pki/trust/anchors

Si vous souhaitez ne plus faire confiance à un serveur, supprimez-le du répertoire puis re-exécutez la commande : 

update-ca-certificates

Le premier script PHP de cet article fonctionne maintenant correctement avec la vérification du certificat.

CURL TEST

it worked!

Les exemples de cet article traitent de la consommation de ressources https auto-signées en PHP, avec récupération du certificat par le navigateur.

Retrouvez l’article co-écrit par Gautier DUMAS et Calvin Buckley traitant du même sujet, avec l’utilisation de packages Open Source en environnement IBM i comme OpenSSL (pour la récupération du certificat) et curl (pour la partie client http) : ici

Enjoy Open Source on IBM i !

Remerciement à Calvin Buckley de Seiden Group pour l’aide technique et les indications apportées sur le sujet.