Verbinding maken met webservices
De Azure Sphere SDK bevat de libcurl-bibliotheek, die toepassingen op hoog niveau kunnen gebruiken om verbinding te maken en te verifiëren met HTTP- en HTTPS-webservices. Zowel server- als clientverificatie worden ondersteund, zodat toepassingen kunnen controleren of ze communiceren met de verwachte server en aan de server kunnen bewijzen dat hun apparaat en Azure Sphere-catalogus legitiem zijn. Wederzijdse verificatie combineert deze twee.
De Azure Sphere-voorbeeldopslagplaats op GitHub bevat de volgende curl-voorbeelden:
- HTTPS_Curl_Easy gebruikt een synchrone (blokkerende) API voor serververificatie.
- HTTPS_Curl_Multi voorbeeld maakt gebruik van een asynchrone (niet-blokkerende) API voor serververificatie.
Hoewel de synchrone benadering van serververificatie in HTTPS_Curl_Easy vrij eenvoudig is, moeten Azure Sphere-toepassingen over het algemeen de complexere asynchrone techniek gebruiken die wordt weergegeven in het HTTPS_Curl_Multi voorbeeld, samen met een op epoll gebaseerd, gebeurtenisgestuurd patroon met één thread.
De libcurl-website biedt uitgebreide documentatie van de libcurl C-API en vele voorbeelden. De verschillen tussen de cURL-bibliotheek en de Azure Sphere SDK-runtimebibliotheek zijn als volgt:
Constante naam (definitie) |
Limieten voor cURL-bereik | Limieten voor Azure Sphere-bereik |
---|---|---|
CURLOPT_BUFFERSIZE (buffergrootte) |
Standaardinstelling: 16 kB | Standaardinstelling: 1536 kB |
CURLOPT_UPLOAD_BUFFERSIZE (buffergrootte uploaden) |
Standaardinstelling: 64 kB Maximum: 2 MB Minimaal: 16 kB |
Standaardinstelling: 1536 kB Maximaal: 64 kB Minimaal: 1536 kB |
CURLOPT_HEADERFUNCTION (volledige HTTP-header doorgegeven aan deze functie) |
Maximum: 100 KB | Maximaal: 16 kB |
CURLOPT_DNS_CACHE_TIMEOUT | Standaardinstelling: resultaten gedurende 60 seconden in de cache opslaan Maximum: resultaten voor altijd in cache opslaan Minimaal: 0 (geen resultaten opslaan in de cache) |
Alle waarden worden overschreven op 0 en resultaten worden niet in de cache opgeslagen. |
Vereisten voor toepassingen die gebruikmaken van curl
Toepassingen die gebruikmaken van de curl-bibliotheek moeten de juiste headerbestanden bevatten en de UUID van de Azure Sphere-tenant (verouderd) en de internethostgegevens in het toepassingsmanifest opgeven.
Koptekstbestanden
Als u curl wilt gebruiken, neemt u deze headerbestanden op in uw toepassing:
#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
Het headerbestand storage.h is alleen vereist als u een of meer certificaten opgeeft in het toepassingsinstallatiekopiepakket. De header deviceauth_curl.h is vereist voor het uitvoeren van wederzijdse verificatie. De header networking_curl.h is vereist als de toepassing een proxy gebruikt om verbinding te maken met internet.
Toepassingsmanifest
Het veld AllowedConnections van het toepassingsmanifest moet de hosts opgeven waarmee de toepassing verbinding maakt. Het moet ook de naam bevatten van elk domein dat de verbinding kan tegenkomen als deze wordt omgeleid. Zowel als microsoft.com
www.microsoft.com
zijn bijvoorbeeld vereist voor een toepassing die verbinding maakt met de Startpagina van Microsoft.
Als de toepassing gebruikmaakt van wederzijdse verificatie, moet het veld DeviceAuthentication van het manifest de UUID van de Azure Sphere-tenant (verouderd) bevatten. Apparaatverificatiecertificaten worden alleen uitgegeven als de catalogus van het apparaat is gekoppeld aan een UUID van een Azure Sphere-tenant (verouderd) die overeenkomt met de tenant-UUID in het toepassingsmanifest. Deze beperking biedt diepgaande verdediging: een toepassing die wordt uitgevoerd op een apparaat in een andere catalogus (bijvoorbeeld die van een andere klant of een rogue-entiteit) kan niet worden geverifieerd bij de server.
Tijdens de ontwikkeling kunt u de verouderde tenant-UUID vinden met behulp van de opdracht az sphere catalog show en de MigratedCatalogId
waarde uit het tags
object extraheren.
Als de toepassing een proxy gebruikt, geeft het veld ReadNetworkProxyConfig aan of de toepassing gemachtigd is om de proxyconfiguratie op te halen.
In het volgende voorbeeld geeft het veld AllowedConnections aan dat de toepassing alleen www.example.com
verbinding maakt met , het veld DeviceAuthentication geeft de Azure Sphere (verouderde) tenant-UUID op, waardoor de toepassing het apparaatcertificaat kan gebruiken voor wederzijdse verificatie, en het veld ReadNetworkProxyConfig geeft aan dat de toepassing proxyconfiguratiegegevens kan ophalen.
"Capabilities": {
"AllowedConnections": [ "www.example.com" ],
"Gpio": [],
"Uart": [],
"WifiConfig": false,
"DeviceAuthentication": "00000000-0000-0000-0000-000000000000",
"ReadNetworkProxyConfig": true
}
Ondersteunde functionaliteit
Libcurl voor Azure Sphere ondersteunt alleen de HTTP- en HTTPS-protocollen. Bovendien biedt het Azure Sphere-besturingssysteem geen ondersteuning voor bepaalde functies, zoals beschrijfbare bestanden (cookies) of UNIX-sockets. Functies die niet worden ondersteund in toekomstige libcurl-releases, zoals de mprintf() -familie, zijn niet beschikbaar.
Libcurl voor Azure Sphere ondersteunt TLS 1.2 en TLS 1.3 en heeft TLS 1.0 en TLS 1.1 buiten gebruik gesteld in overeenstemming met de bredere Microsoft TLS-beveiligingsstrategie.
Hier volgen de ondersteunde coderingssuites:
- 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
Pogingen om een niet-ondersteunde versie van TLS te gebruiken, retourneren de fout CyaSSL does not support <version>
.
Serververificatie
Azure Sphere ondersteunt serververificatie via libcurl. Het certificaat van de server moet zijn ondertekend door een certificeringsinstantie (CA) die het apparaat vertrouwt. Libcurl kan een server alleen verifiëren als de toepassing het pad naar het CA-bestand opgeeft.
CA-certificaten toevoegen aan het installatiekopieënpakket
Als u een of meer CA's wilt gebruiken, moet u de certificaten toevoegen aan uw installatiekopieënpakket. Elk certificaat moet een base-64-codering hebben. De eenvoudigste aanpak is om één bestand te maken dat alle aanvullende certificaten bevat. Het bestand moet de bestandsnaamextensie .pem hebben. Certificaten toevoegen:
- Maak een map met certificaten in de projectmap voor uw toepassing. De projectmap bevat het bestand CMakeLists voor uw toepassing.
- Maak in de map certificaten een tekstbestand met de extensie .pem, kopieer elk certificaat naar het bestand en sla het bestand op.
- Voeg in het CMakeLists.txt-bestand het certificaatbestand als een resourcebestand toe aan het installatiekopieënpakket. Bijvoorbeeld:
azsphere_target_add_image_package(${PROJECT_NAME} RESOURCE_FILES "certs/DigiCertGlobalRootCA.pem")
Het certificaatbestand moet nu worden weergegeven in de map certs in het installatiekopieënpakket.
Certificaatlocaties instellen
Gebruik in uw toepassing de opties CURLOPT_CAPATH en CURLOPT_CAINFO om de locaties van de certificaten in te stellen. Roep Storage_GetAbsolutePathInImagePackage aan om het absolute pad naar de certificaten in het installatiekopieënpakket op te halen en roep vervolgens curl_easy_setopt aan.
CURLOPT_CAPATH stelt een standaardmap in voor de certificaten. De volgende code vertelt curl bijvoorbeeld om te zoeken naar certificaten in de map certs in de afbeelding:
char *path = Storage_GetAbsolutePathInImagePackage("certs");
curl_easy_setopt(curl_handle, CURLOPT_CAPATH, path);
CURLOPT_CAINFO stelt een pad in naar een bestand dat een of meer certificaten bevat. Curl doorzoekt dit bestand naast de standaardmap die is ingesteld in CURLOPT_CAPATH. Bijvoorbeeld:
char *path = Storage_GetAbsolutePathInImagePackage("CAs/mycertificates.pem");
curl_easy_setopt(curl_handle, CURLOPT_CAINFO, path);
Deze code vertelt curl om alle CA's te vertrouwen die zijn gedefinieerd in het bestand mycertificates.pem, naast CA's die zijn gedefinieerd in de mapset in CURLOPT_CAPATH.
Wederzijdse verificatie
Wederzijdse verificatie controleert of zowel de server als het clientapparaat legitiem zijn. Het is een proces met meerdere stappen:
- De toepassing verifieert de server met behulp van een CA-certificaat, zoals beschreven in Serververificatie.
- De toepassing presenteert een x509-clientverificatiecertificaat aan de server, zodat de server het apparaat kan verifiëren.
- De server gebruikt de certificaatketen van de Azure Sphere-catalogus om te controleren of het apparaat tot de catalogus behoort.
Een toepassing kan de apparaatverificatiezijde van wederzijdse verificatie op twee manieren instellen:
- Configureer de functie Azure Sphere DeviceAuth_CurlSslFunc als de SSL-functie waarmee verificatie wordt uitgevoerd.
- Maak een aangepaste SSL-functie die de functie Azure Sphere DeviceAuth_SslCtxFunc aanroept voor verificatie.
Opmerking
Azure Sphere biedt geen ondersteuning voor opnieuw onderhandelen over SSL/TLS.
Voordat u een van beide functies gebruikt, moet u het CMakeLists.txt-bestand voor uw toepassing bijwerken om curl- en tlsutils toe te voegen aan TARGET_LINK_LIBRARIES:
TARGET_LINK_LIBRARIES(${PROJECT_NAME} applibs pthread gcc_s c curl tlsutils)
Gebruik DeviceAuth_CurlSslFunc
De eenvoudigste manier om apparaatverificatie uit te voeren, is door DeviceAuth_CurlSslFunc te configureren als de callback-functie voor curl SSL-verificatie:
// 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;
}
De functie DeviceAuth_CurlSslFunc haalt de certificaatketen op voor de huidige Azure Sphere-catalogus en stelt de curl-verbinding in om wederzijdse verificatie uit te voeren. Als verificatie mislukt, retourneert de functie CURLE_SSL_CERTPROBLEM.
Gebruik DeviceAuth_SslCtxFunc
Een toepassing kan ook een aangepaste SSL-callback-functie gebruiken die de functie Azure Sphere DeviceAuth_SslCtxFunc aanroept voor verificatie.
Uw aangepaste SSL-functie moet DeviceAuth_SslCtxFunc aanroepen om de verificatie uit te voeren, maar kan ook andere taken met betrekking tot verificatie uitvoeren.
DeviceAuth_SslCtxFunc retourneert een waarde van de DeviceAuthSslResult
opsomming, die gedetailleerde informatie over de fout bevat. Bijvoorbeeld:
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;
}
De cataloguscertificaatketen op uw server gebruiken
Als u wederzijdse verificatie wilt uitvoeren, moet de server kunnen controleren of het apparaat deel uitmaakt van uw Azure Sphere-catalogus en of de catalogus zelf legitiem is. Voor deze verificatie heeft de server de certificaatketen van de Azure Sphere-catalogus nodig, waarmee al uw Azure Sphere-apparaten worden ondertekend:
Als u de certificaatketen voor uw catalogus wilt ophalen, downloadt u deze naar een .p7b-bestand, zoals in het volgende voorbeeld:
az sphere ca-certificate download-chain --output-file CA-cert-chain.p7b
Vervolgens kunt u het .p7b-bestand op uw server gebruiken.
Aanvullende tips voor het gebruik van curl
Hier volgen enkele aanvullende tips voor het gebruik van curl in een Azure Sphere-toepassing.
Als u van plan bent om pagina-inhoud op te slaan in RAM of Flash, moet u er rekening mee houden dat de opslag op het Azure Sphere-apparaat beperkt is.
Om ervoor te zorgen dat curl omleidingen volgt, voegt u het volgende toe aan uw code:
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
Uitgebreide informatie toevoegen over curl-bewerkingen die nuttig kunnen zijn tijdens foutopsporing:
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
Sommige servers retourneren fouten als een aanvraag geen gebruikersagent bevat. Een gebruikersagent instellen:
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
Wanneer u curl_multi timer callbacks verwerkt, vermijdt u recursieve oproepen wanneer de gerapporteerde time-out 0 ms is, omdat dit kan leiden tot onvoorspelbaar gedrag. Behandel in plaats daarvan 0 ms als 1 ms door een EventLoopTimer te activeren (0 ms EventLoopTimers zijn ook recursief en moeten worden vermeden).
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; }