Поделиться через


Подключение к веб-службам

Внимание

Это документация по Azure Sphere (устаревшая версия). Служба Azure Sphere (устаревшая версия) выходит на пенсию 27 сентября 2027 г., и к этому времени пользователи должны перейти в Azure Sphere (интегрированная). Используйте селектор версий, расположенный над toC, чтобы просмотреть документацию по Azure Sphere (интегрированная).

Пакет SDK для Azure Sphere включает библиотеку libcurl, которую высокоуровневые приложения могут использовать для подключения и проверки подлинности с помощью веб-служб HTTP и HTTPS. Проверка подлинности сервера и клиента поддерживается, поэтому приложения могут проверить, что они взаимодействуют с ожидаемым сервером и могут доказать серверу, что их устройство и клиент Azure Sphere являются полноправными. Взаимная проверка подлинности объединяет эти два типа.

Репозиторий примеров Azure Sphere на сайте GitHub содержит следующие примеры curl:

  • HTTPS_Curl_Easy использует синхронный (блокирующий) API для проверки подлинности сервера.
  • Пример HTTPS_Curl_Multi использует асинхронный (не блокирующий) API для проверки подлинности сервера.

Хотя синхронный подход к проверке подлинности сервера в HTTPS_Curl_Easy довольно прост, приложения Azure Sphere обычно используют более сложные асинхронные методы, показанные в примере HTTPS_Curl_Multi, наряду с основанным на epoll однопоточным шаблоном, управляемым событиями.

Веб-сайт libcurl содержит подробную документацию по API C для libcurl и множество примеров. Различия между библиотекой cURL и библиотекой среды выполнения пакета SDK Для Azure Sphere приведены ниже.

Имя константы
(определение)
Ограничения диапазона cURL Ограничения диапазона Azure Sphere
CURLOPT_BUFFERSIZE
(размер буфера)
По умолчанию: 16 КБ По умолчанию: 1536 КБ
CURLOPT_UPLOAD_BUFFERSIZE
(размер буфера отправки)
Значение по умолчанию: 64 КБ
Максимум: 2 МБ
Минимум: 16 КБ
По умолчанию: 1536 КБ
Максимальное значение: 64 КБ
Минимум: 1536 КБ
CURLOPT_HEADERFUNCTION
(полный заголовок HTTP, переданный этой функции)
Максимальное: 100 КБ Максимум: 16 КБ
CURLOPT_DNS_CACHE_TIMEOUT По умолчанию: результаты кэширования в течение 60 секунд
Максимальное значение: результаты кэша навсегда
Минимум: 0 (не кэшировать результаты)
Все значения переопределяются на 0, а результаты не кэшируются.

Требования к приложениям, использующим curl

Приложения, использующие библиотеку curl, должны содержать соответствующие файлы заголовков и предоставлять сведения о клиенте и интернет-узле в манифесте приложения.

Файлы заголовков

Чтобы использовать curl, включите в приложение следующие файлы заголовка.

#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 является обязательным только в том случае, если вы добавляете в пакет образа приложения один или несколько сертификатов. Заголовок deviceauth_curl.h необходим для выполнения взаимной проверки подлинности. Заголовок networking_curl.h необходим, если приложение использует прокси-сервер для подключения к Интернету.

Манифест приложения

В поле AllowedConnections манифеста приложения должны быть указаны узлы, к которым подключается приложение. Оно также должно содержать имя каждого домена, подключение к которому может возникнуть в случае перенаправления. Например, microsoft.com и www.microsoft.com требуются для работы приложения, которое подключается к домашней странице Майкрософт.

Если приложение использует взаимную проверку подлинности, в поле DeviceAuthentication манифеста должен быть указан идентификатор клиента Azure Sphere. Сертификаты проверки подлинности устройства выдаются только в том случае, если идентификатор клиента устройства совпадает с идентификатором клиента в манифесте приложения. Это ограничение обеспечивает глубокую защиту: приложение, работающее на устройстве в другом клиенте (скажем, у другого клиента или фальшивой сущности), не может пройти проверку подлинности на сервере.

Если приложение использует прокси-сервер, поле ReadNetworkProxyConfig указывает, имеет ли приложение разрешение на получение конфигурации прокси-сервера.

Во время разработки можно найти идентификатор текущего клиента Azure Sphere с помощью команды azsphere tenant show-selected.

В следующем примере поле AllowedConnections указывает, что приложение подключается только к www.example.com, поле DeviceAuthentication указывает идентификатор клиента Azure Sphere, позволяющий приложению использовать сертификат устройства для взаимной проверки подлинности, а поле ReadNetworkProxyConfig указывает, что приложение может повторно получить сведения о конфигурации прокси-сервера.

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

Поддерживаемые функции

Библиотека Libcurl для Azure Sphere поддерживает только протоколы HTTP и HTTPS. Кроме того, ОС Azure Sphere не поддерживает некоторые функции, такие как записываемые файлы (файлы cookie) или сокеты UNIX. Функции, которые не будут поддерживаться в будущих выпусках libcurl, например семейство mprintf(), недоступны.

Libcurl для Azure Sphere поддерживает TLS 1.2 и TLS 1.3 и отставил TLS 1.0 и TLS 1.1 в соответствии с более широкой стратегией безопасности Microsoft TLS.

Поддерживаются следующие комплекты шифров:

  • 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

Попытки использовать неподдерживаемую версию TLS возвращают ошибку CyaSSL does not support <version>.

Аутентификация сервера

Azure Sphere поддерживает проверку подлинности сервера через libcurl. Сертификат сервера должен быть подписан центром сертификации (ЦС), которому устройство доверяет. Для аутентификации сервера с помощью libcurl приложению необходимо указать путь к файлу ЦС.

Добавление сертификатов ЦС в пакету образа

Чтобы использовать один или несколько центров сертификации, необходимо добавить сертификаты в пакет образа. Каждый сертификат должен быть в кодировке base-64. Самый простой подход — создать один файл, содержащий все дополнительные сертификаты. Этот файл должен иметь расширение PEM. Добавление сертификатов

  1. Создайте папку certs в папке проекта для приложения. Папка проекта содержит файл CMakeLists для приложения.
  2. В папке certs создайте текстовый файл с расширением PEM, скопируйте в него каждый сертификат и сохраните этот файл.
  3. В файле CMakeLists.txt добавьте файл сертификата в пакет образа в качестве файла ресурса. Например:
azsphere_target_add_image_package(${PROJECT_NAME} RESOURCE_FILES "certs/DigiCertGlobalRootCA.pem")

Теперь файл сертификата должен появиться в папке certs в пакете образа.

Настройка расположений сертификата

Используйте параметры CURLOPT_CAPATH и CURLOPT_CAINFO в приложении, чтобы задать расположение сертификатов. Вызовите Storage_GetAbsolutePathInImagePackage, чтобы получить абсолютный путь к сертификатам в пакете образа, а затем вызовите curl_easy_setopt.

CURLOPT_CAPATH задает папку по умолчанию для сертификатов. Например, следующий код указывает, что библиотека curl должна искать сертификаты только в папке образа certs.

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

CURLOPT_CAINFO задает путь к файлу, который содержит один или несколько сертификатов. Curl проверяет этот файл в дополнение к папке по умолчанию, заданной параметром CURLOPT_CAPATH. Рассмотрим такой пример:

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

Этот код указывает библиотеке curl доверять центрам сертификации, определенным в файле mycertificates.pem, помимо центров сертификации, которые определены в каталоге, заданном в CURLOPT_CAPATH.

Взаимная проверка подлинности

Взаимная проверка подлинности проверяет сервер и клиентское устройство на законность. Этот процесс состоит из нескольких этапов:

  1. Приложение проверяет подлинность сервера с помощью сертификата ЦС, как описано в разделе Проверка подлинности сервера.
  2. Приложение представляет сертификат проверки подлинности клиента x509 для сервера, чтобы сервер мог проверить подлинность устройства.
  3. Сервер использует цепочку сертификатов клиента Azure Sphere, чтобы проверить, что устройство относится к клиенту.

Чтобы настроить для приложения аутентификацию устройства как часть взаимной проверки подлинности, воспользуйтесь одним из двух способов:

  • Настройте функцию Azure Sphere DeviceAuth_CurlSslFunc в качестве функции SSL, которая выполняет проверку подлинности.
  • Создайте пользовательскую функцию SSL, которая вызывает функцию Azure Sphere DeviceAuth_SslCtxFunc для проверки подлинности.

Примечание.

Azure Sphere не поддерживает повторное согласование SSL и TLS.

Перед использованием любой из функций необходимо обновить файл CMakeLists.txt для приложения, чтобы добавить curl и tlsutils в список целевых библиотек TARGET_LINK_LIBRARIES:

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

Использование DeviceAuth_CurlSslFunc

Самый простой способ выполнить проверку подлинности устройства — настроить DeviceAuth_CurlSslFunc в качестве функции обратного вызова для проверки подлинности curl 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;
}

Функция DeviceAuth_CurlSslFunc извлекает цепочку сертификатов для текущего клиента Azure Sphere и устанавливает curl-соединение для взаимной проверки подлинности. Если проверка подлинности завершается неудачно, функция возвращает CURLE_SSL_CERTPROBLEM.

Использование DeviceAuth_SslCtxFunc

В приложении можно применять пользовательскую функцию обратного вызова SSL, которая обращается к функции Azure Sphere DeviceAuth_SslCtxFunc для проверки подлинности.

Пользовательская функция SSL должна вызывать DeviceAuth_SslCtxFunc для выполнения проверки подлинности, но также может выполнять другие задачи, связанные с проверкой подлинности. DeviceAuth_SslCtxFunc возвращает значение перечисления DeviceAuthSslResult, которое предоставляет подробные сведения о сбое. Например:

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

Использование цепочки сертификатов клиента на сервере

Чтобы выполнить взаимную проверку подлинности, сервер должен иметь возможность убедиться, что устройство относится к вашему клиенту Azure Sphere и что клиент является допустимым. Для выполнения этой проверки подлинности серверу требуется цепочка сертификатов клиента Azure Sphere, которая подписывает все устройства Azure Sphere.

Чтобы получить цепочку сертификатов клиента, скачайте ее в P7B-файл, как показано в следующем примере:

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

Затем этот P7B-файл можно использовать на сервере.

Дополнительные советы по использованию curl

Ниже приведено несколько дополнительных советов по использованию curl в приложении Azure Sphere.

  • Если вы планируете хранить содержимое страниц в ОЗУ или флэш-памяти, имейте в виду, что емкость устройства Azure Sphere ограничена.

  • Чтобы убедиться, что curl выполняет перенаправление, добавьте в код следующую строку:

    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
    
  • Чтобы добавить детальные сведения об операциях curl, которые могут оказаться полезными во время отладки, добавьте следующую строку.

    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
    
  • Некоторые серверы возвращают ошибки, если запрос не содержит агент пользователя. Чтобы настроить агент пользователя, добавьте в код следующую строку.

    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
    
  • При обработке обратных вызовов таймера curl_multi избежать рекурсивных вызовов, когда сообщаемое время ожидания равно 0 мс, так как это может привести к непредсказуемому поведению. Вместо этого следует обрабатывать 0 мс как 1 мс путем активации EventLoopTimer (0ms EventLoopTimers также рекурсивно и следует избегать).

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