Partager via


Se connecter aux services web

Important

Il s’agit de la documentation Azure Sphere (héritée). Azure Sphere (hérité) prend sa retraite le 27 septembre 2027 et les utilisateurs doivent migrer vers Azure Sphere (intégré) pour l’instant. Utilisez le sélecteur de version situé au-dessus du TOC pour afficher la documentation Azure Sphere (intégrée).

Le SDK Azure Sphere comprend la bibliothèque libcurl que les applications générales peuvent utiliser pour se connecter et s’authentifier auprès des services web HTTP et HTTPS. L’authentification serveur et client sont toutes les deux prises en charge, pour que les applications puissent vérifier qu’elles communiquent avec le serveur attendu et puissent prouver au serveur que leur appareil et leur locataire Azure Sphere sont légitimes. L’authentification mutuelle combine les deux.

Le dépôt d’exemples Azure Sphere sur GitHub comprend les exemples curl suivants :

  • HTTPS_Curl_Easy utilise une API synchrone (bloquante) pour l’authentification serveur.
  • HTTPS_Curl_Multi utilise une API asynchrone (non bloquante) pour l’authentification serveur.

Même si l’approche synchrone de l’authentification serveur illustrée dans l’exemple HTTPS_Curl_Easy est assez simple, les applications Azure Sphere doivent en général utiliser la technique asynchrone la plus complexe montrée dans l’exemple HTTPS_Curl_Multi, ainsi qu’un modèle piloté par les événements, monothread et de type epoll.

Le site web libcurl fournit une documentation complète sur l’API C libcurl, ainsi que de nombreux exemples. Les différences entre la bibliothèque cURL et la bibliothèque d’exécution du Kit de développement logiciel (SDK) Azure Sphere sont les suivantes :

Nom de la constante
(définition)
Limites de plage cURL Limites de plage Azure Sphere
CURLOPT_BUFFERSIZE
(taille de la mémoire tampon)
Valeur par défaut : 16 Ko Valeur par défaut : 1536 Ko
CURLOPT_UPLOAD_BUFFERSIZE
(taille de mémoire tampon de chargement)
Valeur par défaut : 64 Ko
Maximum : 2 Mo
Minimum : 16 Ko
Valeur par défaut : 1536 Ko
Maximum : 64 Ko
Minimum : 1536 Ko
CURLOPT_HEADERFUNCTION
(en-tête HTTP complet passé à cette fonction)
Maximum : 100 Ko Maximum : 16 Ko
CURLOPT_DNS_CACHE_TIMEOUT Valeur par défaut : résultats du cache pendant 60 secondes
Maximum : résultats du cache à jamais
Minimum : 0 (ne pas mettre en cache les résultats)
Toutes les valeurs sont remplacées par 0 et les résultats ne sont pas mis en cache.

Configuration requise pour les applications qui utilisent curl

Les applications qui utilisent la bibliothèque curl doivent inclure les fichiers d’en-tête appropriés et fournir des informations sur le locataire et l’hôte Internet dans le manifeste de l’application.

Fichiers d’en-tête

Pour utiliser curl, ajoutez ces fichiers d’en-tête dans votre application :

#include <applibs/storage.h>  // required only if you supply a certificate in the image package
#include <tlsutils/deviceauth_curl.h> // required only for mutual authentication
#include <curl/curl.h>
#include <applibs/networking_curl.h>  // required only if using proxy to connect to the internet

Le fichier d’en-tête storage.h est nécessaire seulement si vous fournissez un ou plusieurs certificats dans le package d’image d’application. L’en-tête deviceauth_curl.h est nécessaire pour effectuer l’authentification mutuelle. L’en-tête networking_curl.h est requis si l’application utilise un proxy pour se connecter à Internet.

Manifeste d’application

Le champ AllowedConnections du manifeste de l’application doit spécifier les hôtes auxquels l’application se connecte. Il doit également contenir le nom de chaque domaine que la connexion peut rencontrer si elle est redirigée. Par exemple, microsoft.com et www.microsoft.com sont nécessaires pour une application qui se connecte à la page d’accueil de Microsoft.

Si l’application utilise une authentification mutuelle, le champ DeviceAuthentication du manifeste doit inclure l’ID de locataire Azure Sphere. Des certificats d’authentification d’appareil sont émis uniquement si l’ID de locataire de l’appareil correspond à celui indiqué dans le manifeste de l’application. Cette restriction est un moyen de défense renforcé : une application exécutée sur un appareil appartenant à un locataire différent (par exemple, celle d’un autre client ou d’une entité non autorisée) ne peut pas s’authentifier auprès du serveur.

Si l’application utilise un proxy, le champ ReadNetworkProxyConfig indique si l’application est autorisée à récupérer la configuration du proxy.

Pendant le développement, vous pouvez trouver l’ID du locataire Azure Sphere actuel à l’aide de la commande azsphere tenant show-selected.

