Freigeben über


Verbinden mit Webserverdiensten

Wichtig

Dies ist die Dokumentation zu Azure Sphere (Legacy). Azure Sphere (Legacy) wird am 27. September 2027 eingestellt, und Benutzer müssen bis zu diesem Zeitpunkt zu Azure Sphere (integriert) migrieren. Verwenden Sie die Versionsauswahl oberhalb des Inhaltsverzeichniss, um die Dokumentation zu Azure Sphere (Integriert) anzuzeigen.

Das Azure Sphere SDK enthält die libcurl-Bibliothek, mit der allgemeine Anwendungen eine Verbindung mit HTTP- und HTTPS-Webdiensten herstellen und die Authentifizierung ausführen können. Sowohl Server- als auch Clientauthentifizierung werden unterstützt, sodass Anwendungen überprüfen können, ob sie mit dem erwarteten Server kommunizieren und dem Server nachweisen können, dass ihr Gerät und der Azure Sphere-Mandant legitim sind. Gegenseitige Authentifizierung kombiniert die beiden Typen.

Das Azure Sphere-Beispielrepository auf GitHub enthält die folgenden curl-Beispiele:

  • HTTPS_Curl_Easy verwendet eine synchrone (blockierende) API für die Serverauthentifizierung.
  • HTTPS_Curl_Multi Sample verwendet eine asynchrone (nicht blockierende) API für die Serverauthentifizierung.

Obwohl der synchrone Ansatz für die Serverauthentifizierung in HTTPS_Curl_Easy recht einfach ist, sollten Azure Sphere-Anwendungen in der Regel das komplexere asynchrone Verfahren verwenden, das im HTTPS_Curl_Multi-Beispiel gezeigt wird, zusammen mit einem epoll-basierten, ereignisgesteuerten Singlethreadmuster.

Die libcurl-Website enthält eine umfassende Dokumentation der libcurl-C-API und zahlreiche Beispiele. Unterschiede zwischen der cURL-Bibliothek und der Azure Sphere SDK-Laufzeitbibliothek sind wie folgt:

Konstanter Name
(Definition)
cURL-Bereichsbeschränkungen Azure Sphere-Bereichsbeschränkungen
CURLOPT_BUFFERSIZE
(Puffergröße)
Standard: 16 KB Standard: 1536 KB
CURLOPT_UPLOAD_BUFFERSIZE
(Größe des Uploadpuffers)
Standard: 64 KB
Maximal: 2 MB
Minimum: 16 KB
Standard: 1536 KB
Maximal: 64 KB
Minimum: 1536 KB
CURLOPT_HEADERFUNCTION
(vollständiger HTTP-Header, der an diese Funktion übergeben wird)
Maximal: 100 KB Maximal: 16 KB
CURLOPT_DNS_CACHE_TIMEOUT Standard: Cacheergebnisse für 60 Sekunden
Maximum: Cacheergebnisse für immer
Minimum: 0 (ergebnisse nicht zwischenspeichern)
Alle Werte werden auf 0 überschrieben, und Die Ergebnisse werden nicht zwischengespeichert.

Anforderungen für Anwendungen, die curl verwenden

Anwendungen, die die curl-Bibliothek verwenden, müssen die entsprechenden Headerdateien enthalten und Mandanten- und Internethostinformationen im Anwendungsmanifest bereitstellen.

Headerdateien

Um curl verwenden zu können, schließen Sie die folgenden Headerdateien in Ihre Anwendung ein:

#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

Die Headerdatei „storage.h“ ist nur erforderlich, wenn Sie mindestens ein Zertifikat im Anwendungsimagepaket angeben. Der deviceauth_curl.h-Header ist für gegenseitige Authentifizierung erforderlich. Der header networking_curl.h ist erforderlich, wenn die Anwendung einen Proxy zum Herstellen einer Internetverbindung verwendet.

Anwendungsmanifest

Das Feld AllowedConnections des Anwendungsmanifests muss die Hosts angeben, mit denen die Anwendung eine Verbindung herstellt. Es muss außerdem den Namen jeder Domäne enthalten, auf die die Verbindung treffen kann, wenn sie umgeleitet wird. Beispielsweise werden sowohl microsoft.com als auch www.microsoft.com für eine Anwendung benötigt, die eine Verbindung mit der Microsoft-Startseite herstellt.

Wenn die Anwendung gegenseitige Authentifizierung verwendet, muss das Feld DeviceAuthentication des Manifests die Azure Sphere-Mandanten-ID enthalten. Geräteauthentifizierungszertifikate werden nur ausgestellt, wenn die Mandanten-ID des Geräts mit der Mandanten-ID im Anwendungsmanifest übereinstimmt. Diese Einschränkung bietet umfassende Schutzmaßnahmen: Eine Anwendung, die auf einem Gerät in einem anderen Mandanten ausgeführt wird (etwa für einen anderen Kunden oder eine nicht autorisierte Entität), kann sich nicht beim Server authentifizieren.

