Szerkesztés

Share via


Az Azure IoT-ügyfél SDK támogatása külső jogkivonat-kiszolgálókhoz

Azure IoT
Azure IoT Hub

Az IoT Hubhoz való hozzáférés szabályozása című cikk bemutatja, hogyan integrálható egy külső jogkivonat-szolgáltatás az IoT Hubbal. Ez a cikk a közös hozzáférésű jogosultságkódok (SAS) jogkivonat-hitelesítésének támogatását ismerteti az egyes Azure IoT-ügyféloldali SDK-kban. Azt is ismerteti, hogy mit kell implementálni egy eszközalkalmazásban a megfelelő SDK-val az egyes nyelvekhez, valamint azt is, hogyan használhatók eszközhatókörű vagy modulhatókörű jogkivonatok az Eszköz Csatlakozás vagy modul megosztott hozzáférési szabályzataihoz Csatlakozás.

Kontextus és probléma

Az Azure IoT Hub jelenlegi biztonsági dokumentációja az Azure IoT-ügyfél SDK-jait használó IoT Hubtal végzett SAS-hitelesítés külső jogkivonat-kiszolgálói mintáját ismerteti. Az ügyfél által a legutóbbi nagyvállalati előjegyzés során tett helytelen feltételezések azonban arra utalnak, hogy további pontosítás nélkül félrevezető benyomást kelthet az Azure IoT-ügyfél SDK-kban alapértelmezés szerint implementált támogatási szintről.

Ez a cikk az előjegyzésből származó ismereteket ismerteti, és tisztázza, hogy mit kell tenni az egyes SDK-kban az eszközök számára a külső jogkivonat-kiszolgáló hitelesítésének eléréséhez. Ez a cikk azt is megakadályozza, hogy az Azure IoT-ügyfél SDK-ban a külső jogkivonat-kiszolgáló mintájának támogatásával kapcsolatban hasonló helytelen feltételezéseket tegyen.

Megoldás

Az Azure IoT-ügyféloldali SDK-k különböző szintű támogatást nyújtanak az SAS-jogkivonat-hitelesítéshez, és mindegyikhez egyéni kód szükséges a hitelesítés és a jogkivonat-kezelési funkció elvégzéséhez.

A jogkivonat-kiértékelési gyakoriság a választott átviteli protokolltól függ – MQTT, AMQP vagy HTTPS. A változat attól függ, hogy a protokoll képes-e támogatni a jogkivonatok proaktív megújítását és a munkamenetek időtúllépését. Csak az AMQP implementálja a proaktív megújítási támogatást. Ez azt jelenti, hogy a többi átvitel sasjogkivonat-hitelesítési hiba esetén bezárja a kapcsolatot, majd új kapcsolati műveletet kell végrehajtania. Ez egy potenciálisan költséges kapcsolati művelet az ügyfél számára.

Ha az SAS-hitelesítés sikertelen, az átviteli implementáció hibát jelez, amelyet az eszközalkalmazásban egy "Csatlakozás ion Status Changed" eseménykezelővel lehet kezelni. Az ilyen kezelő implementálásának sikertelensége általában azt fogja látni, hogy az eszközalkalmazás leáll a hiba miatt. Az eseménykezelő és a jogkivonat megújítási funkciójának megfelelő implementálásával az átvitelek újra megpróbálhatják a kapcsolatot.

Az alábbi ábra a külső jogkivonat-kiszolgáló mintáját mutatja be:

A külső jogkivonat-kiszolgáló mintájának illusztrációja

Az alábbi ábra az Azure IoT-ügyfél SDK implementálási támogatását szemlélteti a Mobile Net Operator-integrációval:

Implementálási támogatás folyamatábra az Azure IoT ügyféloldali SDK-ban Mobile Net Operator-integrációval

A minta implementációk a GitHub Azure Samples-adattárában találhatók.

Problémák és megfontolandó szempontok