Dans l’exemple suivant, le champ AllowedConnections spécifie que l’application se connecte uniquement à www.example.com, le champ DeviceAuthentication spécifie l’ID de locataire Azure Sphere, ce qui permet à l’application d’utiliser le certificat d’appareil pour l’authentification mutuelle, et le champ ReadNetworkProxyConfig spécifie que l’application peut retreive proxy configuration information.

  "Capabilities": {
    "AllowedConnections": [ "www.example.com" ],
    "Gpio": [],
    "Uart": [],
    "WifiConfig": false,
    "DeviceAuthentication": "00000000-0000-0000-0000-000000000000",
    "ReadNetworkProxyConfig": true
  }

Fonctionnalités prises en charge

Libcurl pour Azure Sphere prend uniquement en charge les protocoles HTTP et HTTPS. De plus, le système d’exploitation Azure Sphere ne prend pas en charge certaines fonctionnalités, telles que les fichiers accessibles en écriture (cookies) et les sockets UNIX. Les fonctionnalités qui ne seront pas prises en charge dans les versions futures de libcurl, telles que la famille mprintf(), ne sont pas disponibles.

Libcurl pour Azure Sphere prend en charge TLS 1.2 et TLS 1.3 et a mis hors service TLS 1.0 et TLS 1.1 conformément à la stratégie de sécurité Microsoft TLS plus large.

Les suites de chiffrement prises en charge sont les suivantes :

  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
  • TLS_DHE_RSA_WITH_AES_128_CBC_SHA256

Les tentatives d’utilisation d’une version non prise en charge de TLS retournent l’erreur CyaSSL does not support <version>.

Authentification du serveur

Azure Sphere prend en charge l’authentification serveur par le biais de libcurl. Le certificat du serveur doit être signé par une autorité de certification (CA) approuvée par l’appareil. Pour que libcurl authentifie un serveur, l’application doit fournir le chemin du fichier d’autorité de certification.

Ajouter des certificats d’autorité de certification au package d’images

Pour utiliser une ou plusieurs autorités de certification, vous devez ajouter des certificats à votre package d’images. Chaque certificat doit être encodé en base 64. L’approche la plus simple consiste à créer un fichier unique contenant tous les certificats supplémentaires. Le fichier doit avoir l’extension de nom de fichier « .pem ». Pour ajouter des certificats :

  1. Créez un dossier de certificats dans le dossier du projet de votre application. Le dossier du projet contient le fichier CMakeLists de votre application.
  2. Dans le dossier de certificats, créez un fichier texte portant l’extension .pem, copiez-y chaque certificat, puis enregistrez le fichier.
  3. Dans le fichier CMakeLists.txt, ajoutez le fichier de certificat au package d’images en tant que fichier de ressources. Par exemple :
azsphere_target_add_image_package(${PROJECT_NAME} RESOURCE_FILES "certs/DigiCertGlobalRootCA.pem")

Le fichier de certificat doit maintenant s’afficher dans le dossier de certificats du package d’image.

Définir les emplacements des certificats

Dans votre application, utilisez les options CURLOPT_CAPATH et CURLOPT_CAINFO pour définir les emplacements des certificats. Appelez Storage_GetAbsolutePathInImagePackage pour récupérer le chemin absolu des certificats dans le package d’image, puis appelez curl_easy_setopt.

CURLOPT_CAPATH définit un dossier par défaut pour les certificats. Par exemple, le code suivant indique à curl de rechercher les certificats dans le dossier certs de l’image :

char *path = Storage_GetAbsolutePathInImagePackage("certs");
curl_easy_setopt(curl_handle, CURLOPT_CAPATH, path);

CURLOPT_CAINFO définit un chemin d’un fichier qui contient un ou plusieurs certificats. Curl parcourt ce fichier en plus du dossier par défaut défini dans CURLOPT_CAPATH. Par exemple :

char *path = Storage_GetAbsolutePathInImagePackage("CAs/mycertificates.pem");
curl_easy_setopt(curl_handle, CURLOPT_CAINFO, path);

Ce code indique à curl d’approuver toutes les autorités de certification qui sont définies dans le fichier mycertificates.pem, en plus des autorités de certification qui sont définies dans le répertoire défini dans CURLOPT_CAPATH.

Authentification mutuelle

L’authentification mutuelle vérifie que le serveur et l’appareil client sont légitimes. Ce processus comprend plusieurs étapes :

  1. L’application authentifie le serveur à l’aide d’un certificat d’autorité de certification, comme décrit dans Authentification server.
  2. L’application présente un certificat d’authentification client x509 au serveur afin que le serveur puisse authentifier l’appareil.
  3. Le serveur utilise la chaîne de certificats du locataire Azure Sphere pour vérifier que l’appareil appartient au locataire.

Une application peut configurer le côté appareil de l’authentification mutuelle de deux manières :

  • Configurez la fonction Azure Sphere DeviceAuth_CurlSslFunc comme fonction SSL qui effectue l’authentification.
  • Créez une fonction SSL personnalisée qui appelle la fonction Azure Sphere DeviceAuth_SslCtxFunc pour l’authentification.

