Select Page

NETWAYS Blog

Spracherkennung als Sicherheitsrisiko

Was vor fünf Jahren noch undenkbar war, findet sich heutzutage in fast jedem Mobiltelefon: Spracherkennung. Die Einstiegshürde ist inzwischen dank Fortschritten bei der Erkennungsgenauigkeit sehr niedrig. Im Gegensatz zu Spracherkennungssoftware der ersten Generation ist auch das Training mit Mustertexten nicht notwendig.
Allgemein scheint der Trend in die Richtung zu gehen, Spracherkennung auf möglichst vielen Plattformen anzubieten. So hat Apple beispielsweise kürzlich Siri in macOS Sierra integriert und Microsoft bietet Cortana für Windows 10 an. Zusätzlich verkaufen sowohl Google als auch Amazon auf dem Gebiet der Home Automation Lautsprecher mit integriertem Mikrofon, die auf Spracheingabe reagieren.
Viele dieser Systeme “hören” permanent mit und reagieren auf bestimmte Schlüsselwörter: z.B. “Ok, Google”, “Hey Alexa”, “Hey Siri” und “Xbox”. Dabei findet in der Regel keine Unterscheidung zwischen verschiedenen Stimmen statt, weswegen auch andere Personen als der Besitzer des Geräts Befehle ausführen können, sofern sie sich in der Nähe befinden.
Bei Systemen wie Amazon Echo können Besucher beispielsweise kostenpflichtige Bestellungen aufgeben. Die meisten Mobiltelefone erlauben es, Kontakte anzurufen oder ihnen Nachrichten zu senden.
Andererseits kann auch der rechtmäßige Besitzer dazu veranlasst werden, ungewollt Befehle auszuführen, wie dieses YouTube-Video am Beispiel der Xbox One zeigt.
Da die meisten Mobiltelefone gar nicht die notwendige Rechenleistung aufbringen können, um die Spracherkennung selbst durchzuführen, senden sie eine Aufnahme der gesprochenen Worte an ihren Hersteller. Was dieser im Detail damit macht, wird zwar in den Datenschutzrichtlinien dargelegt – jedoch werden bestimmte externe Partner (NSA, Bundesnachrichtendienst, Verfassungsschutz, u.ä.) dort nicht erwähnt.
Ich für meinen Teil verzichte auf meinen persönlichen Teleschirm und habe daher auf allen meinen Geräten Siri, Cortana und co. deaktiviert. Nicht nur zur Wahrung meiner Privatsphäre, sondern auch, weil ich mir ziemlich komisch vorkommen würde, in der Öffentlichkeit mit meinem Handy zu sprechen – aber vielleicht bin ich auch einfach zu alt für solch neumodischen Kram.

Speicherverbrauch analysieren mit Heaptrack

Um den Speicherverbrauch von Icinga 2 besser verstehen zu können, habe ich mir einen Docker-Container für heaptrack (gbeutner/heaptrack) gebaut. Heaptrack ist ähnlich wie Massif ein Tool, das dabei hilft, herauszufinden, wie Anwendungen Speicher verwenden:
heaptrack
In diesem Fall sieht man sehr schön, dass Strings zahlenmäßig anderen Objekt-Typen in Icinga 2 deutlich überlegen sind. Die Anzahl der geleakten Objekte ist in diesem Fall falsch, da ich den Icinga-Prozess mit Strg-C abgebrochen habe.
Der Speicherverbrauch ist eine der Stellen, an denen ich aktuell fleißig am optimieren bin, um sowohl den insgesamt benötigten Speicher allgemein zu verringern, aber auch um die Anzahl der temporär angelegten Objekte so klein wie möglich zu halten – was sich positiv auf die benötigte CPU-Zeit auswirkt. Zwischen der Version 2.4.10 und dem aktuellen Git-Master (“2.6.0”) habe ich den Config-Validator so z.B. bereits um fast 50% schneller gemacht (71 Sekunden mit 2.4.10 und nun aktuell 37 Sekunden)

Updates für den NETWAYS-Mittagsshop

