Nicht nur im Kontext von DevOps ist "Configuration as Code" ein Schlagwort, das sich seit geraumer Zeit wachsender Beliebtheit erfreut. Die Idee von Configuration as Code ist es, die gewünschte Konfiguration eines IT-Systems, oder auch einer ganzen IT-Landschaft, in vergleichsweise einfachem Code auszudrücken. Mit einem zugehörigen Tool lässt sich dieser Code dann automatisiert auf die zu verwaltenden Systeme anwenden, die sich anschließend im gewünschten Zustand befinden. Man spricht auch davon, die Systeme zu "orchestrieren".
Für die Modellierung der Konfiguration in Code wird üblicherweise eine Sprache wie beispielsweise YAML genutzt, die einerseits maschinenlesbar sein muss, um automatisiert verarbeitet werden zu können, andererseits aber auch hinreichend gut menschenlesbar (und -schreibbar) ist, sodass die Administratoren stets den Überblick behalten können. Umfassende Programmierkenntnisse sind dazu nicht notwendig. Einzelne Schritte werden deklarativ niedergeschrieben, um eine Abfolge der notwendigen Tasks zu beschreiben – beispielsweise "Installiere das Softwarepaket X", "Kopiere die Config-Datei Y an den richtigen Ort" oder "Stelle sicher, dass der Dienst Z läuft". System- und softwarespezifische Konfigurationsdateien können dabei vom Configuration as Code-Werkzeug mithilfe von Variablen dynamisch angepasst werden, bevor sie auf das System kopiert werden. Auch einfache Konstrukte wie Fallunterscheidungen und Schleifen können verwendet werden, um Teile der Konfiguration programmatisch zu generieren.
Es gibt eine Reihe verschiedener Configuration as Code-Werkzeuge, von denen die meisten als freie Open-Source-Software verfügbar sind. Bekannt und verbreitet sind insbesondere Ansible, Salt, Puppet und Chef. Diese unterscheiden sich einerseits in den verwendeten Beschreibungs- und Templatesprachen, andererseits in der Funktionsweise der Benutzung. Manche Werkzeuge arbeiten mit einer Client-Server-Architektur, bei der sich die zu verwaltenden Systeme regelmäßig ihre Konfiguration bei einem zentralen Server abholen. Andere Werkzeuge werden bei Bedarf vom Administrator angestoßen und loggen sich dann automatisiert via SSH ein, um die Konfigurationsschritte durchzuführen. Zu letzteren Werkzeugen gehört Ansible, welches in diesem Artikel als Beispiel dienen soll, zu veranschaulichen, wie Configuration as Code auch für Sicherheitsaspekte interessant sein kann.
Hier ein erstes Beispiel für das Verwalten eines SSH-Servers via Ansible:
Der klassische Ansatz zur Administration von IT-Systemen basiert primär auf manueller Arbeit. Soll eine Aufgabe erledigt werden, meldet sich der Administrator interaktiv am System an und führt die erforderlichen Schritte durch. Gibt es nicht nur ein System, sondern gleich mehrere, etwa aus Gründen der Redundanz, wird dieses Vorgehen wiederholt, bis die Änderung auf allen Systemen durchgeführt wurde. Nach kurzer Zeit kann sich diese Arbeit monoton anfühlen und dem Fähigkeitslevel eines IT-Administrators nicht angemessen erscheinen. Wenn irgendwann sogar ein neues System dazukommt oder ein bestehendes neu aufgesetzt wird, beginnt die Arbeit von vorn, nur dass diesmal nicht nur die kürzlich vorgenommenen Änderungen eine Rolle spielen, sondern auch die gesamte Grundkonfiguration erneut eingerichtet werden muss. Sollte die Dokumentation nicht ganz auf dem neuesten Stand sein – wie es leider oftmals vorkommt –, kann dies frustrierend sein und es entstehen Zweifel, ob nicht doch ein relevanter Schritt vergessen wurde.
Bei all diesen Punkten unterstützt ein Configuration as Code-Ansatz enorm. Besteht eine Änderung beispielsweise darin, ein neues Softwarepaket zu installieren und einige Zeilen in der Konfigurationsdatei zu ändern, ist dies mit dem Hinzufügen eines neuen Tasks und der Änderung des Konfigurationstemplates schnell erledigt. Durch Anstoßen des Configuration as Code-Werkzeugs beginnt dieses mit der Arbeit, loggt sich auf jedem gewünschten System ein und führt die Änderung durch. Nach einigen Sekunden ist die Änderung auf jedem System vorhanden.
Wird ein neues System in Betrieb genommen, kann es auf Knopfdruck in den gewünschten Zustand gebracht werden, vorausgesetzt die Zielkonfiguration wurde zuvor vollständig modelliert. Dies kann auch modular erfolgen, sodass zunächst etwa eine Grundkonfiguration für einen Linux-Server angewendet wird, dann ein Webserver nach Vorgabe eingerichtet wird und schließlich eine konkrete Anwendung "deployt" wird.
Ein unschätzbarer Vorteil ergibt sich zudem aus dem Umstand, dass das Niederschreiben der notwendigen Schritte zur Einrichtung der Systeme in leicht lesbarer YAML-Syntax gleichzeitig als akkurate Dokumentation gewertet werden kann. Wer beispielsweise wissen will, welche Softwarepakete für eine bestimmte Systemgruppe installiert werden, kann dies dort leicht nachlesen.
Während die beschriebenen Vorteile ganz grundsätzlich beim Betrieb von IT-Infrastrukturen nützlich sind, ergeben sich auch positive Effekte für die IT-Sicherheit. Änderungen nicht jedes Mal erneut von Hand durchzuführen hilft dabei, Flüchtigkeitsfehler zu vermeiden oder keine Schritte zu vergessen, die im Zweifelsfall sicherheitsrelevant waren. Etwa, wenn es sich um eine Härtungsmaßnahme handelt oder ein Account mit Standardzugangsdaten deaktiviert werden soll.
Auch trägt die Verwaltung von Konfiguration in einem Configuration as Code-System dazu bei, eine gewisse Konsistenz zu schaffen. So kann vermieden werden, dass dieselbe Software auf verschiedenen Servern in unterschiedlichster Konfiguration und mit schwankenden Sicherheitseinstellungen existiert, über die kaum noch jemand den Überblick hat.
Wer schon einmal die eigene im Internet erreichbare Infrastruktur im Rahmen eines Pentests von der SySS GmbH hat untersuchen lassen hat, kennt vermutlich einige der typischen konfigurativen Schwachstellen: veraltete TLS-Protokollversionen und kryptografische Algorithmen, Letztere ebenfalls für SSH. Dabei handelt es sich um kleinere Probleme, die oftmals eine größere Zahl von Systemen betreffen. Auf jedem Server die entsprechenden Konfigurationsdateien anzupassen, kann dabei schnell der Mühe nicht Wert erscheinen. Mit Configuration as Code könnte die relevante Webserverkonfiguration einmal in den gewünschten Zustand gebracht und dann auf alle Webserver angewendet werden.
Eine solche Konfiguration mit Ansible zu verwalten, wird im Folgenden auszugsweise als Beispiel dargestellt.
YAML-Datei mit Tasks zur Installation und Konfiguration von nginx (weitere Konfigurationsdateien können und sollten ebenfalls ausgerollt werden):
Templatedatei "tls_settings.conf.j2" (sollte in den VHost-Konfigurationen der einzelnen Sites inkludiert werden, hier nicht dargestellt):
Die Templatedatei enthält dabei Jinja2-Syntaxelemente (insbesondere "if"), um eine Fallunterscheidung, basierend auf Variablen, zu treffen. Diese werden von Ansible ausgewertet; auf das Zielsystem gelangt nur eine der Varianten. So können verschiedene TLS Cipher Suites konfiguriert werden, je nachdem, ob die Variable "nginx_tls_ciphers" auf den Wert "modern" oder auf den Wert "compatibility" gesetzt ist. Auch die Unterstützung von OCSP Stapling bleibt optional, abhängig davon, wie die Variable "nginx_ocsp_stapling" gesetzt wird. In diesem vereinfachten Beispiel wurden die Variablen direkt im Task gesetzt, der die Datei auf das Zielsystem kopiert. In der Praxis würde man stattdessen sinnvolle Standardwerte wählen und diese bei Bedarf in systemspezifischen Variablendateien überschreiben.
Ein System oder sogar eine Systemlandschaft mit Configuration as Code zu modellieren, kann initial eine sehr große Menge Arbeit bedeuten. Insbesondere wenn das Vorgehen neu ist, muss zunächst auch das ein oder andere Tutorial durchgearbeitet werden.
Schließlich bietet es aber die bereits genannten Vorteile wie Konsistenz sowie die inhärente Existenz von Dokumentation.
Darüber hinaus lässt sich langfristig aber auch Zeit durch den sinnvollen Einsatz von Configuration as Code-Werkzeugen sparen. Sich wiederholende Arbeiten können leicht automatisiert werden, bis selbst die Installation eines neuen Systems kaum Mehraufwand bedeutet.
Interessant kann dies auch nach einem Security Incident sein, sobald das Thema Disaster Recovery aufkommt. In der Regel wird hier auf das Wiedereinspielen von Backups zurückgegriffen. Dies ist jedoch nicht immer möglich, etwa wenn Zweifel besteht, ob ein Angreifer nicht schon so lange im System war, dass das Backup ebenfalls betroffen ist. Manchmal fällt also doch die Wahl darauf, zumindest manche Systeme vollständig neu zu installieren. Existiert nun ein Configuration as Code-System, ist eine Neuinstallation schnell bewerkstelligt und das frische System kann automatisiert in den gewünschten Zustand gebracht werden.
16.09.2024
Secu4: IT-Recht und Datenschutz für IT-Verantwortliche
17.09.2024
- 18.09.2024
SySS auf der IKT in Wien
17.09.2024
- 18.09.2024
Hack6: Mobile Device Hacking
24.09.2024
- 26.09.2024
Hack9: Embedded Security
Ihr direkter Kontakt zu SySS +49 (0)7071 - 40 78 56-0 oder anfrage@syss.de | IN DRINGENDEN FÄLLEN AUSSERHALB DER GESCHÄFTSZEITEN +49 (0)7071 - 40 78 56-99
Als Rahmenvertragskunde wählen Sie bitte die bereitgestellte Rufbereitschaftsnummer
Ihr direkter Kontakt zu SySS +49 (0)7071 - 40 78 56-0 oder anfrage@syss.de
IN DRINGENDEN FÄLLEN AUSSERHALB DER GESCHÄFTSZEITEN +49 (0)7071 - 40 78 56-99
Als Rahmenvertragskunde wählen Sie bitte die bereitgestellte Rufbereitschaftsnummer
Direkter Kontakt
+49 (0)7071 - 40 78 56-0 oder anfrage@syss.de
IN DRINGENDEN FÄLLEN AUSSERHALB DER GESCHÄFTSZEITEN
+49 (0)7071 - 40 78 56-99
Als Rahmenvertragskunde wählen Sie bitte die bereitgestellte Rufbereitschaftsnummer