Podpora klientské sady SDK Azure IoT pro servery tokenů třetích stran

Azure IoT
Azure IoT Hub

Článek Řízení přístupu ke službě IoT Hub znázorňuje, jak je možné integrovat službu tokenů třetích stran se službou IoT Hub. Tento článek popisuje podporu ověřování tokenu sdíleného přístupového podpisu (SAS) v každé z klientských sad SDK Azure IoT. Také popisuje, co je potřeba implementovat v aplikaci zařízení pomocí odpovídající sady SDK pro každý jazyk, a jak používat tokeny vymezené zařízením nebo moduly pro zásady sdíleného přístupu zařízení Připojení nebo modulu Připojení.

Kontext a problém

Aktuální dokumentace zabezpečení služby Azure IoT Hub popisuje model token-server třetích stran pro ověřování SAS se službou IoT Hub zařízeními IoT pomocí klientských sad SDK Azure IoT. Nesprávné předpoklady provedené zákazníkem během nedávného zapojení podniku však naznačují, že bez dalšího objasnění můžete vytvořit zavádějící dojem na úroveň podpory implementované ve výchozím nastavení v klientských sadách SDK azure IoT.

Tento článek popisuje poznatky z této rezervace a vysvětluje, co je potřeba udělat v každé sadě SDK, aby zařízení dosáhla ověřování token-server třetích stran. Tento článek by také měl zabránit tomu, abyste v klientské sadě SDK Azure IoT udělali podobné nesprávné předpoklady o podpoře vzoru token-serveru třetích stran.

Řešení

Klientské sady SDK Azure IoT poskytují různé úrovně podpory ověřování tokenů SAS, přičemž každý vyžaduje vlastní kód k dokončení funkce ověřování a správy tokenů.

Frekvence vyhodnocení tokenu závisí na zvoleném přenosovém protokolu – MQTT, AMQP nebo HTTPS. Varianta závisí na schopnosti protokolu, která podporuje proaktivní prodlužování platnosti tokenů a časových limitů relací. Pouze AMQP implementuje proaktivní podporu prodlužování platnosti. To znamená, že ostatní přenosy připojení zavřou při selhání ověřování tokenu SAS a pak musí provést novou operaci připojení. Jedná se o potenciálně nákladnou operaci připojení pro klienta.

Pokud ověřování SAS selže, vyvolá se chyba implementací přenosu, kterou je možné zpracovat v rámci aplikace zařízení obslužnou rutinou události "Připojení ion Status Changed". Při implementaci takové obslužné rutiny se obvykle zastaví aplikace zařízení kvůli chybě. Se správnou implementací obslužné rutiny události a funkce obnovení tokenů se přenosy můžou znovu pokusit o připojení.

Následující obrázek znázorňuje model token-server třetích stran:

Obrázek vzoru token-server třetích stran

Následující obrázek znázorňuje podporu implementace v klientské sadě SDK Azure IoT s integrací mobile Net Operator:

Vývojový diagram podpory implementace v klientské sadě SDK Azure IoT s integrací mobile Net Operator

Ukázkové implementace jsou součástí úložiště Azure Samples na GitHubu.

Problémy a důležité informace

Při rozhodování o implementaci tohoto modelu zvažte následující body:

  • Klientské sady SDK služby Azure IoT Hub Device Provisioning (Azure DPS) nepodporují ověřování tokenů SAS. Rozhraní REST API služby Azure DPS podporuje ověřování tokenu SAS. Aby bylo možné použít Azure DPS se službou tokenů třetích stran pro ověřování SAS, musí aplikace zařízení implementovat proces DPS zařízení pomocí rozhraní REST API služby Azure DPS.

  • Skládá se z provedení operace počáteční žádosti o registraci a následného dotazování rozhraní API provozního stavu, dokud proces DPS nebude úspěšný nebo selže. V případě úspěchu je možné získat podrobnosti o zřizování zařízení tím, že je požádáte o registraci modulu runtime rozhraní REST API služby Azure DPS.

Kdy se má tento model použít

