Mon voyage dans le nuage (25) : ESP32 + AWS = envoi sécurisé de données

16 mai 2018, 16:21
Dans la Management Console (console de gestion), le service web Amazon (AWS) affiche le nombre de messages MQTT envoyés.
Dans la Management Console (console de gestion), le service web Amazon (AWS) affiche le nombre de messages MQTT envoyés.
Dans l'épisode précédent, nous avons réalisé, à l'aide du kit ESP32 Pico et d’un peu de câblage, un appareil IdO capable d'envoyer des mesures dans le nuage et que l'on peut commander depuis celui-ci. Comme plateforme de nuage, nous avons utilisé la version Maker d'AllThingsTalk. Il existe de nombreux sites Web qui donnent un accès gratuit et configurable par l'utilisateur après une simple inscription. On peut y afficher les mesures d'un capteur sous forme de courbe et également y créer une mini-interface de commande.

Amazon Web Services
Il existe cependant beaucoup d'autres plateformes gratuites pour le nuage. De nombreuses solutions IdO visibles, par exemple, dans des salons comme Embedded World, utilisent Amazon Web Services (AWS). Cette plateforme est très puissante, robuste et sécurisée et est devenue en quelque sorte une norme industrielle. Des services connus, comme Dropbox, reposent sur AWS. En particulier pour l'Internet des objets, Amazon a développé « AWS IoT Core ». Les entreprises et les particuliers peuvent en théorie y enregistrer des millions de cartes de mesure qui accumulent des flux de données dans une base, font des calculs statistiques sur ces données, exécutent des procédures pour réguler des systèmes, etc. Les minutes de connexion et les messages se comptent par millions. Celui qui, comme moi, souhaite un jour essayer, dispose gratuitement de quelque 500 000 messages pour 12 mois.

Avant toute chose : débuter un projet dans AWS et être capable de programmer une carte de mesure dans ce cadre, représente un gros investissement en temps. Il faut commencer par ouvrir un compte AWS. Pour s'inscrire, une adresse de courriel et un mot de passe ne sont pas suffisants, il faut également indiquer une adresse postale, un numéro de carte de crédit pour la facturation et un numéro de téléphone. Ce dernier fait l'objet d'une vérification : un robot vous appelle et vous demande de saisir un nombre à quatre chiffres que vous aurez reçu sur l'écran de votre PC. Je précise que le numéro de téléphone doit être saisi complet (avec indicatif du pays) dans le champ prévu à cet effet, sans aucun espace, sans quoi vous ne serez pas rappelé.

Ensuite, le mieux est de suivre le tutoriel Commencer à utiliser AWS IoT Core. Il faut un peu de temps pour se familiariser avec la terminologie AWS. Ce n'est pas très facile car un certain nombre de notions anglaises sont parfois traduites, parfois non (en outre, dans le tutoriel français, apparaissent des écrans avec des menus en anglais). C'est bon à savoir : Registry est le terme utilisé pour la gigantesque base de données AWS dans laquelle on enregistre les appareils. Device (appareil) et Thing (objet) désignent pratiquement la même chose (plus exactement un Thing est un appareil virtuel qui, dans le nuage, représente un appareil réel).

La sécurité est prioritaire

La notion de sécurité recouvre un grand savoir-faire. Tous les ordinateurs, cartes et smartphones du monde entier communiquent avec AWS en mode chiffré en utilisant le protocole Transport Layer Security (TLS), qui repose sur TCP/IP. Je cite rapidement l'article en français de Wikipédia, qui en décrit vraiment bien le principe de fonctionnement :

