Dela via


Ansluta till webbtjänster

Azure Sphere SDK innehåller libcurl-biblioteket, som program på hög nivå kan använda för att ansluta och autentisera med HTTP- och HTTPS-webbtjänster. Både server- och klientautentisering stöds, så att program kan verifiera att de kommunicerar med den förväntade servern och kan bevisa för servern att deras enhet och Azure Sphere-katalogen är legitima. Ömsesidig autentisering kombinerar de två.

Azure Sphere-exempelrepoilen på GitHub innehåller följande curl-exempel:

Även om den synkrona metoden för serverautentisering i HTTPS_Curl_Easy är ganska enkel, bör Azure Sphere-program i allmänhet använda den mer komplexa asynkrona tekniken som visas i HTTPS_Curl_Multi-exemplet, tillsammans med ett epollbaserat, enkeltrådat händelsedrivet mönster.

Libcurl-webbplatsen ger grundlig dokumentation om libcurl C API och många exempel. Skillnaderna mellan cURL-biblioteket och Azure Sphere SDK runtime-biblioteket är följande:

Konstantnamn
(definition)
cURL-intervallgränser Azure Sphere-intervallgränser
CURLOPT_BUFFERSIZE
(buffertstorlek)
Standard: 16 kB Standard: 1 536 kB
CURLOPT_UPLOAD_BUFFERSIZE
(uppladdningsbuffertstorlek)
Standard: 64 kB
Maximalt: 2 MB
Minimum: 16 KB
Standard: 1 536 kB
Maximalt: 64 kB
Minimum: 1536 KB
CURLOPT_HEADERFUNCTION
(fullständigt HTTP-sidhuvud skickas till den här funktionen)
Max: 100 kB Maximalt: 16 kB
CURLOPT_DNS_CACHE_TIMEOUT Standard: cacheresultat i 60 sekunder
Maximum: cacheresultat för alltid
Minimum: 0 (cachelagrade inte resultat)
Alla värden åsidosättas till 0 och resultaten cachelagrades inte.

Krav för program som använder curl

Program som använder curlbiblioteket måste innehålla lämpliga huvudfiler och tillhandahålla UUID-klientorganisation för Azure Sphere (äldre) och värdinformation för Internet i programmanifestet.

Sidhuvudfiler

Om du vill använda curl tar du med dessa rubrikfiler i programmet:

#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

Storage.h-huvudfilen krävs bara om du anger ett eller flera certifikat i programbildpaketet. Sidhuvudet deviceauth_curl.h krävs för att utföra ömsesidig autentisering. Sidhuvudet networking_curl.h krävs om programmet använder en proxy för att ansluta till Internet.

Programmanifest

Fältet AllowedConnections i programmanifestet måste ange de värdar som programmet ansluter till. Den måste också innehålla namnet på varje domän som anslutningen kan stöta på om omdirigeras till. Till exempel både microsoft.com och www.microsoft.com krävs för ett program som ansluter till Microsofts startsida.

Om programmet använder ömsesidig autentisering måste fältet DeviceAuthentication i manifestet innehålla Azure Sphere -klientorganisationenS UUID. Enhetsautentiseringscertifikat utfärdas endast om enhetens katalog är länkad till en Azure Sphere-klientorganisations-UUID som matchar klientorganisationens UUID i programmanifestet. Den här begränsningen ger djup skydd: ett program som körs på en enhet i en annan katalog (t.ex. en annan kund eller en falsk enhet) kan inte autentiseras för servern.

Under utvecklingen kan du hitta den äldre klientorganisationens UUID genom att använda kommandot az sphere catalog show och extrahera MigratedCatalogId värdet från tags objektet.

Om programmet använder en proxy anger fältet ReadNetworkProxyConfig om programmet har behörighet att hämta proxykonfigurationen.

I följande exempel anger fältet AllowedConnections att programmet endast ansluter till www.example.com, fältet DeviceAuthentication anger Azure Sphere (äldre) klientorganisations-UUID, vilket gör att programmet kan använda enhetscertifikatet för ömsesidig autentisering, och fältet ReadNetworkProxyConfig anger att programmet kan ändra proxykonfigurationsinformationen.

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

Funktioner som stöds

Libcurl för Azure Sphere har endast stöd för HTTP- och HTTPS-protokollen. Dessutom har Azure Sphere-operativsystemet inte stöd för vissa funktioner, till exempel skrivbara filer (cookies) eller UNIX-uttag. Funktioner som inte stöds i framtida libcurl-versioner, till exempel mprintf() -familjen, är inte tillgängliga.

Libcurl för Azure Sphere har stöd för TLS 1.2 och TLS 1.3 och har dragit tillbaka TLS 1.0 och TLS 1.1 i linje med den bredare Microsoft TLS-säkerhetsstrategin.

Följande är de chiffersviter som stöds:

  • 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

Försök att använda en version av TLS som inte stöds returnerar felet CyaSSL does not support <version>.

Serverautentisering

Azure Sphere stöder serverautentisering via libcurl. Serverns certifikat måste signeras av en certifikatutfärdare (CA) som enheten litar på. För att libcurl ska autentisera en server måste programmet ange sökvägen till CA-filen.

Lägga till certifikatutfärdarcertifikat i avbildningspaketet