Tento vzor byste měli používat vždy, když se chcete ověřit ve službě Azure IoT Hub ze zařízení IoT pomocí různých sad SDK klienta Azure IoT. Místo použití klientských sad SDK pro ověřování tokenů SAS použijte rozhraní REST API služby Azure DPS, abyste zajistili implementaci proaktivní podpory obnovení pro všechny mechanismy přenosu.

Příklady

Následující části obsahují příklady, které můžete použít pro různé programovací jazyky, jako jsou Embedded C, .NET, Java a Python.

Sada SDK pro zařízení služby Azure IoT Hub pro C a sadu SDK pro zařízení Azure IoT Hub pro vložený jazyk C

Následující přístup je možné využít v aplikacích zařízení vytvořených pomocí sady Azure IoT C SDK nebo sady Azure IoT Embedded C SDK. Žádná sada SDK neposkytuje správu životnosti tokenů SAS, proto budete muset implementovat funkci správce životnosti tokenu SAS.

Tokeny SAS lze použít prostřednictvím struktury IOTHUB_CLIENT_CONFIG nastavením členu deviceSasToken na token a nastavením hodnoty deviceKey null. Další nepoužívané hodnoty, například protocolGatewayHostName, musí být také nastaveny na hodnotu null.

IOTHUB_CLIENT_CONFIG* CONFIG = (IOTHUB_CLIENT_CONFIG*)malloc(sizeof(IOTHUB_CLIENT_CONFIG));

CONFIG->PROTOCOL = PROTOCOL;
CONFIG->DEVICEID = DEVICEID;
CONFIG->IOTHUBNAME = IOTHUBNAME;
CONFIG->IOTHUBSUFFIX = IOTHUBSUFFIX;
CONFIG->DEVICEKEY = 0;
CONFIG->DEVICESASTOKEN = TOKEN;
CONFIG->PROTOCOLGATEWAYHOSTNAME = 0;

// The created IOTHUB_CLIENT_CONFIG can then be provided to the IoTHubDeviceClient_Create function to establish a DeviceClient instance.
if ((IOTHUBCLIENTHANDLE = IoTHubDeviceClient_Create(CONFIG)) == NULL) {
    (void)printf("ERROR: IOTHUBCLIENTHANDLE IS NULL!\r\n");
}

// To capture SAS token authentication failures, a handler needs to be implemented for the IoTHubDeviceClient_SetConnectionStatusCallback.
(void)IoTHubDeviceClient_SetConnectionStatusCallback(IOTHUBCLIENTHANDLE, CONNECTION_STATUS_CALLBACK, NULL);

Connection_status_callback může zachytit IOTHUB_CLIENT_CONNECTION_STATUS_REASON IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN a aktivovat obnovení tokenu SAS prostřednictvím služby tokenů třetích stran. To je vyžadováno pro všechny přenosy, aby zachytily problémy s připojením, ale přenosy, které nepodporují proaktivní prodlužování platnosti tokenů SAS. Proaktivní správu životnosti tokenů SAS je možné implementovat jako funkci, která se opakovaně spouští během "provozní" smyčky aplikací zařízení. Zajištění doby života tokenu se často vyhodnocuje a v případě potřeby je možné proaktivně provést obnovení tokenu.

Souhrn implementace ověřování tokenu SAS pro sady SDK C:

  1. Implementujte obslužnou rutinu Připojení ionStatusCallback pro zaznamenání IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN události a aktivaci obnovení tokenu.

  2. Pomocí IOTHUB_CLIENT_CONFIG zadejte token SAS zařízení pro IoTHubDeviceClient_Create.

  3. Implementujte proaktivní správu životnosti tokenů SAS jako součást provozní smyčky aplikace zařízení.

Sada SDK pro zařízení služby Azure IoT Hub pro .NET

Klientská sada SDK Azure IoT pro .NET implementuje podporu správy životnosti tokenů SAS prostřednictvím abstraktní třídy DeviceAuthenticationWithTokenRefresh. Jako metodu ověřování do metody DeviceClient.Create lze poskytnout konkrétní implementaci této třídy, která přidává funkce obnovení tokenu. Implementace přenosu token automaticky obnoví metodou ověřování podle potřeby. Připojení ionStatusChangesHandler se vyžaduje k zaznamenání změn připojení a zabránění vyvolání výjimek přenosy.

