Kategorie-Archiv: Allgemein

Azure IoT Hub – Shared Access Signature

Pro Device Authentifizierung/Autorisierung

Um Telemetry Daten von einem Gerät/Device an einen Azure IoT Hub zu senden stellt dieser, im Unterschied zu einem Azure Event Hub, eine pro Device Authentifizierung/Autorisierung zur Verfügung. D. h. für jedes Gerät muss ein Set an symmetrischen Schlüsseln erstellt werden.

Dies kann sowohl über Code und die Verwendung eines entsprechenden SDK erfolgen (siehe: https://github.com/RobertEichenseer/IoT_MasterClass/blob/master/MC_SensorIoTHub/MC_AdminBackend/ManageDevice.cs ) oder mit dem auf GitHub zum Download (https://github.com/Azure/azure-iot-sdks/releases ) zur Verfügung stehenden Device Explorer.

In vielen Beispielen wird nun einer dieser Schlüssel bzw. ein Connection-String, der diesen Schlüssel enthält, verwendet um Daten von einem Device zu einem IoT Hub zu senden bzw. Kommandos von diesem zu erhalten. Im „Get-Started“ Tutorial unter https://azure.microsoft.com/en-us/develop/iot/get-started/ findet sich der notwendige Source Code um basierend auf einem Device Connection String eine Verbindung zu einem IoT Hub aufzubauen. Der hierfür notwendige Connection String kann einfach erstellt oder z. B. aus einer Instanz des Device Explorers kopiert werden.

Device Explorer
Device Explorer

Der Connection String besteht hierbei aus der öffentlich verfügbaren Url der IoT Hub Instanz, der eindeutigen Id des Devices (erzeugt im Device Explorer oder via Code) und aus einem der für das Device erzeugtem symmetrischen Schlüssel.

Bsp.: HostName=iotvd.azure-devices.net;DeviceId=Device01;SharedAccessKey=4Ml+KlkFvFoggFJlb…t/I=

Authentifizierung von Datenpaketen

Interessant ist nun die Betrachtung einzelner Datenpakete und wie der symmetrische Schlüssel benützt wird um diese Datenpakete zu authentifizieren. Hierbei bietet sich an mit Hilfe von Fiddler und einem Device welches via https Datenpakete an eine IoT Hub Instanz sendet.

Beispielhafter Post:

POST https://robeich.azure-devices.net/devices/Device01/messages/events?api-version=2016-02-03 HTTP/1.1

iothub-messageid: 707aadea-9aff-43f4-b52b-c2b9b426d68d

Accept: application/json

iothub-app-CustomInfo: FromEmulator

Authorization: SharedAccessSignature sr=robeich-iotpoc.azure-devices.net%2Fdevices%2FDevice01&sig=pqauHmdPnd1VcxoKx6xKWW2s7SUjzPoXZyy87m7UX70%3D&se=1473178007

Content-Length: 150

Host: robeich-iotpoc.azure-devices.net

Connection: Keep-Alive

{"DeviceId":2385964,"Longitude":105.9,"Latitude":105.9,"RPM":600,"TyrePressure":3.1,"Speed":45.0,"OilTemperature":25.0,"CreationTime":"0001-01-01T00:00:00"}

Interessant ist hierbei, dass der Payload der Message nicht mit dem symmetrischen Schlüssel verschlüsselt worden ist. Vielmehr ist „nur“ ein zusätzlicher Headereintrag „Authorization“ hinzugefügt worden. Splittet man den Headereintrag auf findet sich der String „SharedAccessSignature“ sowie die drei Werte sr, sig und se. Dieser Headereintrag wird vom SDK automatisch erzeugt und von der IoT Hub Instanz verwendet um das Datenpaket zu autorisieren.

Shared Access Signature

Betrachtet man das Azure IoT SDK welches den Headereintrag erzeugt, zeigt sich, dass der Wert „se“ ein Zeitwert ist, der festlegt, wie lange das Nachrichtenpaket „gültig ist“ und somit von der IoT Hub Instanz akzeptiert und angenommen wird. Die Zahl steht für Sekunden ab dem 01.01.1970. Dieser Wert wird vom SDK automatisch berechnet und auf 60 Minuten ab der aktuellen Systemzeit gesetzt, sowie für jedes Datenpaket neu berechnet. Aktuell findet sich im SDK kein Property mit dem dieser Wert von außerhalb des SDK manuell gesetzt und damit beeinflusst werden kann.

Bei „sig“ handelt es sich um einen auf Basis des symmetrischen Schlüssel errechneten Hash Wert (HmacSha256) eines Strings. Dieser String setzt sich folgendermaßen zusammen:

<<Url_der_ IoT_Hub_Instanz>>/devices/<<DeviceId>>\n<<ExpirationInSeconds>>

Bsp.: iotvd.azure-devices.net/Fdevices/Device01\n1483142400

Bei “sr” handelt es sich um die Url der IoT Hub Instanz dem Literal devices sowie der eindeutigen Id des Devices welches das Nachrichtenpaket versendet

Diese drei errechneten Werte plus der String Konstante „SharedAccessSignature“ werden von der IoT Hub Instanz verwendet um das Nachrichtenpaket zu authentifizieren/autorisieren.

Erweiterungen

Da das auf dem Client ausgeführte SDK den Payload der Nachricht nicht mit dem symmetrischen Schlüssel chiffriert ergeben sich viele Möglichkeiten um die Sicherheit bei der Erteilung der Erlaubnis Daten von einem Device an eine IoT Hub Instanz zu versenden zu erhöhen. So muss beispielsweise der symmetrische Schlüssel, der bei der Anlage des Devices in der IoT Hub Instanz nicht auf dem Client übertragen und gespeichert werden. Dieser muss das sichere Umfeld der Cloud Instanzen nicht verlassen um den String Eintrag im Authorization Header zu erzeugen.

Dass Device kann diesen String z. B. in bestimmten Intervallen von einer einer WebApp anfordern. Wobei der vom Device bisher verwendete String automatisch nach Ablauf der Zeitspanne automatisch ungültig wird. Sollte dieser Fall auftreten kann das Device die WebApp kontaktieren, welche den Symmetrischen Schlüssel aus der IoT Hub Instanz aufgrund der eindeutigen Device Id welchem vom Device im Request mitgeliefert wird ausliest. Solch eine WebApp wird häufig als Discovery Service bezeichnet, da sie auch für andere Zwecke wie z. B. automatischer Failover, 24/7 Szenarien benützt werden kann. Die Absicherung der Kommunikation mit dem Discovery Service kann nun den jeweiligen Sicherheitsanforderungen angepasst werden. Die Palette reicht hier vom manuellen Eingriff, Multifaktor Systemen bis zu innovativen Machine Learning Algorythmen.

Ein Beispiel wie das Token off-Board, d. h. nicht auf dem Device erzeugt werden kann findet sich auf meinem GitHub Account unter: https://github.com/RobertEichenseer/IoT_HardeningIoTSecurity

C# Entwicklung + Arduino/Genuino

Gerade im privaten Umfeld erfreuen sich die Arduino/Genuino Boards großer Beliebtheit um alle Arten von IoT  Projekten umzusetzen.  Auch im kommerziellen / professionellen Umfeld erfreuen sich die Boards großer Beliebtheit um prototypische Umsetzungen von Projekten bzw. Geschäftsideen schnell und kostengünstig zu verproben. Um Arduino Boards anzuprogrammieren kann die Open Source Arduino IDE erwendet werden. Die Programmierung von sog. Sketchen (d. h. Programme die auf den Arduino Boards ausgeführt werden) ähnelt C/C++ und ist einfach zu erlernen.

Für C# / VisualBasic.NET oder generell Windows Runtime Entwickler welche die Hardware Möglichkeiten eines Arduino nutzen möchten gibt es noch eine zusätzliche Möglichkeit. Windows Remote Arduino ist eine Open Source Windows Runtime Komponente die es ermöglicht die analogen und digitalen Ports eines Arduino Uno von einem beliebigen Windows 10 Device aus zu benützen. Gerade wenn ein User Interface, UMTS, WiFi, Storage etc.  zusammen mit dem Arduino Board benötigt wird lohnt es sich ggf. ein günstiges Windows 10 Device zusammen mit dem Arduino einzusetzen. Auf dem GitHub Account des Projektes findet sich eine einfache Step-by-Step Anleitung um ein Windows 10 Device via USB, Bluetooth, WiFi oder Ethernet mit dem Arduino zu verbinden.

Folgt man der Anleitung, verbindet den Arduino z. B. via USB, lädt die notwendige Firmata Implementierung auf den Arduino und beginnt in Visual Studio mit einem leeren UWP Projekt, könnenzwar mittels UsbSerial.listAvailableDevicesAsync()

RemoteArduiono_01

 

alle verbundenen Arduino(s) (in diesem Falle über USB angebunden) ohne Fehler ermittelt werden. Versucht man jedoch die Kommunikation mit dem Arduiono mittels .begin() RemoteArduiono_02aufzubauen. Kommt es zu folgender Fehlermeldung

UsbSerial::connectToDeviceAsync failed with a Platform::Exception type. (message: Catastrophic failure Unable to initialize the device. Did you forget your USB device capabilities in the manifest? SerialDevice::FromIdAsync returned null.)

Selbst wenn im Manifest der UWP Applikation explizit der Zugriff auf den USB Port erlaubt wurde tritt der Fehler auf. RemoteArduiono_03

Trotzdem gibt die Fehlermeldung den entscheidenden Hiweis auf fehlende Capabilities im Manifest der Applikation. Um die Kommunikation mit dem Arduino erfolgreich durchführen zu können, muß die folgende Device Capability im Manifest eingetragen werden:

<DeviceCapability Name=“serialcommunication“>
      <Device Id=“any“>
        <Function Type=“name:serialPort“ />
      </Device>
    </DeviceCapability>
  </Capabilities>

RemoteArduiono_04

 

Nach einem nochmaligem Deploy der UWP App kann auch die Kommunikation mit dem Arduino erfolgreich initiiert werden.