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

Multienvironment Puppet

Im Puppet-Umfeld passiert immer noch relativ viel. Standards ändern sich und werden mit deprecated markiert. Daher hier eine Zusammenfassung für eine aktuelle Puppet-Umgebung.

Verzeichnisstruktur

Wer mit verschiedenen Umgebungen (production/testing) arbeitet und keinen external node classifier verwendet und node Definitionen lieber in klassisch in „node.pp“ Files ablegt, braucht eine Verzeichnisstruktur für die Unterscheidung der Umgebungen. Best Practice aktuell (Puppet v3.7.4) ist in der /etc/puppet/puppet.conf:

Die entsprechende Verzeichnisstruktur für die Ablage der Nodedefinitionen  sieht dann so aus:

 Hiera

Wer dem Design Pattern „Separation Of Data And Code“ folgt (und ich kann nur empfehlen es zu tun) fragt sich früher oder später wie er die ganzen Default Werte und Übergabeparameter an Puppet Klassen aus dem Code oder aus den Nodedefinitionen wieder herausbekommt. Im ersten Schritt wird man eine params.pp (Siehe https://docs.puppetlabs.com/guides/module_guides/bgtm.html) bauen und da zumindest die ganzen Defaultwerte einbauen. Aber so richtig los wird man das Ganze mit Hiera.
Hier werden alle Daten, ob Defaultwerte oder speziellere Daten, die z.B. pro Umgebung/Betriebssystem/Rechner/… unterschiedlich sind, in YAML Files abgelegt. Wie der Name „Hiera“ schon sagt ist der Clou an der Sache das hierarchische Element. So kann man Werte mehrfach definieren. Hiera geht dann, ähnlich wie bei Firewallregeln, von oben nach unten durch und nimmt den ersten Treffer. Die Konfiguration ist trivial:

Auf der Suche nach dem Wert einer Variable sucht Hiera in /etc/puppet/hieradata nach Files die auf den Rechnernamen, die Umgebung oder „common“ matchen und liest den Wert aus der ersten passenden Datei, welche die entsprechende Variable enthält. Im Puppet Code kann man Hiera auf zwei Arten nutzen.

1. Nutzung der Funktion hiera()

 2. Implizit über Übergabeparameter

Das ist mein Favorit. Ggf. benötigte Parameter werden als Übergabeparameter in der Puppetklasse definiert:

Diese werden dann automatisch ohne Angabe in der Nodedefinition in Hiera gesucht und genutzt, wenn vorhanden.

Beispiel

  • Rechnername: web01.domain.tld
  • Umgebung: production

Folgende Hieradateien sind abgelegt (hiera.yaml wie oben angegeben):

Somit wird eine Variable „$pwd“ der Klasse „web„, bzw. „hiera(‚web::pwd‘)“ zuerst in der „web01.domain.tld.yaml„, dann in der „production.yaml“ und falls sie noch nicht gefunden wurde in der „common.yaml“ gesucht. Die YAML Datei könnte wie folgt aussehen:

Vorteil ist, dass nun sehr einfach in jeder Umgebung ein anderes Passwort gesetzt sein könnte und das passende einfach so ohne irgendwelche If-Abfragen im Puppet genutzt wird.