Příklad implementace na základě DeviceAuthenticationWithTokenRefreash třídy:

internal class StsDeviceAuthenticationWithTokenRefresh : DeviceAuthenticationWithTokenRefresh
{

    private readonly string _stsConnectUrl = "http://localhost:8080/sts/azure/token/operations?sr={0}/devices/{1}";

    private const int DEFAULTTIMETOLIVESECONDS = 1 * 60 * 60;

    private const int DEFAULTBUFFERPERCENTAGE = 15;

    public StsDeviceAuthenticationWithTokenRefresh(string deviceId, int suggestedTimeToLiveSeconds, int timeBufferPercentage) : BASE(deviceId, suggestedTimeToLiveSeconds, timeBufferPercentage)
    {
        If(String.IsNullOrWhitespace(deviceId)){
            throw new ArgumentNullException(nameof(deviceId));
        }
    }

    protected override async Task<string> SafeCreateNewToken(string iotHub, int suggestedTimeToLive)
    {
        string result;
        string url = string.Format(_stsConnectUrl, iotHub, deviceId);

        using (HttpClientHandler handler = new HttpClientHandler())
        using (HttpClient client = new HttpClient(handler))
        {
            try
            {
                HttpResponseMessage response = await client.GetAsync(url);
                if (response.IsSuccessStatusCode)
                {
                    result = await response.Content.ReadAsStringAsync();
                }
                else
                {
                    throw new HttpRequestException($"Request failed with status code {response.StatusCode}.");
                }
            }
            catch (HttpRequestException)
            {
                result = null;
            }
        }

        return result;
    }
}

Souhrn implementace ověřování tokenu SAS pro sadu SDK pro zařízení služby Azure IoT Hub pro .NET:

  1. Implementujte konkrétní třídu založenou na abstraktní třídě DeviceAuthenticationWithTokenRefresh, která implementuje funkci obnovení tokenu.

  2. Implementujte Připojení ionStatusChangesHandler pro zachycení stavu připojení přenosu a zabránění výjimkám vyvolaným implementací přenosu.

Referenční informace:

Sada SDK pro zařízení služby Azure IoT Hub pro Javu

Klientská sada SDK Azure IoT pro Javu implementuje podporu správy životnosti tokenů SAS prostřednictvím rozhraní SasTokenProvider. Třída, která implementuje toto rozhraní s funkcí obnovení tokenu SAS lze použít jako SecurityProvider v konstruktoru DeviceClient. Implementace přenosu token automaticky obnoví prostřednictvím zprostředkovatele zabezpečení podle potřeby. Připojení ionStatusChangeCallback je potřeba zaregistrovat, aby bylo možné zaznamenat změny připojení a zabránit vyvolání výjimek přenosy.

Příklad implementace zprostředkovatele zabezpečení implementovaného rozhraní SasTokenProvider:

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class StsSecurityProvider implements SasTokenProvider {
    private final String hostname;
    private final String deviceId;
    private int renewalBufferSeconds;
    private long expiryTimeSeconds;
    private char[] sasToken;

    public StsSecurityProvider(String hostname, String deviceId) {
        this.hostname = hostname;
        this.deviceId = deviceId;
        this.renewalBufferSeconds = 120;
        this.expiryTimeSeconds = (System.currentTimeMillis() / 1000);
    }

    @Override
    public char[] getSasToken() {
        long currentTimeSeconds = (System.currentTimeMillis() / 1000);
        try {
            if (this.sasToken == null || this.expiryTimeSeconds + this.renewalBufferSeconds >= currentTimeSeconds) {
                this.sasToken = stsGetToken();
                assert this.sasToken != null;
                String t = String.copyValueOf(this.sasToken);
                String[] bits = t.split("SE=");
                long l = Long.parseLong(bits[1]);
                this.expiryTimeSeconds = l; // the SE= number
                this.renewalBufferSeconds = (int)(l * 0.15); // renew within 15% of expiry
            }
        } catch (InterruptedException | IOException e) {
            e.printStackTrace();
        }
        return this.sasToken;
    }

    private char[] stsGetToken() throws IOException, InterruptedException {
        String stsUrl = String.format("http://localhost:8080/sts/azure/token/operations?sr=%s/devices/%s", this.hostname, this.deviceId);
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(stsUrl))
            .timeout(Duration.ofMinutes(2))
            .header("Content-Type", "application/json")
            .build();
        HttpClient client = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_1_1)
            .connectTimeout(Duration.ofSeconds(20))
            .build();
        HttpResponse < String > response = client.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() < 200 || response.statusCode() >= 300) {
            return null;
        }
        if (response.body().isEmpty()) {
            return null;
        }
        return response.body().toCharArray();
    }
}