Der NETWAYS-Mittagsshop ist eine von uns intern genutzte Anwendung, um z.B. Pizzabestellungen gesammelt ausführen zu können. Seit Kurzem unterstützt er nun einige neue Features:
1. Bestellstatistiken
Der Shop bietet nun eine Statistikfunktion, mit der z.B. die Bestellanzahl ausgewertet werden kann.
Bestellstatistik
2. Bearbeiten von Bestellungen
Benutzer können nun nachträglich ihre eigenen Bestellungen bearbeiten, ohne diese vorher löschen zu müssen. Außerdem können Händler für andere Benutzer Bestellungen einstellen bzw. auch ändern, wem eine Bestellung gehört.
3. Der Jabberbot ist nun im Git-Repository.
Der Sourcecode des Jabberbots befindet sich im Verzeichnis “jabber”. Der Bot unterstützt Befehle, um Bestellungen aufzugeben und den aktuellen Bestellstatus abzufragen.
4. Rabatte/Liefergebühren werden nun richtig berechnet
An sich ist das natürlich kein Feature, aber der Shop rundet Rabatte und Liefergebühren nun korrekt, auch wenn z.B. der Rabattsatz geändert wird, nachdem bereits Bestellungen aufgegeben wurden.
Für die Rabattfunktion kann nun zusätzlich auch ein Benutzer angegeben werden, dem die gewährten Rabatte per interner Lastschrift berechnet werden.
5. Die Menüs der Läden sind nun bearbeitbar.
Ursprünglich mussten Speisekarten mühsam mit SQL-Kommandos manuell in die Datenbank eingefügt werden. Dabei hat der durchschnittliche Laden ca. 500 Menüeinträge (verschiedene Pizzas mit Varianten: klein, groß, u.ä.). Inzwischen gibt es nun eine textbasierte Beschreibungssprache, die sogar Templates unterstützt. Somit können z.B. Preise per Git-Commit einfacher angepasst werden.

Avoiding Common Pitfalls with Apply Rules

When building apply rules for your Icinga 2 configuration there are a few common pitfalls you should avoid:
1. Using apply when you’re really just creating a single object
Rule-based configs are great at simplifying your config. However, there are times when you really just want to create a single object. One common anti-pattern I’ve come across is this:

apply Service "ntp" {
  ...
  assign where host.name == "ntp1.example.org"
}

Now, obviously this will work as intended, however there are two significant problems: Writing a filter rule for a single host is unnecessarily complicated and additionaly there is a significant performance penalty because this rule has to be evaluated for all of your hosts.
A much simpler way to achieve this is to just use a simple object declaration:

object Service "ntp" {
  host_name = "ntp1.example.org"
  ...
}

2. Using too many assign where rules
Apply rules are intended to be used to make your config more general by putting your hosts into certain classes (“all ntp servers”, “all database servers”, etc.) and then assigning services and notifications to each member of a certain class. However, for some reason people sometimes do this instead:

apply Service "web" {
  ...
  assign where host.name == "web1.example.org"
  assign where host.name == "web2.example.org"
  assign where host.name == "web3.example.org"
  ...
  assign where host.name == "web73.example.org"
}

The obvious problem here is that this is a maintenance nightmare – and as we’ve already learned “assign where” rules aren’t exactly free in terms of performance.
Unlike in our first example the solution isn’t to unroll this filter by creating an “object” definition for each of the hosts. Instead you should use some of the great filtering capabilities that come with Icinga 2. Here’s a short list of just some of the filters that are available:
1. CIDR matching (using the cidr_match function)
2. Regular expressions (using the regex function)
3. Wildcard matches (using the match function)
4. and last but not least: custom variables
In this particular example I’m going to use wildcard matching and custom variables:

object Host "web1.example.org" { }
object Host "web2.example.org" { }
object Host "web3.example.org" { vars.no_web_check = false }
apply Service "web" {
  ...
  assign where match("web*.example.org", host.name)
  ignore where host.vars.no_web_check
}

This assumes that all of your “web” hosts should have a “web” service by default. Using “ignore where” we can make sure that certain hosts don’t get the service.
3. Reusing “assign where” filters
This is pretty much the opposite problem compared to our previous example. Instead of using the same filter expression dozens of times in the same apply rule this is about unnecessarily repeating the filter in multiple apply rules:

apply Service "mysql" {
  ...
  // All db hosts except those in the dev subnet
  assign where match("db*.example.org", host.name) && !cidr_match("172.16.23.0/24", host.address)
}
apply Service "postgresql" {
  ...
  // All db hosts except those in the dev subnet
  assign where match("db*.example.org", host.name) && !cidr_match("172.16.23.0/24", host.address)
}
apply Service "mssql" {
  ...
  // All db hosts except those in the dev subnet
  assign where match("db*.example.org", host.name) && !cidr_match("172.16.23.0/24", host.address)
}

