Kategorie-Archiv: IoT

Hardening Azure Event Hub Solutions

Allgemein

In vielen IoT Scenarien stellt sich immer wieder die Frage wie der Daten Ingest von Devices (Things) zu einem zentralen Backend abgesichert werden kann. Hierbei ist neben der grundsätzlichen Absicherung des Transportweges auch die Absicherung des Dateningest einzelner Devices zu verstehen. Verwendet man den Azure IoT Hub kann jedes Device in dem zentralen Repository angelegt und mit entsprechenden Security Credentials versorgt werden. Dadurch ist eine feingranulare Verwaltung von Devices möglich. Letztendlich kann dadurch auf Device Ebene entschieden werden, ob die Daten des Device akzeptiert werden oder ggf. als kompromitiert betrachtet und verworfen werden.

Azure Event Hub stellt eine ähnliche Funktionalität zur Verfügung welche ebenfalls ermöglicht, den Daten Ingest von einzelnen Devices bereits auf Ebene des Event Hub zu blockieren.

Shared Access Policy

Nach Anlage eines Event Hub im Azure Portal können sogenannte „Shared Access Policies“ angelegt werden. Zu jeder Shared Access Policy werden zwei Keys erzeugt welche verwendet werden können, um ein Datenpaket zu signieren. D. h. Datenpakete welche von einem Device zu Azure Event Hub übertragen werden verwenden einen dieser Keys um einen Hash des Datenpaketes zu errechnen. Dieser Hash wird mit einem Key der erzeugten Shared Access Policy verschlüssen und zusammen mit anderen Informationen wie z. B. Event Hub Name und  Shared Access Policy Name zu einem String zusammengefasst. Dieser String wird nun jedem Datenpaket welches vom Device zum Event Hub übertragen wird beigefügt. Vereinfacht gesprochen handelt es sich bei diesem String um eine „Eintrittskarte“ welche das Datenpaket gegenüber dem Event Hub ausweist. Der Event Hub kann mittels der im String enthaltenen Informationen und einem privatem Schlüssel, der während der Anlage der Shared Access Policy ebenfalls erzeugt wurde und im Portal nicht sichtbar ist, prüfen ob die Signatur korrekt und damit das Datenpaket valide ist.

Der Key einer Shared Access Policy muss dementsprechend vertraulich behandelt werden. Viele Beispiele zu Übertragung von Daten von einem Device zu Event Hub verwenden jedoch den Key im Code des Devices. Insbesondere die Methode ServiceBusConnectionStringBuilder.CreateUseingSharedAccessKey() des aktuellen Azure Service Bus SDK (Azure Event Hub ist Teil des Azure Service Bus) macht es sehr einfach, auf Basis eines Shared Access Policy Key einen Connection String zum Event Hub zu erzeugen.

      

        public void TelemetryIngest()
        {
            string serviceBusNamespace = "<<Your Service Bus Namespace>> e. g. -> iotmc-ns";
            string eventHubName = "<<your Event Hub Name>> e. g. -> IoTMC";
            string eventHubSAPKeyName = "<<your Shared Access Policy Name>> e. g. -> Device01";
            string eventHubSAPKey = "<<your Key>> e.g. -> t0JK197745t345…s4N09aNI0s=";
            string eventHubConnectionString = ServiceBusConnectionStringBuilder.CreateUsingSharedAccessKey(
            ServiceBusEnvironment.CreateServiceUri("sb", serviceBusNamespace, string.Empty),
                eventHubSAPKeyName,
                eventHubSAPKey);
            EventHubClient eventHubClient = EventHubClient.CreateFromConnectionString(eventHubConnectionString, eventHubName);
            //Your code to ingest telemetry data
        }

Wurde das Device kompromitiert, muss serverseiting ein neuer Key generiert werden, damit Event Hub zukünftig Telemetry Ingests von diesem Device ablehnt. Dies ist solange machbar, wie eine geringe Anzahl von Devices installiert worden sind und für jedes Device eine eigene Shared Access Policy erzeugt wurde. Jedoch ist die Anzahl der erzeugbaren Shared Access Policies begrenzt, so dass mehrere (unter Umständen hunderte oder tausende) Devices mit dem Key einer einzigen Shared Access Policy Key provisioniert werden müssen. Wird nun ein einzelnes Device kompromitiert müssen unter Umständen hunderte oder tausende weitere Devices aktualisiert bzw. ausgetauscht werden.