Souhrn implementace ověřování tokenu SAS pro sadu SDK zařízení služby Azure IoT Hub pro Javu:

  1. Implementujte rozhraní SasTokenProvider ve třídě a zahrňte funkci obnovení tokenu.

  2. Implementujte obslužnou rutinu Připojení ionStatusChangeCallback pro zachycení změn stavu připojení přenosu a zabránění výjimkám vyvolaným implementací přenosu.

Referenční informace:

Sada SDK pro zařízení služby Azure IoT Hub pro Python

Sada SDK zařízení služby Azure IoT Hub pro Python implementuje podporu tokenu SAS prostřednictvím metod v objektu IoTHubDeviceClient. Tyto metody umožňují vytvoření klienta zařízení pomocí tokenu a možnost zadat aktualizovaný token po vytvoření klienta zařízení. Neimplementují správu životnosti tokenů, ale dá se snadno implementovat jako asynchronní operace.

Ukázková implementace Pythonu 3.7 zobrazující jenom přehled funkcí:

import asyncio
import iothub_device_client

async def main():
    # Get a SAS token you generated
    sastoken = get_new_sastoken()
    # The client object is used to interact with your Azure IoT Hub.
    device_client = iothub_device_client.create_from_sastoken(sastoken)

    # Connect the client
    await device_client.connect()

    # Define behavior for providing new SAS tokens to prevent expiry
    async def sastoken_keepalive():
        while True:
            await asyncio.sleep(new_token_interval)
            sastoken = get_new_sastoken()
            await device_client.update_sastoken(sastoken)

    # Also run the SAS token keepalive in the event loop
    keepalive_task = asyncio.create_task(sastoken_keepalive())

    # Cancel the SAS token update task
    keepalive_task.cancel()

    # Finally, shut down the client
    await device_client.shutdown()

if __name__ == "main":
    asyncio.run(main())

Shrnutí sady SDK pro zařízení služby Azure IoT Hub pro ověřování tokenů SAS v Pythonu:

  1. Vytvoření funkce generování tokenu SAS

  2. Vytvořte klienta zařízení pomocí IoTHubDeviceClient.create_from_sastoken.

  3. Spravovat životnost tokenu jako samostatnou aktivitu a poskytnout klientovi zařízení obnovený token, pokud to vyžaduje metoda IoTHubDeviceClient.update_sastoken.

Referenční informace:

Sada SDK pro zařízení služby Azure IoT Hub pro Node.JS/JavaScript

Azure IoT pro Node.JS/JavaScript implementuje SharedAccessSignatureAuthenticationProvider, který bude obsluhovat token SAS klientovi zařízení a přenáší je k ověření ve službě IoT Hub. Neimplementuje žádnou funkci obnovení tokenu. Aplikace zařízení musí spravovat životnost tokenu a obnovovat token podle potřeby.

Pomocí metod klienta zařízení zesharedAccessSignature a aktualizaceSharedAccessSignature inicializovat připojení ke službě IoT Hub a poskytnout obnovený token sharedAccessSignatuteAuthenticationProvider, což způsobí, že zprostředkovatel ověřování vygeneruje do přenosů novou událostTokenAvailable.

V příkladu simple_sample_device_with_sas.js je k dispozici základní ukázka tokenu SAS.

Shrnutí sady SDK pro zařízení služby Azure IoT Hub pro Node.JS/JavaScript:

  1. Implementujte správu a obnovení životnosti tokenu SAS.

  2. Pomocí klienta zařízení zesharedAccessSignature vytvořte instanci klienta zařízení.

  3. Pomocí aktualizace klienta zařízeníSharedAccessSignature zadejte obnovený token.

Referenční informace:

Další kroky