Code reuse is a best common practice when it comes to writing software. This also applies to Icinga 2 and makes your config much more maintainable and pleasant to work with.
Here’s how you can re-use your filter expression in multiple apply rules:

globals.is_prod_database_host = function(host) {
  // All db hosts except those in the dev subnet
  return match("db*.example.org", host.name) && !cidr_match("172.16.23.0/24", host.address)
}
apply Service "mysql" {
  ...
  assign where is_prod_database_host(host)
}
apply Service "postgresql" {
  ...
  assign where is_prod_database_host(host)
}
apply Service "mssql" {
  ...
  assign where is_prod_database_host(host)
}

By using descriptive function names you also gain the advantage of making your code… er, config more readable.

Mittagsbestellungen bei NETWAYS

Mittagsbestellungen in einem größeren Büro zu organisieren, ist gar nicht so einfach. Die Kollegen müssen gefragt werden, was sie denn gerne bestellen wollen und irgendjemand muss das Geld jeweils passend einsammeln (“Ich hab’ aber nur einen 50 Euro-Schein!”).
Sobald das Essen dann da ist, müssen die Kollegen benachrichtigt werden, die inzwischen vielleicht in einem Meeting sitzen und gar nicht mehr daran denken, dass sie vor einer halben Stunde eine Pizza bestellt haben.
Um diesen Prozess zu vereinfachen, haben wir uns einige Automatismen ausgedacht, die uns sowohl Zeit sparen als auch den Bestellvorgang komfortabler gestalten.
Zunächst einmal habe ich hierfür eine Webseite entwickelt, über die Bestellungen entgegengenommen werden können:
order-form
Unsere Mitarbeiter bekommen dazu täglich um 10:15 Uhr eine E-Mail, in der die heutigen Angebote stehen (z.B. Pizza oder Döner). Auf der Bestellseite gibt es auch für den jeweiligen Laden die aktuelle Speisekarte, in der einfach die gewünschten Gerichte inkl. derer Optionen (groß, klein, mit extra Käse, usw.) ausgewählt werden können. Alternativ kann auch über einen Jabber-Bot bestellt werden.
Händler können über die Webseite auch Trinkgeld für den jeweiligen Laden einsammeln, das dann gerecht auf alle Bestellungen aufgeteilt wird. Auch sind Rabattaktionen möglich (z.B. 30% auf alles).
Der Bestellschluss ist um 11:15 Uhr. Danach können sich unsere Händler die Liste der Bestellungen über die Webseite als PDF herunterladen und entsprechend bestellen. Sobald das Essen im Büro angekommen ist, ändern die Händler den Bestellstatus über die Webseite, wodurch auch gleichzeitig Jabber-Benachrichtigungen an alle Kollegen verschickt werden, die am jeweiligen Tag mitbestellt haben.
In Zukunft wird dieser Schritt dann über einen Taster erledigt, der neben der Eingangstür angebracht ist. Dabei gibt es für die Kollegen, von denen die meisten Bestellungen ausgeführt werden, jeweils einen Taster:
fhem-buttons
Bleibt eigentlich nur noch die Frage, wie die Händler an das Geld kommen, um die Bestellungen bezahlen zu können. Anstatt täglich Kleinstbeträge für Döner (3€) und ähnliches einzusammeln, erhält jeder Mitarbeiter ein Konto, über das die Bestellungen abgerechnet werden:
bank
Dies ermöglicht uns auch, Bargeld an einer zentralen Stelle einzusammeln. Hierfür haben wir eine Geldkasette, in der wir jeweils eine ausreichende Summe Bargeld vorhalten, um für die nächsten 1-2 Wochen Bestellungen ausführen zu können.
Einzahlungen sind allerdings auch über SEPA-Überweisungen möglich. Hierzu fragt ein Cronjob stündlich ein externes Bankkonto per HBCI ab und schreibt es dem jeweiligen Mitarbeiter auf seinem Essenskonto gut.
Überweisungen zwischen Mitarbeitern sind auch möglich (inkl. SMS-TAN zur Sicherheit) und wir räumen jedem Kollegen einen zinsfreien Dispokredit von 20€ ein.
Der Sourcecode für die beiden Anwendungen ist auf GitHub in den beiden Repositories https://github.com/gunnarbeutner/shop-app und https://github.com/gunnarbeutner/bank-app. Aktuell fehlt leider jegliche Dokumentation (ups!) und der Code ist an einigen Stellen nicht wirklich schön.