Udostępnij za pośrednictwem


Nawiązywanie połączenia z usługami sieci Web

Klawiatura SDK Azure Sphere zawiera bibliotekę libcurl, której aplikacje wysokiego poziomu mogą używać do łączenia się i uwierzytelniania za pomocą usług sieci Web HTTP i HTTPS. Zarówno uwierzytelnianie serwera, jak i klienta są obsługiwane, dzięki czemu aplikacje mogą sprawdzić, czy komunikują się z oczekiwanym serwerem i mogą udowodnić serwerowi, że ich urządzenie i wykaz usługi Azure Sphere są zgodne z prawem. Wzajemne uwierzytelnianie łączy te dwa elementy.

Próbki azure sphere repo w GitHub obejmuje następujące próbki curl:

  • HTTPS_Curl_Easy używa synchronicznego (blokowania) interfejsu API uwierzytelniania serwera.
  • HTTPS_Curl_Multi przykład korzysta z asynchronicznego (nieblokującego) interfejsu API uwierzytelniania serwera.

Mimo że synchroniczne podejście do uwierzytelniania serwera w HTTPS_Curl_Easy jest dość proste, aplikacje Azure Sphere powinny na ogół korzystać z bardziej złożonej techniki asynchronicznej pokazanej w próbce HTTPS_Curl_Multi wraz ze wzorcem opartym na zdarzeniach opartym na epoll.

Strona libcurl zawiera dokładną dokumentację libcurl C API i wiele przykładów. Różnice między biblioteką cURL a biblioteką środowiska wykonawczego SDK azure Sphere są następujące:

Nazwa stałej
(definicja)
Ograniczenia zakresu cURL Limity zakresu w usłudze Azure Sphere
CURLOPT_BUFFERSIZE
(rozmiar buforu)
Domyślne: 16 KB Domyślne: 1536 KB
CURLOPT_UPLOAD_BUFFERSIZE
(rozmiar buforu przekazywania)
Domyślne: 64 KB
Maksymalna liczba: 2 MB
Minimum: 16 KB
Domyślne: 1536 KB
Maksymalna: 64 KB
Minimum: 1536 KB
CURLOPT_HEADERFUNCTION
(pełny nagłówek HTTP przekazany do tej funkcji)
Maksymalna: 100 KB Maksymalna wartość: 16 KB
CURLOPT_DNS_CACHE_TIMEOUT Domyślne: wyniki w pamięci podręcznej przez 60 sekund
Maksimum: zawsze wyniki w pamięci podręcznej
Minimum: 0 (nie buforuj wyników)
Wszystkie wartości zostaną zastąpione wartością 0, a wyniki nie zostaną buforowane.

Wymagania dotyczące aplikacji, które używają funkcji zwijania

Aplikacje korzystające z biblioteki zwijania muszą zawierać odpowiednie pliki nagłówków i udostępniać w manifeście aplikacji identyfikator użytkownika dzierżawy Azure Sphere (Starsza wersja) i informacje o hostie internetowym.

Pliki nagłówków

Aby użyć funkcji zwijania, uwzględnij w aplikacji następujące pliki nagłówków:

#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

Plik nagłówka storage.h jest wymagany tylko w przypadku podania co najmniej jednego certyfikatu w pakiecie obrazów aplikacji. Nagłówek deviceauth_curl.h jest wymagany do wykonywania wzajemnego uwierzytelniania. Nagłówek networking_curl.h jest wymagany, jeśli aplikacja łączy się z Internetem za pomocą serwera proxy.

Manifest aplikacji

Pole AllowedConnections manifestu aplikacji musi określać hosty, z którymi łączy się aplikacja. Musi również zawierać nazwę każdej domeny, która może wystąpić w przypadku przekierowania połączenia. Na przykład oba microsoft.com te www.microsoft.com elementy są wymagane dla aplikacji, która łączy się ze stroną główną firmy Microsoft.

Jeśli aplikacja korzysta z wzajemnego uwierzytelniania, pole DeviceAuthentication manifestu musi zawierać identyfikator użytkownika dzierżawy Azure Sphere (Legacy). Certyfikaty uwierzytelniania urządzenia są wystawiane tylko wtedy, gdy katalog urządzenia jest połączony z interfejsem użytkownika dzierżawy usługi Azure Sphere (Starsza wersja) zgodnym z identyfikatorem użytkownika dzierżawy w manifeście aplikacji. To ograniczenie zapewnia dogłębną obronę: aplikacja działająca na urządzeniu w innym katalogu (na przykład inna firma lub nieuczciwa jednostka) nie może uwierzytelnić się na serwerze.