Betrachtet man z. B. Devices die an einem Fließband z. B. die Tätigkeit von Robotern überwachen übermitteln so können diese in einer einfachen Anbindung den Key einer Shared Access Policy benützen, um Daten gegenüber einem Event Hub zu legitimitieren. In der Regel finden sich an einem Fließband sehr viele Sensoren und Devices so dass ein Key einer Shared Access Policy von ggf. vielen Devices verwendet werden muss.

Um diese Problematik zu adressieren, bietet sich eine Architektur an, bei der die Keys nicht auf dem Device gespeichert werden und sogenannte Shared Access Signature Tokens (SAS Token) „off-board“ erzeugt werden, die einen zeitlich begrenzten Daten-Ingest von den Devices erlauben.

„Off-Board“ Token Erzeugung

Bei der Erzeugung eines SAS Tokens „off-Board“ wird der Key der Shared Access Policy nicht auf den Devices  vorgehalten sondern von einem externen Service verwendet um ein SAS Token zu erzeugen, dass ebenfalls zur Legitimitierung von Telemetry Ingest am Event Hub verwendet werden kann. Diese Tokens beinhalten eine temporäre Komponente, d. h. sie sind nur für eine bestimmte definierbare Zeitspanne zur Legitimitierung am Event Hub gültig. Ein typischer Workflow bei der „off-Board“ Token Erzeugung stellt sich folgendermaßen dar:

  1. Device kontaktiert einen externen Service, in der Regel ein REST basierter Service (Discovery Service) und authorisiert sich mit den üblichen Verfahren (Pre-Shared-Key, OAuth etc.) I.d.R. werden hier noch zusätzliche Metadaten übertragen und die vom Discovery Service geprüft. Z. B. aktuelle IP Adresse oder GPS Daten um zu prüfen, ob das Device sich noch an der vorgesehen physikalischen oder netzwerktechnischen Position befindet. Sehr häufig findet sich hier auch eine Prüfung des letzten Daten Ingest. Diese Information kann im Backend ermittelt werden und ist hier bereits eine gewisse Zeitspanne seit dem letzen Daten Ingest verstrichen und es sind keine Wartungsarbeiten, Bandstillstand etc. aufgetreten kann dieses Device als zumindest „wartungsbedürftig“ oder im extremen Fall als kompromitiert betrachtet werden. In diesem Fall wird kein Token vom Service ausgestellt. Ohne gültiges Token ist auch kein Telemetry Ingest am Event Hub möglich.
  2. Ist die Authorisierung und Prüfung der Metadaten erfolgreich, kann der Discovery Service ein Token für das jeweilige Device erstellen und als Return Value eines potentiellen REST Call an das Device übermittelt werden. Die detailierte Beschreibung, wie dieses Token erzeugt wird, findet sich im weiteren Verlauf des Artikels.
  3. Das Device verwendet das erzeugte Token beim Telemetry Ingest an den Event Hub um diesen zu legitimitieren.

Erzeugung Shared Access Signature (SAS) Token

