Infrastructure as secure code

Im Rahmen meiner Abschlussarbeit habe ich mich damit beschäftigt den Code des Konfigurationsmanagementsystems Puppet automatisiert auf unsichere Praktiken zu analysieren. Herausgekommen ist ein puppet-lint Plugin zur Prüfung von Puppetcode aus mögliche Sicherheitsrisiken.

Das Plugin steht auf rubygems.org zur Verfügung. Der Quellcode ist auf Github verfügbar. Die eingebauten Sicherheitschecks sind als Basis zu verstehen und sollten auf die eigenen Bedürfnisse angepasst werden. Gerne können und sollten weitere Checks eingebaut werden.

Gem Version

Nun noch ein paar Hintergrundinfos.

Continue reading

post

Ruby on Rails | Massenverarbeitung mit ActiveRecord

Bei der produktiven Nutzung eines von mir entwickelten Tools hat es zugeschlagen: Es ist halt doch etwas anderes mit ein paar Testdatensätzen oder mit ein paar Hunderttausend Datensätzen zu arbeiten. Die Laufzeiten für INSERTs und UPDATEs gingen gar nicht. Also was tun? Das Projekt ist mit ActiveRecord realisiert.

Etwas Recherche hat gezeigt: Da geht einiges!

Abrufen von Datensätzen

Das Abrufen von Datensätzen via ActiveRecord kann über verschiedene Techniken beschleunigt werden. Erster Ansatzpunkt sind die Funktionen zum Abruf von Datensätzen in Bündeln (Batches). Hierzu bietet ActiveRecord bereits Funktionen an, so dass eine große Menge an Datensätzen nicht auf einmal, sondern stapelweise und somit schonend für Arbeitsspeicher und Swap Bereich verarbeitet werden kann (Retrieving Multiple Objects in Batches).

Generell sollte man die Menge an Datensätzen aus der Datenbank bereits bei der Abfrage weitestgehend reduzieren um im Programmcode möglichst nur noch mit den relevanten Datensätzen zu arbeiten. Es sollten also nicht die Ruby Methoden find bzw. find_all zum Filtern von Datensätzen genutzt werden, sondern besser bereits bei der Abfrage entsprechende Einschränkungen gemacht werden.

Also so eher nicht:

Besser:

Bei n:m Beziehungen sollte man mit der ‚through‘ Anweisung arbeiten um die Beziehungen zwischen Objekten darzustellen (Siehe http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association). ActiveRecord generiert dann SQL mit entsprechenden JOIN Anweisungen, anstatt über mehrere SELECTs die Anfragen zusammenzubauen.

UPDATEs auf vielen Datensätzen

Updates auf vielen Datensätzen ist ineffizient, wenn für jeden Datensatz ein eigenes UPDATE Statement generiert wird. Hier schafft update_all Abhilfe. Man selektiert vorab alle Datensätze die aktualisiert werden sollen und kann dann diese in einem Rutsch bearbeiten:

Somit wird ein UPDATE Statement für alle Datensätze erzeugt.

Massen-INSERT

Das massenhafte Anlegen neuer Datensätze frisst ebenso sehr viel Performance, da für jeden INSERT eine eigene Transaktion gestartet wird. Hier kann man manuell eingreifen und ActiveRecord beibringen alle INSERTs ein einer Transaktion zu verarbeiten: