Herstellen einer Verbindung mit Webdiensten
Das Azure Sphere SDK enthält die bibliothek libcurl, die allgemeine Anwendungen zum Herstellen einer Verbindung und Authentifizierung mit HTTP- und HTTPS-Webdiensten verwenden können. Sowohl die Server- als auch die Clientauthentifizierung werden unterstützt, damit Anwendungen überprüfen können, ob sie mit dem erwarteten Server kommunizieren und dem Server nachweisen können, dass ihr Gerät und ihr Azure Sphere-Mandant legitim sind. Bei der gegenseitigen Authentifizierung werden beides kombiniert.
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 Beispiel 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 im Allgemeinen die komplexere asynchrone Technik verwenden, die im HTTPS_Curl_Multi Beispiel gezeigt wird, zusammen mit einem epoll-basierten, ereignisgesteuerten Singlethreadmuster.
Die libcurl-Website bietet eine ausführliche Dokumentation der libcurl C-API und viele Beispiele. Die Unterschiede zwischen der cURL Library und der Azure Sphere SDK-Laufzeitbibliothek sind wie folgt:
Konstantenname (Definition) |
cURL Bereichsgrenzwerte | Azure Sphere-Bereichsbeschränkungen |
---|---|---|
CURLOPT_BUFFERSIZE (Puffergröße) |
Standard: 16 KB | Standard: 1536 KB |
CURLOPT_UPLOAD_BUFFERSIZE (Puffergröße hochladen) |
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: Zwischenspeichern der Ergebnisse für 60 Sekunden Maximum: Zwischenspeichern von Ergebnissen 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 zu verwenden, 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 die gegenseitige Authentifizierung erforderlich. Der networking_curl.h-Header ist erforderlich, wenn die Anwendung einen Proxy verwendet, um eine Verbindung mit dem Internet herzustellen.
Anwendungsmanifest
Das Feld AllowedConnections des Anwendungsmanifests muss die Hosts angeben, mit denen die Anwendung eine Verbindung herstellt. Sie muss auch den Namen jeder Domäne enthalten, die bei der Umleitung der Verbindung auftreten kann. Beispielsweise sind sowohl als www.microsoft.com
auch microsoft.com
für eine Anwendung erforderlich, die eine Verbindung mit der Microsoft-Startseite herstellt.
Wenn die Anwendung die 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 eine umfassende Verteidigung: Eine Anwendung, die auf einem Gerät in einem anderen Mandanten (z. B. dem eines anderen Kunden oder einer nicht autorisierten Entität) ausgeführt wird, kann sich nicht beim Server authentifizieren.
Wenn die Anwendung einen Proxy verwendet, gibt das Feld ReadNetworkProxyConfig an, ob die Anwendung über die Berechtigung zum Abrufen der Proxykonfiguration verfügt.
Während der Entwicklung können Sie die ID des aktuellen Azure Sphere-Mandanten mithilfe des Befehls azsphere tenant show-selected ermitteln.
Im folgenden Beispiel gibt das Feld AllowedConnections an, dass die Anwendung nur www.example.com
eine Verbindung mit herstellt, das Feld DeviceAuthentication die Azure Sphere-Mandanten-ID angibt, sodass die Anwendung das Gerätezertifikat für die gegenseitige Authentifizierung verwenden kann, und das Feld ReadNetworkProxyConfig gibt an, dass die Anwendung Proxykonfigurationsinformationen erneut erfassen 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 Protokolle HTTP und HTTPS. Darüber hinaus unterstützt das Azure Sphere-Betriebssystem einige Funktionen nicht, z. B. beschreibbare Dateien (Cookies) oder UNIX-Sockets. Features, die in zukünftigen libcurl-Releases nicht unterstützt werden, z. B. die mprintf() -Familie, 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.
Im Folgenden werden die unterstützten Verschlüsselungssammlungen aufgeführt:
- 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
Versuche, eine nicht unterstützte Version von TLS zu verwenden, geben den Fehler CyaSSL does not support <version>
zurück.
Serverauthentifizierung
Azure Sphere unterstützt die Serverauthentifizierung über libcurl. Das Zertifikat des Servers muss von einer Zertifizierungsstelle signiert werden, der das Gerät vertraut. Damit libcurl einen Server authentifizieren kann, muss die Anwendung den Pfad zur Zertifizierungsstellendatei angeben.
Hinzufügen von Zertifizierungsstellenzertifikaten zum Imagepaket
Um eine oder mehrere Zertifizierungsstellen zu verwenden, müssen Sie die 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 Dateierweiterung PEM aufweisen. So fügen Sie Zertifikate hinzu:
- Erstellen Sie einen Ordner certs im Projektordner für Ihre Anwendung. Der Projektordner enthält die CMakeLists-Datei für Ihre Anwendung.
- Erstellen Sie im Ordner certs eine Textdatei mit der Erweiterung .pem, kopieren Sie jedes Zertifikat hinein, und speichern Sie die Datei.
- Fügen Sie in der CMakeLists.txt-Datei die Zertifikatdatei dem Imagepaket als Ressourcendatei hinzu. Zum Beispiel:
azsphere_target_add_image_package(${PROJECT_NAME} RESOURCE_FILES "certs/DigiCertGlobalRootCA.pem")
Die Zertifikatdatei sollte nun im Ordner certs im Imagepaket angezeigt werden.
Festlegen von Zertifikatspeicherorten
Verwenden Sie in Ihrer Anwendung die Optionen CURLOPT_CAPATH und CURLOPT_CAINFO , um die Speicherorte der Zertifikate festzulegen. Rufen Sie Storage_GetAbsolutePathInImagePackage auf, um den absoluten Pfad zu den Zertifikaten im Imagepaket abzurufen, und rufen Sie dann curl_easy_setopt auf.
CURLOPT_CAPATH legt einen Standardordner für die Zertifikate fest. Der folgende Code weist curl beispielsweise an, im Ordner certs in der Abbildung nach Zertifikaten zu suchen:
char *path = Storage_GetAbsolutePathInImagePackage("certs");
curl_easy_setopt(curl_handle, CURLOPT_CAPATH, path);
CURLOPT_CAINFO legt einen Pfad zu einer Datei fest, die mindestens ein Zertifikat enthält. Curl durchsucht diese Datei zusätzlich zum Standardordner, der in CURLOPT_CAPATH festgelegt ist. Zum 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
Die gegenseitige Authentifizierung überprüft, ob sowohl der Server als auch das Clientgerät legitim sind. Es handelt sich um einen mehrstufigen Prozess:
- Die Anwendung authentifiziert den Server mithilfe eines Zertifizierungsstellenzertifikats, wie unter Serverauthentifizierung beschrieben.
- Die Anwendung stellt dem Server ein x509-Clientauthentifizierungszertifikat vor, damit der Server das Gerät authentifizieren kann.
- Der Server verwendet die Zertifikatkette des Azure Sphere-Mandanten, um zu überprüfen, ob das Gerät zum Mandanten gehört.
Eine Anwendung kann die Geräteauthentifizierungsseite der gegenseitigen Authentifizierung auf zwei Arten einrichten:
- Konfigurieren Sie die Azure Sphere-DeviceAuth_CurlSslFunc-Funktion als SSL-Funktion, die die Authentifizierung ausführt.
- Erstellen Sie eine benutzerdefinierte SSL-Funktion, die die Azure Sphere-DeviceAuth_SslCtxFunc-Funktion für die Authentifizierung aufruft.
Hinweis
Azure Sphere unterstützt keine SSL-/TLS-Neuverhandlung.
Bevor Sie eine der funktionen verwenden, müssen Sie die CMakeLists.txt-Datei für Ihre Anwendung aktualisieren, um curl und tlsutils TARGET_LINK_LIBRARIES hinzuzufügen:
TARGET_LINK_LIBRARIES(${PROJECT_NAME} applibs pthread gcc_s c curl tlsutils)
Verwenden von DeviceAuth_CurlSslFunc
Die einfachste Möglichkeit zum Durchführen der Geräteauthentifizierung besteht darin, DeviceAuth_CurlSslFunc als Rückruffunktion für die curl-SSL-Authentifizierung zu konfigurieren:
// 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 Zertifikatkette für den aktuellen Azure Sphere-Mandanten ab und richtet die curl-Verbindung ein, um die gegenseitige Authentifizierung durchzuführen. Wenn die Authentifizierung fehlschlägt, 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 DeviceAuth_SslCtxFunc-Funktion 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 zurück, der DeviceAuthSslResult
detaillierte Informationen zum Fehler bereitstellt. 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 Mandantenzertifikatkette auf Ihrem Server
Für die gegenseitige Authentifizierung muss der Server überprüfen können, ob das Gerät zu Ihrem Azure Sphere-Mandanten gehört und dass der Mandant selbst legitim ist. Für diese Authentifizierung benötigt der Server die Zertifikatkette des Azure Sphere-Mandanten, die alle Ihre Azure Sphere-Geräte signiert:
Um die Zertifikatkette für Ihren Mandanten abzurufen, laden Sie sie wie im folgenden Beispiel in eine P7B-Datei herunter:
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 für die Verwendung von curl
Hier finden Sie einige zusätzliche Tipps für die Verwendung von curl in einer Azure Sphere-Anwendung.
Wenn Sie Planen, Seiteninhalte im RAM oder Flash zu speichern, beachten Sie, dass der Speicher auf dem Azure Sphere-Gerät begrenzt ist.
Um sicherzustellen, dass curl Umleitungen folgt, fügen Sie Dem Code Folgendes hinzu:
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
So fügen Sie ausführliche Informationen zu curl-Vorgängen hinzu, die während des Debuggens hilfreich sein können:
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 von curl_multi Timerrückrufen rekursive Aufrufe, wenn das gemeldete Timeout 0 ms beträgt, da dies zu unvorhersehbarem Verhalten führen kann. Behandeln Sie stattdessen 0ms als 1 ms, indem Sie einen EventLoopTimer auslösen (0 ms EventLoopTimer 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; }