Om du vill använda en eller flera certifikatutfärdare måste du lägga till certifikaten i avbildningspaketet. Varje certifikat måste vara bas-64-kodat. Det enklaste sättet är att skapa en enda fil som innehåller alla ytterligare certifikat. Filen måste ha filnamnstillägget .pem. Så här lägger du till certifikat:

  1. Skapa en certifikatmapp i projektmappen för programmet. Projektmappen innehåller filen CMakeLists för programmet.
  2. Skapa en textfil med filnamnstillägget .pem i mappen certifikat, kopiera varje certifikat till den och spara filen.
  3. I den CMakeLists.txt filen lägger du till certifikatfilen i avbildningspaketet som en resursfil. Till exempel:
azsphere_target_add_image_package(${PROJECT_NAME} RESOURCE_FILES "certs/DigiCertGlobalRootCA.pem")

Certifikatfilen ska nu visas i certifikatmappen i avbildningspaketet.

Ange certifikatplatser

Använd alternativen CURLOPT_CAPATH och CURLOPT_CAINFO i programmet för att ange certifikatens platser. Ring Storage_GetAbsolutePathInImagePackage för att hämta den absoluta sökvägen till certifikaten i avbildningspaketet och ring sedan curl_easy_setopt.

CURLOPT_CAPATH anger en standardmapp för certifikaten. Följande kod anger till exempel att curl ska söka efter certifikat i mappen certifikat i avbildningen:

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

CURLOPT_CAINFO anger en sökväg till en fil som innehåller ett eller flera certifikat. Curl söker i den här filen utöver standardmappen som anges i CURLOPT_CAPATH. Till exempel:

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

Den här koden anger att curl ska lita på eventuella certifikatutfärdare som definierats i filen mycertificates.pem, utöver de certifikatutfärdare som definierats i kataloguppsättningen i CURLOPT_CAPATH.

Ömsesidig autentisering

Ömsesidig autentisering verifierar att både servern och klientenheten är legitima. Det är en process i flera steg:

  1. Programmet autentiserar servern med hjälp av ett certifikatutfärdarcertifikat enligt beskrivningen i Serverautentisering.
  2. Programmet presenterar ett x509-klientautentiseringscertifikat för servern så att servern kan autentisera enheten.
  3. Servern använder Azure Sphere-katalogens certifikatkedja för att verifiera att enheten tillhör katalogen.

Ett program kan konfigurera enhetsautentiseringssidan för ömsesidig autentisering på något av två sätt:

  • Konfigurera Azure Sphere-DeviceAuth_CurlSslFunc som den SSL-funktion som utför autentisering.
  • Skapa en anpassad SSL-funktion som anropar funktionen Azure Sphere DeviceAuth_SslCtxFunc för autentisering.

Observera

Azure Sphere stöder inte SSL/TLS-omförhandling.

Innan du använder någon av funktionerna måste du uppdatera CMakeLists.txt-filen för programmet för att lägga till curl och tlsutils i TARGET_LINK_LIBRARIES:

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

Använda DeviceAuth_CurlSslFunc

Det enklaste sättet att utföra enhetsautentisering är att konfigurera DeviceAuth_CurlSslFunc som återanropsfunktion för curl SSL-autentisering:

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

Funktionen DeviceAuth_CurlSslFunc hämtar certifikatkedjan för den aktuella Azure Sphere-katalogen och konfigurerar curl-anslutningen för att utföra ömsesidig autentisering. Om autentiseringen misslyckas returnerar funktionen CURLE_SSL_CERTPROBLEM.

Använda DeviceAuth_SslCtxFunc

Ett program kan också använda en anpassad SSL-återuppringningsfunktion som anropar azure sphere-DeviceAuth_SslCtxFunc-funktionen för autentisering.

Din anpassade SSL-funktion måste anropa DeviceAuth_SslCtxFunc för att utföra autentiseringen, men kan också utföra andra uppgifter som rör autentisering. DeviceAuth_SslCtxFunc returnerar ett värde för DeviceAuthSslResult uppräkningen, som innehåller detaljerad information om felet. Till exempel:

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

Använda katalogcertifikatkedjan på servern

För att kunna utföra ömsesidig autentisering måste servern kunna verifiera att enheten tillhör azure sphere-katalogen och att själva katalogen är legitim. För att utföra den här autentiseringen kräver servern certifikatkedjan för Azure Sphere-katalogen, som signerar alla dina Azure Sphere-enheter:

Hämta certifikatkedjan för katalogen genom att ladda ned den till en P7B-fil, som i följande exempel:

az sphere ca-certificate download-chain --destination CA-cert-chain.p7b

Du kan sedan använda P7B-filen på servern.

Ytterligare tips för att använda curl

Här är några ytterligare tips för att använda curl i ett Azure Sphere-program.

  • Om du planerar att lagra sidinnehåll i RAM-minne eller flashminne bör du tänka på att lagringen på Azure Sphere-enheten är begränsad.

  • För att säkerställa att curl följer omdirigeringar lägger du till följande i koden:

    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
    
  • Så här lägger du till utförlig information om curl-åtgärder som kan vara användbara vid felsökning:

    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
    
  • Vissa servrar returnerar fel om en begäran inte innehåller en användaragent. Så här anger du en användaragent:

    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
    
  • Vid hantering av curl_multi timeråterringning ska du undvika rekursiva samtal när den rapporterade timeouten är 0 ms, eftersom det kan leda till oförutsägbart beteende. Behandla i stället 0 ms som 1 ms genom att utlösa en EventLoopTimer (0ms EventLoopTimers är också rekursiva och bör undvikas).

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