Vegye figyelembe a következő szempontokat, amikor eldönti, hogy megvalósítja-e ezt a mintát:

  • Az Azure IoT Hub Device Provisioning Service (Azure DPS) ügyféloldali SDK-k nem támogatják az SAS-jogkivonat-hitelesítést. Az Azure DPS REST APItámogatja az SAS-jogkivonatok hitelesítését. Ezért ahhoz, hogy az Azure DPS-t külső jogkivonat-szolgáltatással használhassa SAS-hitelesítéshez, az eszközalkalmazásnak implementálnia kell az eszköz DPS-folyamatát az Azure DPS REST API használatával.

  • Ez egy kezdeti regisztrációs kérelem műveletet, majd az üzemeltetési állapot API lekérdezését foglalja magában, amíg a DPS-folyamat sikeres vagy sikertelen nem lesz. Sikeresség esetén az eszköz kiépítésének részletei az Azure DPS REST API futtatókörnyezet-regisztrációjából kérhetők le.

Mikor érdemes ezt a mintát használni?

Ezt a mintát akkor érdemes használnia, amikor az Azure IoT Hubon szeretne hitelesítést végezni az IoT-eszközökről a különböző Azure IoT-ügyféloldali SDK-k használatával. Az ügyféloldali SDK-k SAS-jogkivonat-hitelesítéshez való használata helyett az Azure DPS REST API-val biztosíthatja az összes átviteli mechanizmus proaktív megújítási támogatását.

Példák

Az alábbi szakaszok példákat mutatnak be a különböző programozási nyelvekhez, például az Embedded C, a .NET, a Java és a Python nyelvhez.

Azure IoT Hub device SDK for C és Azure IoT Hub device SDK for Embedded C

Az alábbi megközelítés az Azure IoT C SDK vagy az Azure IoT Embedded C SDK használatával létrehozott eszközalkalmazásokban használható. Egyik SDK sem biztosít SAS-jogkivonatok élettartam-kezelését, ezért egy SAS-jogkivonat élettartam-kezelői képességét kell implementálnia.

Az SAS-jogkivonatok a IOTHUB_CLIENT_CONFIG struktúrán keresztül használhatók, ha a deviceSasToken tagot a jogkivonatra állítja, és null értékűvé teszi a deviceKey-t . Az egyéb nem használt értékeket, például a protocolGatewayHostName értéket is null értékre kell állítani.

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

A connection_status_callback elkaphatja a IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN IOTHUB_CLIENT_CONNECTION_STATUS_REASON, hogy elindítsa az SAS-jogkivonat megújítását a külső jogkivonat-szolgáltatáson keresztül. Ez minden átvitel esetében szükséges a csatlakozási problémák rögzítéséhez, de kifejezetten olyan átvitelekre van szükség, amelyek nem támogatják a proaktív SAS-jogkivonat-megújítást. A proaktív SAS-jogkivonatok élettartam-kezelése az eszközalkalmazások "működési" ciklusa során ismétlődően futtatott függvényként implementálható. A jogkivonat élettartamának rendszeres kiértékelése és a jogkivonat megújítása szükség esetén proaktívan végrehajtható.

SAS-jogkivonat-hitelesítés implementációjának összefoglalása C SDK-khoz:

  1. Implementáljon egy Csatlakozás ionStatusCallback kezelőt IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN esemény rögzítéséhez és a jogkivonat megújításának aktiválásához.

  2. Egy IOTHUB_CLIENT_CONFIG használatával adja meg az eszköz SAS-jogkivonatát a IoTHubDeviceClient_Create.

  3. Proaktív SAS-jogkivonatok élettartam-kezelésének megvalósítása az eszközalkalmazás működési ciklusának részeként.

Azure IoT Hub eszköz SDK for .NET

A .NET-hez készült Azure IoT-ügyfél SDK az absztrakt DeviceAuthenticationWithTokenRefresh osztályon keresztül támogatja az SAS-jogkivonatok élettartamának kezelését. Ennek az osztálynak a konkrét implementációja, amely tokenmegújítási funkciókat ad hozzá, hitelesítési módszerként is megadható a DeviceClient.Create metódushoz. Az átviteli implementációk szükség szerint automatikusan megújítják a jogkivonatot a hitelesítési módszerrel. Egy Csatlakozás ionStatusChangesHandler szükséges a kapcsolatváltozások rögzítéséhez és az átvitelek által kiváltott kivételek megelőzéséhez.

Példa implementáció a DeviceAuthenticationWithTokenRefreash osztály alapján:

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