Remarque

Azure Sphere ne prend pas en charge la renégociation SSL/TLS.

Avant d’utiliser l’une ou l’autre des fonctions, vous devez mettre à jour le fichier CMakeLists.txt de votre application pour ajouter curl et tlsutils à TARGET_LINK_LIBRARIES :

TARGET_LINK_LIBRARIES(${PROJECT_NAME} applibs pthread gcc_s c curl tlsutils)

Utiliser DeviceAuth_CurlSslFunc

La façon la plus simple de procéder à l’authentification de l’appareil consiste à configurer DeviceAuth_CurlSslFunc en tant que fonction de rappel pour l’authentification SSL curl :

// Set DeviceAuth_CurlSslFunc to perform authentication
CURLcode err = curl_easy_setopt(_curl, CURLOPT_SSL_CTX_FUNCTION, DeviceAuth_CurlSslFunc);
if (err) {
	// Set ssl function failed
	return err;
}

La fonction DeviceAuth_CurlSslFunc récupère la chaîne d’approbation pour le locataire Azure Sphere actuel et configure la connexion curl pour effectuer l’authentification mutuelle. Si l’authentification échoue, la fonction retourne CURLE_SSL_CERTPROBLEM.

Utiliser DeviceAuth_SslCtxFunc

Une application peut également utiliser une fonction de rappel SSL personnalisée qui appelle la fonction Azure Sphere DeviceAuth_SslCtxFunc pour l’authentification.

Votre fonction SSL personnalisée doit appeler DeviceAuth_SslCtxFunc pour effectuer l’authentification, mais elle peut également effectuer d’autres tâches liées à l’authentification. DeviceAuth_SslCtxFunc retourne une valeur de l’énumération DeviceAuthSslResult, qui fournit des informations détaillées sur l’échec. Par exemple :

static CURLcode MyCallback(CURL *curl, void *sslctx, void *userCtx)
{
    int err = DeviceAuth_SslCtxFunc(sslctx);
    Log_Debug("ssl func callback error %d\n", err);
    if (err) {
        // detailed error handling code goes here
    }
    return CURLE_OK;
}
...

err = curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, MyCallback);
    if (err) {
        goto cleanupLabel;
    }

Utiliser la chaîne de certificats du locataire sur votre serveur

Pour effectuer une authentification mutuelle, le serveur doit être en mesure de vérifier que l’appareil appartient à votre locataire Azure Sphere et que le locataire lui-même est légitime. Pour effectuer cette authentification, le serveur a besoin de la chaîne de certificats du locataire Azure Sphere, qui signe tous vos appareils Azure Sphere :

Pour obtenir la chaîne de certificats pour votre locataire, téléchargez-la dans un fichier .p7b, comme dans l’exemple suivant :

azsphere ca-certificate download-chain --destination CA-cert-chain.p7b

Vous pouvez ensuite utiliser le fichier .p7b sur votre serveur.

Conseils supplémentaires pour l’utilisation de curl

Voici quelques conseils supplémentaires concernant l’utilisation de curl dans une application Azure Sphere.

  • Si vous envisagez de stocker du contenu de page dans la mémoire RAM ou flash, n’oubliez pas que le stockage sur les appareils Azure Sphere est limité.

  • Pour faire en sorte que curl suive les redirections, ajoutez ceci à votre code :

    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
    
  • Pour ajouter des informations détaillées sur les opérations curl qui peuvent être utiles lors du débogage :

    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
    
  • Certains serveurs retournent des erreurs si une requête ne contient pas d’agent utilisateur. Pour définir un agent utilisateur :

    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
    
  • Lorsque vous gérez curl_multi rappels du minuteur, évitez les appels récursifs lorsque le délai d’expiration signalé est de 0 ms, car cela peut entraîner un comportement imprévisible. Au lieu de cela, traitez 0ms comme 1ms en déclenchant un EventLoopTimer (0ms EventLoopTimers sont également récursifs et doivent être évités).

    static int CurlTimerCallback(CURLM *multi, long timeoutMillis, void *unused)
    {
         // A value of -1 means the timer does not need to be started.
         if (timeoutMillis != -1) {
    
             if (timeoutMillis == 0) {
                 // We cannot queue an event for 0ms in the future (the timer never fires)
                 // So defer it very slightly (see https://curl.se/libcurl/c/multi-event.html)
                 timeoutMillis = 1;
             }
    
             // Start a single shot timer with the period as provided by cURL.
             // The timer handler will invoke cURL to process the web transfers.
             const struct timespec timeout = {.tv_sec = timeoutMillis / 1000,
                                              .tv_nsec = (timeoutMillis % 1000) * 1000000};
             SetEventLoopTimerOneShot(curlTimer, &timeout);
         }
    
         return 0;
    }