Wenn die Anwendung einen Proxy verwendet, gibt das ReadNetworkProxyConfig-Feld an, ob die Anwendung über die Berechtigung zum Abrufen der Proxykonfiguration verfügt.

Während der Entwicklung finden Sie die ID des aktuellen Azure Sphere-Mandanten mithilfe des azsphere-Mandanten, der ausgewählt ist.

Im folgenden Beispiel gibt das Feld "AllowedConnections " an, dass die Anwendung nur eine www.example.comVerbindung herstellt, das Feld "DeviceAuthentication " gibt die Azure Sphere-Mandanten-ID an, sodass die Anwendung das Gerätezertifikat für die gegenseitige Authentifizierung verwenden kann, und das Feld "ReadNetworkProxyConfig " gibt an, dass die Anwendung Proxykonfigurationsinformationen erneut ausführen kann.

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

Unterstützte Funktionen

Libcurl für Azure Sphere unterstützt nur die HTTP- und HTTPS-Protokolle. Darüber hinaus unterstützt das Azure Sphere-Betriebssystem einige Funktionen nicht. Hierzu zählen beispielsweise schreibbare Dateien (Cookies) und UNIX-Sockets. Features, die in zukünftigen libcurl-Releases nicht unterstützt werden (z.B. die mprintf()-Funktionen), sind nicht verfügbar.

Libcurl für Azure Sphere unterstützt TLS 1.2 und TLS 1.3 und hat TLS 1.0 und TLS 1.1 in Übereinstimmung mit der umfassenderen Microsoft TLS-Sicherheitsstrategie eingestellt.

Folgende Suites mit Verschlüsselungsverfahren werden unterstützt:

  • 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

Bei Verwendung einer nicht unterstützten TLS-Version wird der Fehler CyaSSL does not support <version> zurückgegeben.

Serverauthentifizierung

Azure Sphere unterstützt die Serverauthentifizierung über libcurl. Das Zertifikat des Servers muss von einer Zertifizierungsstelle (Certificate Authority, CA) signiert werden, der das Gerät vertraut. Damit libcurl einen Server authentifizieren kann, muss die Anwendung den Pfad zur ZS-Datei angeben.

Hinzufügen von Zertifizierungsstellenzertifikaten zum Imagepaket

Wenn Sie Zertifizierungsstellen verwenden möchten, müssen Sie die entsprechenden Zertifikate Ihrem Imagepaket hinzufügen. Jedes Zertifikat muss Base64-codiert sein. Der einfachste Ansatz besteht darin, eine einzelne Datei zu erstellen, die alle zusätzlichen Zertifikate enthält. Die Datei muss die PEM-Erweiterung aufweisen. So fügen Sie Zertifikate hinzu:

  1. Erstellen Sie einen Ordner „certs“ im Projektordner für Ihre Anwendung. Der Projektordner enthält die CMakeLists-Datei für Ihre Anwendung.
  2. Erstellen Sie im Ordner „certs“ eine Textdatei mit der PEM-Erweiterung, kopieren Sie jedes Zertifikat in diese Datei, und speichern Sie die Datei.
  3. Fügen Sie in der datei CMakeLists.txt die Zertifikatdatei als Ressourcendatei zum Bildpaket hinzu. Zum Beispiel:
azsphere_target_add_image_package(${PROJECT_NAME} RESOURCE_FILES "certs/DigiCertGlobalRootCA.pem")

Die Zertifikatdatei sollte jetzt im Ordner „certs“ im Imagepaket angezeigt werden.

Festlegen von Zertifikatspeicherorten

Legen Sie in Ihrer Anwendung mithilfe der Optionen CURLOPT_CAPATH und CURLOPT_CAINFO die Speicherorte der Zertifikate fest. Rufen Sie Storage_GetAbsolutePathInImagePackage auf, um den absoluten Pfad der Zertifikate im Imagepaket abzurufen, und rufen Sie anschließend curl_easy_setopt auf.

Durch „CURLOPT_CAPATH“ wird ein Standardordner für die Zertifikate festgelegt. Mit dem folgenden Code wird cURL beispielsweise angewiesen, im Ordner „certs“ des Images nach Zertifikaten zu suchen:

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

„CURLOPT_CAINFO“ dient zum Festlegen eines Pfads zu einer Datei, die mindestens ein Zertifikat enthält. Diese Datei wird von cURL zusätzlich zu dem Standardordner durchsucht, der in „CURLOPT_CAPATH“ festgelegt wurde. Beispiel:

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

Dieser Code weist curl an, allen Zertifizierungsstellen zu vertrauen, die in der Datei „mycertificates.pem“ definiert sind, zusätzlich zu den Zertifizierungsstellen, die in dem in CURLOPT_CAPATH festgelegten Verzeichnis definiert sind.