Podczas opracowywania możesz znaleźć starszy identyfikator użytkownika dzierżawy, używając polecenia pokaż wykaz az sphere i wyodrębniając MigratedCatalogId wartość z obiektu tags .

Jeśli aplikacja korzysta z serwera proxy, pole ReadNetworkProxyConfig wskazuje, czy aplikacja ma uprawnienia do pobierania konfiguracji serwera proxy.

W poniższym przykładzie pole AllowedConnections określa, że aplikacja łączy się tylko www.example.comz polem DeviceAuthentication określa identyfikator użytkownika dzierżawy Azure Sphere (Legacy), umożliwiając aplikacji używanie certyfikatu urządzenia do wzajemnego uwierzytelniania, a pole ReadNetworkProxyConfig określa, że aplikacja może ponownie przetwarzać informacje o konfiguracji serwera proxy.

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

Funkcja obsługiwana

Program Libcurl dla usługi Azure Sphere obsługuje tylko protokoły HTTP i HTTPS. Ponadto system operacyjny Azure Sphere nie obsługuje niektórych funkcji, takich jak pliki zapisywalne (pliki cookie) lub gniazda UNIX. Funkcje, które nie będą obsługiwane w przyszłych wersjach libcurl, takich jak rodzina mprintf(), są niedostępne.

Program Libcurl dla usługi Azure Sphere obsługuje usługi TLS 1.2 i TLS 1.3, a ponadto wycofał oprogramowanie TLS 1.0 i TLS 1.1 zgodnie z szerszą strategią zabezpieczeń protokołu Microsoft TLS.

Obsługiwane są następujące pakiety szyfrowania:

  • 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

Próby użycia nieobsługiowanej wersji protokołu TLS zwracają błąd CyaSSL does not support <version>.

Uwierzytelnianie serwera

Usługa Azure Sphere obsługuje uwierzytelnianie serwera poprzez libcurl. Certyfikat serwera musi być podpisany przez urząd certyfikacji, któremu ufa urządzenie. Aby libcurl uwierzytelnił serwer, aplikacja musi podać ścieżkę do pliku urzędu certyfikacji.

Dodawanie certyfikatów urzędu certyfikacji do pakietu obrazów

Aby użyć co najmniej jednego uwierzytelniania, musisz dodać certyfikaty do pakietu obrazów. Każdy certyfikat musi być zakodowany w podstawie 64. Najprostszym rozwiązaniem jest utworzenie jednego pliku zawierającego wszystkie dodatkowe certyfikaty. Plik musi mieć rozszerzenie pem nazwa_pliku. Aby dodać certyfikaty:

  1. Utwórz folder certyfikatów w folderze projektu dla aplikacji. Folder projektu zawiera plik CMakeLists aplikacji.
  2. W folderze certyfikatów utwórz plik tekstowy z rozszerzeniem pem, skopiuj do niego każdy certyfikat i zapisz plik.
  3. W pliku CMakeLists.txt dodaj plik certyfikatu do pakietu obrazów jako plik zasobu. Na przykład:
azsphere_target_add_image_package(${PROJECT_NAME} RESOURCE_FILES "certs/DigiCertGlobalRootCA.pem")

Plik certyfikatu powinien zostać wyświetlony w folderze certyfikatów w pakiecie obrazów.

Ustawianie lokalizacji certyfikatów

W aplikacji użyj opcji CURLOPT_CAPATH i CURLOPT_CAINFO , aby ustawić lokalizacje certyfikatów. Wywołaj Storage_GetAbsolutePathInImagePackage , aby pobrać ścieżkę bezwzględną do certyfikatów w pakiecie obrazów, a następnie wywołaj curl_easy_setopt.

CURLOPT_CAPATH ustawia folder domyślny certyfikatów. Na przykład następujący kod informuje curl szukać certyfikatów w folderze certyfikatów na obrazie:

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

CURLOPT_CAINFO ustawia ścieżkę do pliku zawierającego co najmniej jeden certyfikat. Oprócz domyślnego folderu ustawionego w CURLOPT_CAPATH wyszukuje ten plik. Na przykład:

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

Ten kod informuje curl zaufać wszystkie CAs, które są zdefiniowane w pliku mycertificates.pem, oprócz CAs, które są zdefiniowane w katalogu ustawionym w CURLOPT_CAPATH.

Wzajemne uwierzytelnianie