SAS-jogkivonat-hitelesítés implementációjának összefoglalása a .NET-hez készült Azure IoT Hub-eszköz SDK-hoz:

  1. Implementáljon egy konkrét osztályt a DeviceAuthenticationWithTokenRefresh absztrakt osztály alapján, amely a tokenmegújítási funkciót valósítja meg.

  2. Implementáljon egy Csatlakozás ionStatusChangesHandlert az átviteli kapcsolat állapotának rögzítéséhez és a szállítás implementációja által kiváltott kivételek elkerüléséhez.

Referenciák:

Azure IoT Hub device SDK for Java

Az Azure IoT Client SDK for Java a SasTokenProvider interfészen keresztül támogatja az SAS-jogkivonatok élettartamának kezelését. Az SAS-jogkivonat megújítási funkciójával rendelkező felületet implementáló osztály SecurityProviderként használható a DeviceClient-konstruktorban. Az átviteli implementációk szükség szerint automatikusan megújítják a jogkivonatot a biztonsági szolgáltatón keresztül. Regisztrálni kell egy Csatlakozás ionStatusChangeCallbacket a kapcsolatváltozások rögzítéséhez és az átvitelek által kiváltott kivételek megelőzéséhez.

Példa a SasTokenProvider felületet implementáló biztonsági szolgáltató implementálására:

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

SAS-jogkivonat-hitelesítés implementációjának összefoglalása a Java-hoz készült Azure IoT Hub-eszköz SDK-hoz:

  1. Implementálja a SasTokenProvider felületet egy osztályon, és tartalmazza a tokenmegújítási funkciókat.

  2. Implementáljon egy Csatlakozás ionStatusChangeCallback kezelőt az átviteli kapcsolat állapotváltozásának rögzítéséhez és az átvitel implementációja által kiváltott kivételek elkerüléséhez.

Referenciák:

Azure IoT Hub device SDK for Python

A Pythonhoz készült Azure IoT Hub-eszköz SDK az IoTHubDeviceClient objektum metódusain keresztül valósítja meg az SAS-jogkivonatok támogatását. Ezek a metódusok lehetővé teszik egy eszközügyfél jogkivonattal történő létrehozását, valamint a frissített jogkivonatok megadását az eszközügyfél létrehozása után. Nem implementálják a jogkivonatok élettartamának kezelését, de ez egyszerűen implementálható aszinkron műveletként.

Egy Python 3.7-példa implementáció, amely csak a funkciók vázlatát mutatja be:

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())

Az Azure IoT Hub eszköz SDK-jának összefoglalása Python SAS-jogkivonat-hitelesítéshez:

  1. SAS-jogkivonat-létrehozási függvény létrehozása.

  2. Eszközügyfél létrehozása IoTHubDeviceClient.create_from_sastoken használatával.

  3. A jogkivonatok élettartamának kezelése külön tevékenységként, az eszközügyfél megújult jogkivonattal való ellátása, ha az IoTHubDeviceClient.update_sastoken metódus megköveteli.

Referenciák:

Azure IoT Hub eszköz SDK Node.JS/JavaScripthez

A Node.JS/JavaScripthez készült Azure IoT egy SharedAccessSignatureAuthenticationProvidert implementál, amely egy SAS-jogkivonatot fog kiszolgálni az eszközügyfél számára, és az IoT Hubbal való hitelesítéshez szállít. Nem implementál jogkivonat-megújítási funkciókat. Az eszközalkalmazásnak kezelnie kell a jogkivonat élettartamát, és szükség szerint meg kell újítania a jogkivonatot.

A SharedAccessSignature és az updateSharedAccessSignature eszközügyfél-metódusaival kapcsolatot kezdeményezhet az IoT Hubbal, és megújult jogkivonatot adhat meg a SharedAccessSignatuteAuthenticationProvidernek, ami miatt a hitelesítésszolgáltató új, Available eseményt bocsát ki az átvitelek számára.

Az simple_sample_device_with_sas.js példában egy alapszintű SAS-jogkivonat-minta található.

Az Azure IoT Hub eszköz SDK Node.JS/JavaScripthez készült összefoglalása:

  1. AZ SAS-jogkivonat élettartam-felügyeletének és megújításának megvalósítása.

  2. Az eszközügyfél fromSharedAccessSignature használatával hozzon létre egy eszközügyfél-példányt.

  3. Az eszközügyfél updateSharedAccessSignature használatával adjon meg egy megújított jogkivonatot.

Referenciák:

Következő lépések