Gegenseitige Authentifizierung

Gegenseitige Authentifizierung überprüft, ob der Server und das Clientgerät legitim sind. Dies ist ein mehrstufiger Prozess:

  1. Die Anwendung authentifiziert den Server mithilfe eines ZS-Zertifikats, wie unter Serverauthentifizierung beschrieben.
  2. Die Anwendung legt dem Server ein x509-Clientauthentifizierungszertifikat vor, damit der Server das Gerät authentifizieren kann.
  3. Der Server verwendet die Zertifikatkette des Azure Sphere-Mandanten, um zu überprüfen, ob das Gerät dem Mandanten gehört.

Eine Anwendung kann die Geräteauthentifizierungsseite der gegenseitigen Authentifizierung auf zwei Arten einrichten:

  • Konfigurieren der Azure Sphere DeviceAuth_CurlSslFunc-Funktion als SSL-Funktion, die die Authentifizierung ausführt.
  • Erstellen einer benutzerdefinierten SSL-Funktion, die die Azure Sphere-Funktion DeviceAuth_SslCtxFunc für die Authentifizierung aufruft.

Hinweis

Die erneute SSL-/TLS-Verhandlung wird von Azure Sphere nicht unterstützt.

Bevor Sie eine der beiden Funktionen verwenden, müssen Sie die Datei „CMakeLists.txt“ für Ihre Anwendung aktualisieren, um „curl“ und „tlsutils“ zu „TARGET_LINK_LIBRARIES“ hinzuzufügen:

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

Verwenden von DeviceAuth_CurlSslFunc

Die einfachste Art der Geräteauthentifizierung ist die Konfiguration von DeviceAuth_CurlSslFunc als Rückruffunktion für die curl-SSL-Authentifizierung:

// 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;
}

Die Funktion DeviceAuth_CurlSslFunc ruft die Vertrauenskette für den aktuellen Azure Sphere-Mandanten ab und richtet die curl-Verbindung ein, um die gegenseitige Authentifizierung durchzuführen. Ist die Authentifizierung nicht erfolgreich, gibt die Funktion „CURLE_SSL_CERTPROBLEM“ zurück.

Verwenden von DeviceAuth_SslCtxFunc

Eine Anwendung kann auch eine benutzerdefinierte SSL-Rückruffunktion verwenden, die die Azure Sphere-Funktion DeviceAuth_SslCtxFunc für die Authentifizierung aufruft.

Ihre benutzerdefinierte SSL-Funktion muss DeviceAuth_SslCtxFunc aufrufen, um die Authentifizierung durchzuführen, kann aber auch andere Aufgaben im Zusammenhang mit der Authentifizierung ausführen. DeviceAuth_SslCtxFunc gibt einen Wert der Enumeration DeviceAuthSslResult zurück, um ausführliche Fehlerinformationen bereitzustellen. Zum Beispiel:

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;
    }

Verwenden der Zertifikatkette des Mandanten auf Ihrem Server

Zum Durchführen der gegenseitigen Authentifizierung muss der Server verifizieren können, dass das Gerät zu Ihrem Azure Sphere-Mandanten gehört und der Mandant selbst legitim ist. Für die Durchführung dieser Authentifizierung benötigt der Server die Zertifikatkette des Azure Sphere-Mandanten, mit der Ihre gesamten Azure Sphere-Geräte signiert werden:

Sie erhalten die Zertifikatkette für Ihren Mandanten, indem Sie sie wie im folgenden Beispiel in eine P7B-Datei herunterladen:

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

Anschließend können Sie die P7B-Datei auf Ihrem Server verwenden.

Zusätzliche Tipps zum Verwenden von curl

Hier sind einige zusätzliche Tipps für die Verwendung von Curl in einer Azure Sphere-Anwendung.

  • Wenn Sie planen, Seiteninhalte im RAM oder Flashspeicher zu speichern, denken Sie daran, dass der Speicherplatz auf dem Azure Sphere-Gerät begrenzt ist.

  • Um sicherzustellen, dass curl Umleitungen folgt, fügen Sie Ihrem Code Folgendes hinzu:

    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
    
  • Um ausführliche Informationen zu curl-Vorgängen hinzuzufügen, die während des Debuggens hilfreich sein können, gehen Sie folgendermaßen vor:

    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
    
  • Einige Server geben Fehler zurück, wenn eine Anforderung keinen Benutzer-Agent enthält. So legen Sie einen Benutzer-Agent fest:

    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
    
  • Vermeiden Sie bei der Behandlung curl_multi Timerrückrufe rekursive Aufrufe, wenn das gemeldete Timeout 0 ms ist, da dies zu unvorhersehbarem Verhalten führen kann. Behandeln Sie stattdessen 0 ms als 1 ms, indem Sie einen EventLoopTimer auslösen (0ms EventLoopTimers sind auch rekursiv und sollten vermieden werden).

    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;
    }