Lorsqu'un utilisateur se connecte à un site web qui utilise TLS, les étapes suivantes ont lieu :

  1. Le navigateur du client envoie au serveur une demande de mise en place de connexion sécurisée par TLS.
  2. Le serveur envoie au client son certificat (voir l'article concerné pour plus de détails) : celui-ci contient sa clé publique, ses informations (nom de la société, adresse postale, pays, e-mail de contact...) ainsi qu'une signature numérique sous forme de texte chiffré.
  3. Le navigateur du client tente de déchiffrer la signature numérique du certificat du serveur en utilisant les clés publiques contenues dans les certificats des autorités de certifications (AC) intégrés par défaut dans le navigateur.
    1. Si l'une d'entre elles fonctionne, le navigateur web en déduit le nom de l'autorité de certification qui a signé le certificat envoyé par le serveur. Il vérifie que celui-ci n'est pas expiré puis envoie une demande OCSP à cette autorité pour vérifier que le certificat du serveur n'a pas été révoqué.
    2. Si aucune d'entre elles ne fonctionne, le navigateur web tente de déchiffrer la signature numérique du certificat du serveur à l'aide de la clé publique contenue dans celui-ci.
      1. En cas de réussite, cela signifie que le serveur web a lui-même signé son certificat. Un message d'avertissement s'affiche alors sur le navigateur web, prévenant l'utilisateur que l'identité du serveur n'a pas été vérifiée par une autorité de certification et qu'il peut donc s'agir potentiellement d'un site frauduleux.
      2. En cas d'échec, le certificat est invalide, la connexion ne peut pas aboutir.
  4. Le navigateur du client génère une clé de chiffrement symétrique (à la différence des clés privés et publiques utilisés par les certificats qui sont asymétriques), appelée clé de session, qu'il chiffre à l'aide de la clé publique contenue dans le certificat du serveur puis transmet cette clé de session au serveur.
  5. Le serveur déchiffre la clé de session envoyée par le client grâce à sa clé privée.
  6. Le client et le serveur commencent à s'échanger des données en chiffrant celles-ci avec la clé de session qu'ils ont en commun. On considère à partir de ce moment que la connexion TLS est alors établie entre le client et le serveur.
  7. Une fois la connexion terminée (déconnexion volontaire de l'utilisateur ou si durée d’inactivité trop élevée), le serveur révoque la clé de session.
Optionnel : si le serveur nécessite également que le client s'authentifie, le client lui envoie son propre certificat en même temps que la clé de session. Le serveur procède alors comme détaillé au point n°3 pour vérifier que le certificat du client est valide.

Pour la communication d'une carte avec AWS via TCP/IP sécurisé par TLS, il faut trois codes de chiffrement qui doivent par la suite être intégrés au micrologiciel de l'appareil :
  1. Certificate (certificat)
  2. Private Key (clé privée)
  3. Root Certificate (certificat racine)
Pour la communication TLS, un 4e code de chiffrement est nécessaire, la Public Key (clé publique). Toutefois l'appareil n’a pas besoin d’en avoir connaissance. Le certificat et la Private Key sont calculés individuellement par AWS lorsque l'on enregistre un appareil selon le tutoriel. Il en résulte deux fichiers de chaînes de caractères qui doivent être téléchargés et que l'on peut ouvrir avec un éditeur comme Notepad++. Mais ce n'est pas tout. Il faut aussi établir des directives appelées Policies. Il s'agit principalement de règles indiquant ce que l'appareil « a le droit » de faire dans le nuage. MQTT intervient ici encore. Comme avec AllThingsTalk, notre appareil se connectera en effet ultérieurement comme client MQTT à un courtier MQTT qu'AWS met à disposition. Pour envoyer des mesures dans le nuage, nous avons toujours besoin des commandes MQTT CONNECT et PUBLISH. Nous devons aussi permettre à l'appareil de se connecter au courtier et de publier des messages sur un Topic donné. Le mieux est de suivre le tutoriel pas à pas. Il propose par exemple de saisir :
 
arn:aws:iot:us-east-1:123456789012:topic/my/topic/here

dans le champ du Topic autorisé. Il faut bien sûr remplacer « my/topic/here » par le Topic « $aws/things/<DEVICENAME>/shadow/update ». L'ensemble du champ doit être saisi :
 
arn:aws:iot:<REGION>:<ACCOUNTID>:topic/$aws/things/<DEVICENAME>/shadow/update

Vous trouverez l'ID du compte Account-ID en cliquant sur le nom d'utilisateur, en haut à droite de la console de gestion IdO AWS (IoT Management Console), puis en sélectionnant « My Account ». Cet accès web s'utilise pour tout ce qui concerne votre compte parsonnel AWS. Une fois la totalité les étapes du tutoriel effectuées, la Management Console doit ressembler à cette copie d'écran.



Vous voyez que j'ai baptisé mon premier appareil (device) AWS « MyJourneyIoTDevice ». Nous voyons aussi que le menu de gauche est dans la langue locale (je prie les lecteurs non germanophones de m'en excuser, je n'ai pas la possibilité de changer cela). Et enfin, vous voyez que j'avais oublié de remplacer la région par défaut « Ohio » par « EU (Francfort) ». Pour moi, avec l'expression ci-dessus, la <REGION> est = « us-east-2 ».

L'ESP32 apprend le chiffrement TLS

Ouf, ce n'est pas encore gagné, mais je vois le bout du tunnel. Il faut maintenant que je fasse communiquer ma carte avec AWS. Il fallait adapter ma bibliothèque TCP/IP et j'ai dû faire beaucoup de recherches sur Google et d'essais pour passer du TCP/IP standard au TCP/IP sécurisé TLS. Vous vous souvenez peut-être que ma bibliothèque TCP est pour l'essentiel un emballage autour de fonctions de la classe Arduino WiFiClient que les développeurs d'Espressif ont gracieusement implémenté pour l'ESP32. Mais il y a aussi une classe WiFiClientSecure, censée implémenter les opérations TCP/IP protégées par TLS. Pour aboutir rapidement, j'ai grosso modo dupliqué ma bibliothèque TCP/IP puis ajouté aux noms de fichiers et de classes le suffixe « Secure ». En fait, les modifications du code lui-même de la nouvelle bibliothèque TCPClientSecure par rapport à la TCPClient sont minimales (voir la copie d'écran).



Pour la communication TLS, le constructeur de l'objet, communique les trois chaînes de caractères évoquées ci-dessus au compilateur. Il est possible de les coder directement dans le programme, et, dans ce cas il faut toujours les diviser par blocs de 64 caractères séparés par un retour chariot \n. Je peux vous montrer le certificat Root sans risque, c'est de toute façon toujours le même. Pour les deux autres chaînes de caractères, j'ai créé leur propre nom de fichier AWS_Certificate.h . Chaque fichier est intégré à l'aide d'une instruction include dans le TCPClientSecure.cpp. Vous trouverez un modèle de ces fichiers en téléchargement, vous devez naturellement les compléter avec votre certificat ou, le cas échéant, votre clé.

Comme la bibliothèque MQTT attend un objet de type Typ TCPClient, mais que je n'ai besoin que d'un objet de type TCPClientSecure, j'ai également dupliqué la bibliothèque MQTT et là encore simplement ajouté « Secure » aux noms de fichiers et de classes. Finalement les deux bibliothèques TCP/IP et MQTT sont chacune en version normale et en version protection par TLS.

Mise à jour des répliques (shadows)

Pour une petite démonstration je suis parti du matériel et du programme principal utilisé lors de l'épisode 23. Depuis la page de celui-ci, téléchargez le code et comparez-le avec celui du nouveau croquis que vous pouvez télécharger ci-dessous. Comme paramètres individuels, nous avons bien sûr à nouveau besoin du SSID et du Mot de passe du routeur de notre réseau Wi-Fi. Il y a également un Device ID (comme pour travailler avec AllThingsTalk). Dans mon cas, il s'agit de « MyJourneyIoTDevice ». En contrepartie, il n'y a plus de Device Token puisque l'authentification est assurée par le certificat. C'est pourquoi l'adresse du courtier MQTT est individuelle avec AWS. J'ai donc adapté le site Web de configuration pour pouvoir saisir l'adresse du courtier dans le 5e champ. Pour trouver l'adresse du serveur de votre courtier, allez à la Management Console et cliquez sur l'appareil (Device) puis dans le menu de l'appareil, sélectionnez « Interagir ». L'adresse du serveur apparaît tout en haut de la fenêtre. Dans le champ grisé suivant, vous pouvez voir le Topic, pour envoyer des mesures à une shadow , pour moi :
 
$aws/things/MyJourneyIoTDevice/shadow/update

(voir la copie d'écran).



Qu'est-ce qu'un objet shadow ? Le terme shadow (ou réplique) (Schatten en allemand, comme sur les copies de document de cet épisode) désigne une représentation des états d'un nœud IdO (capteur ou actionneur) sous la forme de documents JSON. Nous nous souvenons que nous avons également utilisé la notation JSON pour envoyer des mesures à AllThingsTalk. Ici avec AWS, un document JSON valable ressemble par exemple à ceci :
{
  "desired": {
    "temp": "32"
  }
}

J'ai enregistré ce document dans l'éditeur JSON du site Device sous la rubrique de menu « Shadow » (Schatten, voir la copie d'écran), pour définir les mesures que mon capteur peut envoyer.



Pour le premier essai, je me suis contenté d'envoyer périodiquement à AWS de 10 à 40 valeurs de « température » successives (voir le croquis commenté). Pour récompense de ma peine, j'ai observé avec satisfaction qu'après l'envoi d'un message MQTT, la nouvelle température apparaissait au rafraîchissement de l'affichage de la réplique. Incidemment, je n'ai eu aucune coupure de communication pendant des heures.

La suite au prochain épisode !
Pièce(s) jointe(s)
Firmware Software Exec icon png
MyJourneyIoT25 Software
Chargement des commentaires...
articles apparentés