Ein SAS Token beinhaltet neben der bereits erwähnten zeitlichen Komponente zusätzlich die Möglichkeit ein einzelnes Device eindeutig zu identifizieren. Dies kann über einen String z. B. eine Guid oder einen beliebige andere Kennung erfolgen. Im SDK wird hierbei von einem Publisher gesprochen. Die Erzeugung eines SAS Token gestaltet sich nun mit Hilfe des Service Bus SDK sehr einfach. Die Methode SharedAccessSigantureTokenProvider.GetPublisherSharedAccessSignature() erzeugt ein entsprechendes SAS Token:

        string CreateSASToken()
        {
            Uri serviceBusEndPoint = new Uri("<<your service bus endpoint e.g. -> sb://iotvd-ns.servicebus.windows.net/");
            string eventHubName = "<<your Event Hub Name>> e.g. -> IoTMC"; ;
            string publisherId = "<<your device publisher id e.g. -> DeviceLocatedAtMachine01";
            string eventHubSAPKeyName = "<<your Shared Access Policy Name>> e. g. -> send";
            string eventHubSAPKey = "<<your Key>> e.g. -> t0JK197745t345…s4N09aNI0s=";
            TimeSpan ingestValidTimeSpan = new TimeSpan(0, 5, 0);

            return SharedAccessSignatureTokenProvider.GetPublisherSharedAccessSignature(
                            serviceBusEndPoint, 
                            eventHubName, 
                            publisherId, 
                            eventHubSAPKeyName, 
                            eventHubSAPKey, 
                            ingestValidTimeSpan);
      }

Auf dem Device kann das erzeugte Token nun verwendet werden um einen Telemetry Ingest zum Event Hub durchzuführen:

void IngestTelemetry()
 {
Uri serviceBusEndPoint = new Uri("< sb://iotvd-ns.servicebus.windows.net/");
 string eventHubName = "<> e.g. -> IoTMC";
 string publisherId = "< DeviceLocatedAtMachine01";
 string sASToken = "<>";
string eventHubConnectionString = ServiceBusConnectionStringBuilder.CreateUsingSharedAccessSignature(
serviceBusEndPoint,
eventHubName,
publisherId,
sAStoken);
var eventHubSender = EventHubSender.CreateFromConnectionString(eventHubConnectionString);
eventHubSender.Send(new EventData(Encoding.UTF8.GetBytes("<>>")));

Das Device kann nun bis zum Ablauf der vom Discovery Service gewählten Zeitspanne das SAS Token benützen, um Daten an den Event Hub zu senden. Sobald diese Zeitspanne abgelaufen ist wird das Token ungültig und beim Senden der Telemetry Daten tritt eine Exception auf. In diesem Fall kann das Device wieder den Discovery Service kontaktieren und ein neues SAS Token anfordern. Sollte der Discovery Service Unregelmäßigkeiten feststellen, kann er diese Ausstellung verweigern und der Telemetry Ingest von evtl. kompromitierten oder fehlerhaften Devices somit unterbinden.

 

Blockierung von einzelnen Devices

Solange die Zeitspanne die bei der Erzeugung eines SAS Tokens angegeben worden ist, kann dieses Token verwendet werden um Daten an einen Event Hub zu senden. Es gibt keine Möglichkeit, ein Token vor Ablauf der Gültigkeit als ungültig zu kennzeichnen und damit einen Telemetry Ingest zu unterbinden.

Um trotzdem den Ingest von einem als fehlerhaft oder kompromitiert eingestuftem Device vor Ablauf der Token Gültigkeit zu unterbinden kann die Publisher Id des jeweiligen Device verwendet werden. Diese Publisher Id wird der Methode ServiceBsConnectionStringBuilder.CreateUsingSharedAccessSignature() übergeben um einen ConnectionString zum Event Hub zu erzeugen.

        
        void IngestTelemetry()
        {

            Uri serviceBusEndPoint = new Uri("<<your service bus endpoint e.g. -> sb://iotvd-ns.servicebus.windows.net/");
            string eventHubName = "<<your Event Hub Name>> e.g. -> IoTMC";
            string publisherId = "<<your device publisher id e.g. -> DeviceLocatedAtMachine01";
 string sASToken = "<<Token generated by Discovery Service>>";
 
            string eventHubConnectionString = ServiceBusConnectionStringBuilder.CreateUsingSharedAccessSignature(
                serviceBusEndPoint, 
                eventHubName, 
                publisherId, 
                sAStoken);

            var eventHubSender = EventHubSender.CreateFromConnectionString(eventHubConnectionString);

            eventHubSender.Send(new EventData(Encoding.UTF8.GetBytes("<<Your Telemetry Data")));
        }

Diese Publisher Id kann wie bereits erwähnt beliebig gewählt werden und sollte jedes Device eindeuting kennzeichnen.

Soll nun der Telemetry Ingest von einem bestimmten Device vor Ablauf der Token Lebenszeit gesperrt werden, kann dies über die Methode RevokePublisher()  einer Instanz des Objektes NamespaceManger des Service Bus SDK erreicht werden. Zu beachten ist, dass hierfür eine Verbindung zum Service Bus Namespace in dem der Event Hub angelegt wurde notwendig ist. Eine Verbindung zum jeweiligen Event Hub auf dem der Telemetry Ingest eines Devices blockiert werden soll ist hierfür nicht ausreichend. Die Verbindung muss zusätzlich über die Berechtigung „manage“ verfügen. Am einfachsten ist es hierbei den notwendigen Connection String direkt aus dem Azure Portal zu kopieren. Nach erfolgreicher Instanzierung eines Namespace Manger Objektes können die Methoden RevokePublisher() und RestorePublisher() verwendet werden, um den Telemetry Ingest zu blockieren oder nach bereits erfolgter Blockierung wieder zuzulassen. Beide Methoden erwarten hierfür zum einen den Namen des Event Hub und die jeweilige Publisher Id des Devices:

        void IngestTelemetry()
        {
            Uri serviceBusEndPoint = new Uri("<<your service bus endpoint e.g. -> sb://iotvd-ns.servicebus.windows.net/");
            string eventHubName = "<<your Event Hub Name>> e.g. -> IoTMC";
            string publisherId = "<<your device publisher id e.g. -> DeviceLocatedAtMachine01";
            string sASToken = "<<Token generated by Discovery Service>>";
 
            string eventHubConnectionString = ServiceBusConnectionStringBuilder.CreateUsingSharedAccessSignature(
                serviceBusEndPoint, 
                eventHubName, 
                publisherId, 
                sAStoken);
            var eventHubSender = EventHubSender.CreateFromConnectionString(eventHubConnectionString);
            eventHubSender.Send(new EventData(Encoding.UTF8.GetBytes("<<Your Telemetry Data")));
        }

Fazit

Auch wenn es auf den ersten Blick kofortabel und schnell möglich ist, den Key einer Shared Access Policy direkt in einem Device zu verwenden, sollte man bei der Konzeption einer IoT Lösung einen sogenannten Discovery Service mit der „off-board“ Erzeugung von sogenannten Shared Access Policy Tokens berücksichtigen. Die dadurch gewonnenen Möglichkeiten eine IoT Lösung abzusichern wiegen in der Regel den zusätlichen Aufwand und die zusätzlichen Kosten zur Betreibung/Wartung des Discovery Service auf.

 

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.

 

IoT Hackathon UG Nürnberg

image

Vielen Dank an alle Teilnehmer des Azure IoT TechCamp am 23.04.2014 in Nürnberg. Wie während des Event angekündigt hier noch einmal eine Zusammenfassung der Links zu Code-Snippets bzw. Hardware Intro sowie die verwendeten Slide – Decks:

Getting started:

Tessel: http://start.tessel.io/install

Arduino Yun: http://www.arduino.cc/en/Guide/ArduinoYun

Code Snippets / Dienste:

https://github.com/dx-ted-emea/azure-tessel

Hier finden sich komplette Hands-On-Labs wie ein Tessel Microcontroller (oder generell “Things” mit einem HTTP Stack) Azure basierte Resourcen wie z. B. EventHub, ServiceBus, Mobile Services, WebSites etc. benützen können.

https://github.com/dx-ted-emea/iot-labs

Unter dem Link findet sich ein komplettes End-To-End Szenario aufgeteilt in mehrere Labs. Die Labs decken den Daten Ingest als auch die Verarbeitung der Daten als Stream sowie Rückmeldungen (Command & Control) an die Endgeräte ab.

http://www.connectthedots.io

Ebenfalls ein komplettes Hands-On-Lab welches ein IoT Szenario abdeckt. Ein sehr interessantes Mittel zum Eigenstudium welches viele Azure Backend Dienste vorstellt.

https://github.com/RobertEichenseer/IoT_MasterClass

Sammlung von hilfreichen Code-Snippets wie z. B. das Senden von Telemetrie Daten an einen Azure Event Hub aus einer Universal App, einer Win32 App, .net Micro Framework etc.

https://github.com/crossbario/crossbarexamples/wiki/TechCamp

Crossbar.IO ein Open Source Produkt welches einfach über den Azure Marketplace installiert und benützt werden kann. Crossbar.IO adressiert unter anderem das “Command & Control” Paradigma welches in nahezu jeder IoT Lösung benötigt wird.  

Slide Decks:

Die verwendeten Slide Decks finden sich unter: http://1drv.ms/1DZhqR9

Netduino, IoT Applikationen mit VS 2013 erstellen

imageDas Netduino Prototyping Board ist ein in der .NET community beliebtes Board, welches auf dem .NET Micro Framework aufbaut. Das Netduino ist pin-kompatibel mit dem Arduino Board und damit steht eine große Anzahl an Sensoren, Aktoren und Gadgets zur Verfügung die in eigenen IoT Applikationen eingesetzt werden können. Für viele .NET Entwickler ist jedoch der größte Vorteil, dass zur Entwicklung von Applikationen C# und Visual Studio eingesetzt werden kann. Das Lernen von neuen Sprachen und Entwicklungsumgebungen ist dadurch nicht nötig. 

Colin Miller hat auf dem .NET Micro Framework Blog angekündigt, dass Microsoft das Investment in die Plattform wieder erhöhen wird. Erste Ankündigungen zeigen Investment im Bereich der asynchronen Entwicklung und der Integration in die aktuellen Visual Studio Versionen. Aktuell wird auf der Netduino Homepage noch Visual Studio 2010 als notwendige Entwicklungsumgebung genannt. Eine Side-By-Side Installation von VS 2010 mit VS2013 oder der Beta von VS2014 ist zwar möglich, trotzdem erscheint die Installation einer “alten” Version von VS nicht komfortabel, gerade wenn die “Device-Entwicklung” Bestandteil eines größeren Projektes ist und eine gemeinsame Solution für alle Komponenten gepflegt werden soll. Aktuell existiert eine Beta Integration, die es ermöglicht, Netduino Apps mit Visual Studio 2013 zu erstellen.

Folgende Schritte sind dazu nötig:

  1. Deinstallation aller evtl. vorhandenen .NET Micro Framework und Netduino SDKs vom Computer
  2. Deinstallation aller VS Extensions (Tools –> Extension and Updates; nach .NET Micro suchen)
  3. Installation des .NET MF SDK v4.3 R2 (beta)
  4. Installation des .NET MF v4.3 R2 (beta) add-in für VS 2013
  5. Installation des Netduino SDK v4.3.1

Nach Installation aller Komponenten sollte in VS 2013 neue Projekt Templates für das Micro Framework und die Netduino Entwicklung angezeigt werden.

image

Die nächste Herausforderung stellt i. d. R. das Netduino Board selbst dar. Meist ist nicht die in der Beta Version verwendete Firmware Version 4.3.1 sondern 4.2 bzw. 4.1 installiert. Dies äußert sich in einer Fehlermeldung

Cannot deploy the base assembly ‚mscorlib‘, or any of his satellite assemblies, to device – USB:Netduino twice. Assembly ‚mscorlib‘ on the device has version 4.2.0.0, while the program is trying to deploy version 4.3.1.0

Chris Walker hat auf seinem Blog eine Update Tool zur Verfügung gestellt um die Firmware auf dem Netduino (Achtung: nur für Netduino Plus 2) zu flashen. Folgende Schritte sind nötig:

  1. Netduino vom USB Port des Computers trennen um in auszuschalten
  2. Den Button auf dem Netduino drücken und gedrückt halten während dieser via USB mit dem Computer verbunden wird.
  3. Das oben verlinkte Update Tool starten und die Firmware 4.3.1 auf das Netduino Board übertragen.

Nach erfolgreichem Flash der Firmware können die Netzwerkeinstellungen (IP oder DHCP) des Board mit MFDeploy (Target –> Configuration –> Networking) neu vergeben werden.