Wzajemne uwierzytelnianie weryfikuje, czy zarówno serwer, jak i urządzenie klienckie są zgodne z prawem. Jest to proces wieloetapowy:

  1. Aplikacja uwierzytelnia serwer przy użyciu certyfikatu urzędu certyfikacji zgodnie z opisem w temacie Uwierzytelnianie serwera.
  2. Aplikacja przedstawia serwerowi certyfikat uwierzytelniania klienta x509, dzięki czemu serwer może uwierzytelnić urządzenie.
  3. Serwer używa łańcucha certyfikatów wykazu usługi Azure Sphere w celu sprawdzenia, czy urządzenie należy do wykazu.

Aplikacja może skonfigurować stronę uwierzytelniania urządzenia wzajemnego uwierzytelniania na dwa sposoby:

  • Skonfiguruj funkcję Azure Sphere DeviceAuth_CurlSslFunc jako funkcję SSL wykonującą uwierzytelnianie.
  • Utwórz niestandardową funkcję SSL, która wywołuje funkcję Azure Sphere DeviceAuth_SslCtxFunc na potrzeby uwierzytelniania.

Uwaga

Azure Sphere nie obsługuje renegocjacji SSL/TLS.

Przed użyciem jednej z tych funkcji należy zaktualizować plik CMakeLists.txt dla aplikacji, aby dodać curl i tlsutils do TARGET_LINK_LIBRARIES:

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

Używanie DeviceAuth_CurlSslFunc

Najprostszym sposobem uwierzytelniania urządzenia jest skonfigurowanie DeviceAuth_CurlSslFunc jako funkcji wywołania zwrotnego do uwierzytelniania SSL:

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

Funkcja DeviceAuth_CurlSslFunc pobiera łańcuch certyfikatów dla bieżącego wykazu usługi Azure Sphere i konfiguruje połączenie zwijane w celu wykonywania wzajemnego uwierzytelniania. Jeśli uwierzytelnianie zakończy się niepowodzeniem, funkcja zwraca CURLE_SSL_CERTPROBLEM.

Korzystanie z DeviceAuth_SslCtxFunc

Aplikacja może również używać niestandardowej funkcji wywołania zwrotnego SSL, która wywołuje funkcję Azure Sphere DeviceAuth_SslCtxFunc na potrzeby uwierzytelniania.

Niestandardowa funkcja SSL musi wywoływać DeviceAuth_SslCtxFunc w celu przeprowadzenia uwierzytelniania, ale może również wykonywać inne zadania związane z uwierzytelnianiem. DeviceAuth_SslCtxFunc zwraca wartość wyliczenia DeviceAuthSslResult , która zawiera szczegółowe informacje o niepowodzeniu. Na przykład:

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

Używanie łańcucha certyfikatów wykazu na serwerze

Aby można było przeprowadzić wzajemne uwierzytelnianie, serwer musi mieć możliwość sprawdzenia, czy urządzenie należy do katalogu usługi Azure Sphere i czy sam katalog jest wiarygodny. Aby można było wykonać to uwierzytelnianie, serwer wymaga łańcucha certyfikatów wykazu usługi Azure Sphere, który podpisuje wszystkie urządzenia usługi Azure Sphere:

Aby pobrać łańcuch certyfikatów dla wykazu, pobierz go do pliku p7b, tak jak w poniższym przykładzie:

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

Następnie możesz użyć pliku p7b na serwerze.

Dodatkowe porady dotyczące korzystania z zawijasów

Oto kilka dodatkowych porad dotyczących używania funkcji zwijania w aplikacji Azure Sphere.

  • Jeśli zamierzasz przechowywać zawartość strony w pamięci RAM lub pamięci flash, pamiętaj, że ilość miejsca do magazynowania na urządzeniu Azure Sphere jest ograniczona.

  • Aby upewnić się, że zawijanie następuje przekierowania, dodaj do kodu następujące elementy:

    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
    
  • Aby dodać szczegółowe informacje na temat operacji zwijania, które mogą być pomocne podczas debugowania:

    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
    
  • Niektóre serwery zwracają błędy, jeśli żądanie nie zawiera agenta użytkownika. Aby ustawić agenta użytkownika:

    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
    
  • Podczas obsługi curl_multi wywołań czasomierza unikaj połączeń rekurencyjnych, gdy zgłoszony limit czasu wynosi 0 ms, ponieważ może to prowadzić do nieprzewidywalnego zachowania. Zamiast tego potraktuj 0 ms jako 1 ms, wyzwalając EventLoopTimer (0ms EventLoopTimers są również rekurencyjne i należy ich unikać).

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