Ansible - erweitertes Konfigurationsbeispiel 7: Ansible Vault
Im Eingangskapitel Grundlagen haben wir uns mit der Installation bereits befasst. Mit den Hintergrundinformationen haben wir uns auch schon in den beiden Kapiteln Playbooks und YAML - was ist das? eingehend beschäftigt, sowie erste Erfahrungen mit Playbooks gesammelt.
Beim ersten Playbook-Beispiel Benutzer anlegen ist uns bereits ein wesentlicher Umstand ins Auge gestossen. Das Ablegen von Passwörtern in einem Playbook ist alles andere als sicher:
Doch Achtung: Es zeigt sehr anschaulich, dass es keine gute Idee sein kann, Passworte und ähnliches direkt in einem Playbook und/oder Inventory unverschlüsselt vor zuhalten - kann doch so jeder, der Zugriff auf das Playbook/Inventory hat, unberechtigter Weise Kenntnis von vertraulichen Informationen erlangen!
Das Passwort M31nP4p4157d3r4113r83573!
des Nutzers ruben
ist in diesem Beispiel für jedermann lesbar in dem Playbook gespeichert. Das ist natürlich alles andere als sicher! Jeder oder jede, die auf diese Datei lesend zugreifen kann, kennt nun das Passwort dieses Users. Was also tun? Nun, im Grunde verfahren wir wie sonst auch:
- Sensible Informationen werden verschlüsselt (krypted) und niemals im Klartext vorgehalten!
- Benötigt man Zugriff auf den Inhalt der verschlüsselten Informationen, müssen wir diese temporär entschlüsselt werden (dekrypt). Hierzu müssen wir in Besitz eines entsprechenden Schlüssels und ggf. dessen Sicherungspassphrase sein! Optional wäre auch noch denkbar über einen Access-Token bei einem Agenten, das betreffende Passwort zu erfragen.
- Wir wollen möglichst wenig Aussenanbindungen, wenn es um die Verwaltung und den Zugriff auf vertrauliche Informationen geht. Zum einen können diese ausfallen und unsere Ansible-Umgebung wäre inoperabel und zum anderen trauen wir nur möglichst unserem eigenen System(en)!
- Wir sind uns dabei einig und sicher, dass im RAM des Rechners bzw. über einen Agent, dass Passwort zur Laufzeit vorgehalten und ggf. dort unberechtigter Weise ausgelesen werden könnte - kurzum eine 100% sichere Lösung gibt es nicht, nicht einmal wenn sich ein entsprechendes Passwort ausschliesslich im Gehirn des Admin befände.
- Bei einem Security-Audit wollen wir nicht sofort durch Auswahl, Nutzung und Handling von unsicheren Lösungen auffallen.
Wir benötigen also eine Lösung, die sowohl als ausreichend sicher Bestand hat und auch eine entsprechende Akzeptanz bei der Nutzung gewährleistet. Hier greifen wir nun auf Ansible-Vault aus dem Paket ansible
zurück.
Dokumentation - Beschreibung
Was das Python3-Script ansible-vault
nun alles kann und leistet, entnehmen wir einfach den Hilfe-Optionen des Scripts bzw. der zugehörigen Manpage.
Hilfeseite des Scripts
Rufen wir das Script ansible-vault
mit der Option -h
bzw –help
auf, erhalten wir eine entsprechende Kurzbeschreibung.
$ ansible-vault --help
Ausgabe des Befehls nsible-vault --help
Wollen wir eine Kurz-Hilfe z.B. zur Option encrypt
, fragen wir entsprechend nach dessen beschreibende Option bzw. Kurz-Hilfe.
$ ansible-vault encrypt --help
Manpage
Werfen wir nun also auch noch einen Blick in die Manpage von ansible-vault
.
$ man ansible-vault
ansible-vault - Praxis-Beispiele
Nehmen wir in nachfolgendem Beispiel an, dass Passwort Früh übt sich, wer ein Meister werden will!
des Admin-Users christoph
legen wir im Inventory ab:
$ echo "admin_password: Frueh_uebt_51ch_wer_31n_Meister_werden_will!" > ~/ansible/inventory/produktion/group_vars/all/secrets.yml
Wir haben also eine Datei, mit folgendem Inhalt, die jeder (aus-)lesen kann der Zugriff auf unseren Rechner hat:
$ cat ~/ansible/inventory/produktion/group_vars/all/secrets
admin_password: Frueh_uebt_51ich_wer_31n_Meister_werden_will!
Inhalte/Datei Verschlüsseln
Wir wollen also diese Datei mit Hilfe von ansible-vault
verschlüsseln, dazu rufen wir folgenden Befehl auf:
$ ansible-vault encrypt ~/ansible/inventory/produktion/group_vars/all/secrets.yml
Wir werden nun nach einem hinreichend sicheren Passwort 2x gefragt - hier geben wir also Schleichi, der aufstrebende Stern am Ansible-Himmel!
ein.
New Vault password: Schleichi, der aufstrebende Stern am Ansible-Himmel! Confirm New Vault password: Schleichi, der aufstrebende Stern am Ansible-Himmel! Encryption successful
Unsere Datei mit dem Passwort ist nun verschlüsselt, versuchen wir nun das Passwort „auszulesen“ erhalten wir nur einen entsprechenden „Zahlensalat“.
$ less ~/ansible/inventory/produktion/group_vars/all/secrets
$ANSIBLE_VAULT;1.1;AES256 39303364346439623430643364306438353034663962646364376362626665373862623335323361 3531626233656330646563656262383638336666633363340a356361353938613534623539353937 66366633323936333731653234386363336336376261373632613063663536663931356333303331 3164363837383636650a323630666265363262346662623231636536306532353963323332373932 65376637363362346161376665313231383562643164616332363636363630626264373665313837 32373965393266323231313033613732636438623538616439616364643332366535653230386263 316365393035626461383535613761343365
Inhalte anzeigen
Wie wir gerade gesehen haben, kommen wir nun nicht mehr so ohne weiteres an die verborgene Information. Wollen wir den Inhalt einsehen, benutzen wir die Option view
beim Aufruf von ansible-vault
.
$ ansible-vault view ~/ansible/inventory/produktion/group_vars/all/secrets.yml
Wir werden nun aufgefordert unser Vault-Passphrase/-Passwort einzugeben, damit für die Anzeige der Datei diese temporär entschlüsselt werden kann. Wir geben also hier Schleichi, der aufstrebende Stern am Ansible-Himmel!
ein.
Vault password: Schleichi, der aufstrebende Stern am Ansible-Himmel!
Als Ergebnis erhalten wir:
admin_password: Frueh_uebt_51ch_wer_31n_Meister_werden_will!
Die Datei selbst ist immer noch verschlüsselt:
$ less ~/ansible/inventory/produktion/group_vars/all/secrets.yml
$ANSIBLE_VAULT;1.1;AES256 39303364346439623430643364306438353034663962646364376362626665373862623335323361 3531626233656330646563656262383638336666633363340a356361353938613534623539353937 66366633323936333731653234386363336336376261373632613063663536663931356333303331 3164363837383636650a323630666265363262346662623231636536306532353963323332373932 65376637363362346161376665313231383562643164616332363636363630626264373665313837 32373965393266323231313033613732636438623538616439616364643332366535653230386263 316365393035626461383535613761343365
Inhalte editieren
Möchten wir eine Anpassung am Inhalt der Datei vornehmen, nutzen wir einfach die Option edit
.
$ ansible-vault view ~/ansible/inventory/produktion/group_vars/all/secrets.yml
Wir werden auch hier nun aufgefordert unser Vault-Passphrase/-Passwort einzugeben, damit die Datei entschlüsselt und im vim
zum editieren angeboten werden kann. Wir geben also hier wiederum unsere Passphrase Schleichi, der aufstrebende Stern am Ansible-Himmel!
ein.
Vault password: Schleichi, der aufstrebende Stern am Ansible-Himmel!
Wir fügen einfach mal eine weitere Zeile am Anfang der Datei an und definieren dort den Admin-User:
admin_user: christoph admin_password: Frueh_uebt_51ch_wer_31n_Meister_werden_will!
Anschliessend verlassen wir den Editor und speichern unsere Änderungen mit dem altbekannten :x!
. Die Datei liegt nun wieder verschlüsselt mit den geänderten Inhalten vor.
$ less ~/ansible/inventory/produktion/group_vars/all/secrets
$ANSIBLE_VAULT;1.1;AES256 62376535393830663233323630313962613831356261333336326439613962346132383439363833 6639653032633564373531376263306165306664653939300a313333323632623037373834663033 62363364393231613964363730323065313166306431633338393365333732373637316332643139 3662346632613430310a393437313062393031623435376630643735363364363361316137666261 31643461386563383465663766386464303465653761663738313562663361636237613038313662 31663061643835653339616433323939313130613862323739336261656637336366663636323035 39656238616232386530653161343632626637373238613530666330613139313037633534643132 65373030386236613130383939346361346165343034386532363363656230343935623064653434 3963
Mit view
können wir uns vergewissern, ob die neuen Inhalte auch wirklich vorliegen.
$ ansible-vault view ~/ansible/inventory/produktion/group_vars/all/secrets.yml
Vault password: Frueh_uebt_51ch_wer_31n_Meister_werden_will!
admin_user: christoph admin_password: Frueh_uebt_51ch_wer_31n_Meister_werden_wil
Inhalte/Datei entschlüsseln
Wollen wir die Verschlüsselung unserer Datei wieder entfernen, entschlüsseln wir diese mit der Option decrypt
.
$ ansible-vault decrypt ~/ansible/inventory/produktion/group_vars/all/secrets.yml
Auch hier geben wir unsere Passphrase ein, damit die Datei entschlüsselt werden kann.
Vault password: Decryption successful
Die Datei liegt nun wieder entschlüsselt in plaintext vor.
$ cat ~/ansible/inventory/produktion/group_vars/all/secrets.yml
admin_user: christoph admin_password: Frueh_uebt_51ch_wer_31n_Meister_werden_will!
weitere Optionen und Hinweise
Die weiteren Optionen, wie z.B. create
oder rekey
sind soweit selbsterklärend und werden hier in diesem Konfigurationsbeispiel nicht noch extra ausführlich beschrieben.
Bei der Verschlüsselung von Inhalten sind wir keinesfalls auf Dateien und Variabeln beschränkt. Wir könnten bei Bedarf auch jedwede Projeketdateien, wie Playbooks, Rollen, Templates oder auch ganze Inventories verschlüsseln!
ansible-vault in Verbindung mit ansible-playbook
ask-vault-pass
Beim Aufruf eines Ansible-Playbooks liest ansible-playbook
alle benötigten Dateien ein. Zum Abarbeiten benötigt Ansible natürlich die temporär entschlüsselten Informationen. Damit Ansible nun die verschlüsselten Informationen herankommt, benötigt Ansible natürlich vorübergehend das Vault-Passwort/-Passphrase. Hier kommt die Option --ask-vault-pass
ins Spiel.
Der Aufruf des Scripts 01_create-user.ym
aus Beispiel 1 würde dann lauten:
$ ansible-playbook -v 01_create-user.yml --limit=demo --ask-vault-pass
Nach der Abfrage des BECOME password:
wird dann nach dem Vault-Passwort gefragt Vault password:
.
Aus dem Blickwinkel Sicherheit haben wir nun zum einen erreicht, dass schützenswerte Informationen nicht mehr als plain-text in unserer Ansible-Entwicklungsumgebnung ungeschützt herumliegen. Darüber hinaus haben wir nun quasi einen zweiten Faktor bei der Abarbeitung unserer Ansible-Playbooks eingeführt - genauer gesagt sind es ja eher drei Dinge, über die der Admin verfügen muss:
- Der Admin muss den SSH-Privat-Key besitzen und von dessen Passphrase Kenntnis haben.
- Der Admin muss das
BECOME password:
kennen, mit dessen Hilfe die Rechteerweiterung, gemäss unserer initialen Konfiguration zur Rechteerweiterung mit Passwort auf den Zielsystemen erlangt werden kann. - Der Administrator muss nun auch noch
Vault password:
eingeben, damit die verschlüsselten Inhalte, die im Inventory abgelegt sind, entschlüsselt werden können und das bzw. die Playbooks auch ordnungsgemäss und vollständig abgearbeitet werden können.
Aus Sicht von IT-Security doch schon mal ein erheblicher Mehrwert, der natürlich zugegebener Maßen mit einem Komfortverlust erkauft wird!
vault-password-file
Ja, es gäbe auch die Option --vault-password-file
, aber diese Option streichen wir gleich mal aus unserem Gedächtnis, da es erwiesener Maßen keine gute Idee sein kann, das zum Entschlüsseln von vertraulichen Informationen benötigte Passwort, in Dateisystem wieder für alle lesbar abzulegen!
Nein, so 'was machen wir hier definitiv nicht! Never ever! Ein absolutes no go!
ansible-vault mit Passwortmanager pass
Will oder muss man ansible-playbook
öfters und mehrmals ausführen, ist es doch zuweilen mehr als mühsam, bei jedem Aufruf neben dem become (früher auch bekannt als sudo) bei Verwendung von ansible-vault
nunmehr zusätzlich das ansible-vault-Passwort einzugeben.
Wie im vorangegangenen Abschnitt bereits angeschnitten, verwerfen wir die Option „Übergabe der Passworte auf der Kommandozeile“ bzw. „Vorhalten von Passworten in (Konfig-)Files“ sofort wieder.
Vorüberlegungen
Was wir nun brauchen ist zum einen eine Möglichkeit das Vault-Passwort sicher zu speichern bzw. vor zuhalten und zum anderen bei Bedarf eine Möglichkeit das Vault-Passwort irgendwie zu „cachen“, so dass man Ansible schnell ausführen kann, ohne die Anmeldedaten für kleine Änderungen im Playbook erneut eingeben zu müssen.
Sowohl die Option --extra-vars=„ansible_become_pass=Frueh_uebt_51ch_wer_31n_Meister_werden_will!“
wie auch --vault-password-file
haben entscheidende Nachteile, wären doch die Passworte in der History-Datei der Shell verstreut, in der Prozessliste ps aux
sichtbar oder gar in den betreffenden plaintext Dateien im Dateisystem auffindbar. Alles in allem nachvollziehbar: definitiv eine sehr schlechte und unsichere Lösung!
Die Vault-Funktion von Ansible bietet zwar eine Option, das Passwort aus einer Datei bzw. aus der zugehörigen Konfigurationsvariable zu holen. Aber wie wir bereits wissen: Plaintext-Passworte im Dateisystem, eine furchtbar schlechte und definitiv keine sichere Lösung!
Aber: Die Option vault-password-file
in der Ansible-Konfigurationsdatei ~/.ansible.cfg
kann auch ein (Wrapper-)Script sein. Wir brauchen also nun zwei Dinge bzw. gehen in zwei Schritte vor:
- Ein Wrapper-Skript, um das Passwort vom Benutzer abzufragen um es ggf. für kurze Zeit für weitere
ansible-playbook
-Läufe zwischenzuspeichern. - Ein Tool, das das Vault-Passwort von Ansible auf stdin zurückgibt. Glücklicherweise bietet der Passwort-Manager pass genau diese Funktion.
pass
ist ein Passwort-Manager, der die Passwörter in einer Verzeichnisstruktur organisiert und sie (in Klartextdateien) mit GPG verschlüsselt und über ein CLI1) verfügt..
Der Zugriff nach dem benötigten Passwort könnte nun so ablaufen: Als erstes hinterlegen wir in dem ausführbaren Wrapper-Script pass show ansible-vault-password
. Dadurch frägt GPG nach dem Passwort, entschlüsselt die Passwortdatei und gibt das entschlüsselte Passwort auf stdout
aus. Je nach dem wie lange der GPG-Agent den gecachten persönlichen privaten Schlüssel aus dem Speicher entfernt hat, geben nachfolgende Aufrufe von pass show ansible-vault-password
das Passwort aus, ohne dass das Passwort des privaten PGP-Schlüssels erneut abgefragt wird.
Passwortmanager pass
Als erstes befassen wir uns mit dem Standard UNIX Passwort-Manager pass. Der Passwort-Manager pass
haben wir ein einfach zu bedienendes wie auch strukturiertes Tool. Bei pass
wird jedes Passwort in einer PGP-verschlüsselten Datei abgelegt, deren Dateiname der Titel der Website oder Ressource ist, für die das Passwort benötigt wird. Diese verschlüsselten Dateien können in sinnvollen Ordnerhierarchien organisiert, bei Bedarf von Host zu Host kopiert und im Allgemeinen mit Standard-Kommandozeilen-Dienstprogrammen für die Dateiverwaltung bearbeitet werden. Ferner kann der Passwortmanager einfach über sein CLI angesprochen und bedient werden.
Bei der Nutzung von pass
gehen wir davon aus, dass man bereits über einen eigenen PGP-Key verfügt und mit dessen Verwendung vertraut ist. Falls nicht, wird in diesem Kapitel die Erstellung und Verwendung ausführlich beschrieben. Besonders sicherheitsbewussten Administratoren ist auch die Verwendung einer Kryptographie-Hardware z.B. eines Nitrokey Start empfohlen. Die Erstellung von passenden Schlüsselmaterial wie ECDSA-basierten SSH-Schlüssel und PGP-Schlüssel ist z.B. in diesem Kapitel in Djangos WIKI ausführlich beschrieben und erklärt.
Bevor wir uns nun eingehender mit pass
beschäftigen installieren wir das Programm-Paket mit Hilfe des Paketverwaltungs-Tools unserer Distribution.
- Arch :
$ pacman -S pass
- Fedora / RHEL :
# yum install pass
- Gentoo :
# emerge -av pass
- openSUSE :
$ sudo zypper in password-store
- Ubuntu / Debian :
$ sudo apt-get install pass
Was das Programm pass
alles an Befehlsoptionen mitbringt, offenbart uns die der Programmaufruf mit der Option help
.
$ pass --help
Ausgabe des Befehls pass --help
Zunächst müssen wir einmalig den Passwort-Safe initialisieren. Wichtig ist dabei, dass wir hier (der dritte Wert beim Aufruf) genau den Namen angeben, den wir bei der Generierung des PGP-Schlüssels verwendet hatten. Im folgenden Konfigurationsbeispiel gehen wir davon aus, dass hier die eMail-Adresse christoph@mailserver.guru
unseres Admins christoph verwendet wird.
$ pass init christoph@mailserver.guru
Anschliessend hinterlegen wir das Vault-Passwort Schleichi, der aufstrebende Stern am Ansible-Himmel!
mit welchem wir unsere zu schützende Datei ~/ansible/inventory/produktion/group_vars/all/secrets
verschlüsselt hatten.
$ pass insert ansible-vault-password
Enter password for ansible-vault-password Schleichi, der aufstrebende Stern am Ansible-Himmel!
Im Homeverzeichnis unseres Admins findet sich nun das zugehörige verschlüsselte Dokument.
/home/christoph/.password-store/ └── ansible-vault-password.gpg
Dies zeigt uns auch die Abfrage von pass
.
$ pass
Password Store └── ansible-vault-password
Den Inhalt des Passwort-Store können wir mit Hilfe des folgenden Befehls anzeigen lassen.
$ pass ansible-vault-password
Schleichi, der aufstrebende Stern am Ansible-Himmel!
Den Inhalt des Passwort-Stores können wir auch in die Zwischenablage kopieren um dessen Inhalt dann an geeigneter stelle einzufügen.
$ pass -c ansible-vault-password
Copied ansible-vault-password to clipboard. Will clear in 45 seconds.
WrapperScript
Der zweite der Aufgabenstellung ist schnell und einfach umgesetzt. Wir legen uns das Wrapper-Script im ~/bin
-Verzeichnis unseres Admin-Account an.
Sollte das betreffende Verzeichnis noch nicht existieren, legen wir es erst einmal an.
$ mkdir ~/bin/
Nun legen wir das benötigte Wrapper-Script an.
$ vim ~/bin/ansible_vault_password
- ~/bin/ansible_vault_password
#!/bin/bash /usr/bin/pass show ansible-vault-password
Abschliessend statten wir das Script mit x
-Rechten aus.
$ chmod +x ~/bin/ansible_vault_password
Ansible-Konfiguration
Was nun noch fehlt ist die Konfiguration von Ansible. Dazu setzen wir in der Sektion [defaults]
die Option vault_password_file
entsprechend.
$ vim ~/.ansible.cfg
- ~/.ansible.cfg
... # If set, configures the path to the Vault password file as an alternative to # specifying --vault-password-file on the command line. # Django : 2022-08-09 # default: #vault_password_file = /path/to/vault_password_file vault_password_file = ~/bin/ansible_vault_password ...
Ansible-Playbook
Dank unserer Konfiguration wird ab sofort beim Aufruf von ansible
, ansible-playbook
oder auch ansible-lint
, dass Passwort unseres PGP-Schlüssels abgefragt, damit das wiederum mit dem PGP-Schlüssel verschlüsselte Vault-Passwort entschlüsselt und benutzt werden kann.
Verwenden wir ein Security-Hardware-Geräte wie z.B. einen Nitrokey Start werden wir aufgefordert, den USB-Stick anzustecken uns die zugehörige PIN einzugeben.
Wie bereits im Abschnitt ask-vault-pass im Kapitel ansible-vault in Verbindung mit ansible-playbook aufgezeigt haben wir nun eine, mit der Security-Brille betrachtete, optimale Lösung gefunden, die natürlich zugegebener Maßen nicht gerade bequem und komfortabel anmuten kann.
Wir werden uns hierzu gleich noch eine Konfiguration ansehen, die in gewisser Art und Weise ähnliche Sicherheit beim doch mehr Bequemlichkeit für den Admin mit sich bringen kann, doch hierzu mehr in nachfolgendem Abschnitt.
become_pass und vault-password aus einem Ansible-Vault
Beispiel mit zwei Passwortabfragen
Bei der Grundkonfiguration zur Rechteerweiterung unserer Ansible-Umgebung, hatten wir in der ansible.cfg
in der Sektion [privilege_escalation] unter anderem folgendes definiert.
$ vim ~/.ansible.cfg
- ansible.cfg
... [privilege_escalation] # Django : 2020-01-04 # default: unset #become=True #become_method=sudo #become_user=root #become_ask_pass=False become=True become_method=sudo become_user=root become_ask_pass=True ...
Das hat zur Folge, dass wir nach dem Aufruf eines Ansible Playbooks stets nach dem become_password gefragt werden. In Abschnitt Ansible Konfiguration in diesem WIKI-Artikel hatten wir das vault_password_file
mit unserem Wrapper-Script verknüpft.
$ vim ~/.ansible.cfg
- ansible.cfg
... # If set, configures the path to the Vault password file as an alternative to # specifying --vault-password-file on the command line. # Django : 2022-08-09 # default: #vault_password_file = /path/to/vault_password_file vault_password_file = ~/bin/ansible_vault_password ...
Dank dieser beiden Definitionen haben wir nun erreicht, dass beim Starten eines Ansible-Playbooks nach der Abfrage des BECOME password:
zusätzlich noch das Vault password:
abgefragt wird. Natürlich müssen wir den SSH-Key auch noch geladen haben und dessen Passphrase eingegeben haben!
Zur Abarbeitung eines Ansible-Playbooks muss der Admin über drei Dinge verfügen:
- Er muss den SSH-Privat-Key besitzen, diesen laden und die zugehörige Passphrase eingeben.
- Der Admin muss ferner das
BECOME password:
beim Starten eines Playbooks eingeben, damit er Root-Rechte auf den Zielsystemen erlangen kann. - Zusätzlich muss er auch noch das
Vault password:
eingeben, damit die verschlüsselten Inhalte, die im Inventory abgelegt sind, entschlüsselt werden können und das bzw. die Playbooks auch ordnungsgemäss und vollständig abgearbeitet werden können.
Aus Sicht der IT-Sicherheit ein anpeilbares Zielszenario, welches zugegebener Maßen dem Admin einiges an manuellen Tätigkeiten abverlangt.
Beispiel mit nur einer Passwortabfrage
Jede Lösung und Anwendung in der IT-Welt steht und fällt mit der Akzeptanz der Anwender. In unserem speziellen Fall ist das der Admin und für ihn kann es mitunter helfen, wenn man bei der Lösungsfindung eine akzeptable Mischung aus Sicherheit und Bequemlichkeit der Lösung finden kann. Und genau solch ein Beispiel wollen wir uns nun noch abschliessend genauer ansehen. Was werden wir nun machen? Nun, wir verlagern die Information zum become_passord
weg von einer interaktiven Abfrage beim Starten eines Playbooks hin zur Datenvorhaltung in einem ansible-vault!
Nein, wir werden nicht den Admin-Aser in eine Gruppe sudo
oder wheels
packen und auf den Zielsystemen in der sudoers
auf die Abfrage des Passwortes verzichten! NOPASSWD: ALL
ist keine erstrebenswerte Idee! Übrigens genau so wenig wie das Vorhaben allen Admins einen direkten root-Access auf Zielsystemen zu geben. Aus Sicherheitsaspekten quasi der Super-GAU schlechthin - wenn auch in gewissen Kreisen seit Jahren Usus, aber das ist ein anders Thema …
Wir werden nun als erstes die Konfiguration in der ansible.cfg
, die wir bei der Ansible-Ersteinrichtung ggf vorgenommen hatten wieder entfernen.
$ vim ~/.ansible.cfg
- ansible.cfg
... [privilege_escalation] #become=True #become_method=sudo #become_user=root #become_ask_pass=False ...
Die Konfiguration des become-Optionen verlagern wir nun in unser Inventory. Hierzu legen wir im Inventory ein Variablen-Verzeichnis für alle Hosts an.
$ mkdir ~/ansible/inventories/production/group_vars/all/
Dort hinterlegen wir zunächst die Optionen, die wir früher in der ansible.cfg
vermerkt hatten.
$ vim ~/ansible/inventories/production/group_vars/all/ansible_environment.yml
- ansible_environment.yml
ansible_become: True ansible_become_method: sudo ansible_become_user: root ansible_become_ask_pass: False
Unser become_password
legen wir dann in einer zweiten Datei im Inventory ab.
$ vim ~/ansible/inventories/production/group_vars/all/vault.yml
- vault.yml
ansible_become_pass: Frueh_uebt_51ch_wer_31n_Meister_werden_will!
Anschliessend verschlüsseln wir diese Datei mit dem Vault-Passwort, welches wir ja mit Hilfe von pass
mit unserem PGP-Key verschlüsselt vorhalten.
$ ansible-vault encrypt inventories/production/group_vars/all/vault.yml
Tests
Für einen ersten Test bemühen wir das Ansible adhoc Aufruf und Ermitteln mit Hilfe des shell
-Moduls wie viele Dateien und Verzeichnisse sich im $HOME
-Verzeichnis des Benutzers root
befinden. Der Test zeigt uns unmittelbar, ob der Zugriff auf die vault.yml
-Datei klappt in dem sich das become_pasword
befindet.
- Aufruf ohne PGP Schlüssel
Im ersten Beispiel wollen wir nun die Anzahl der Verzeichnisse und Dateien im$HOME
Verzeichnis des Benutzersroot
erfragen. Hierzu sind natürlich Root-Rechte von nöten, die unser Admin-Account natürlich per se nicht hat.
$ ansible localhost -m shell -a "ls -l /root | wc -l"
gpg: decryption failed: No secret key [WARNING]: Error in vault password file loading (default): Vault password script /home/django/bin/ansible_vault_password returned non-zero (2): None ERROR! Vault password script /home/django/bin/ansible_vault_password returned non-zero (2): None
Der Versuch scheitert natürlich, da wir ohne den PGP-Schlüssel nicht an die per Ansible-Vault verschlüsselte Info zuansible_become_pass
kommen! - Aufruf mit PGP Schlüssel
Im zweiten Beispiel werden wir nun erneut versuchen Anzahl der Verzeichnisse und Dateien im$HOME
Verzeichnis des Benutzersroot
zu erfragen. Nur dieses mal werden wir unseren PGP-Schüssel laden und die zugehörige Passphrase richtig eingeben.
$ ansible localhost -m shell -a "ls -l /root | wc -l"
localhost | CHANGED | rc=0 >> 2
Die Abfrage liefert hier natürlich nun das gewünschte Ergebnis, da die Info zuansible_become_pass
aus dem Ansible-Vault erfolgreich mit Hilfe des PGP-Schlüssels temporär entschlüsselt werden konnte.
Beim Aufruf eines Ansible-Playbooks liest das Programm ansible-playbook
alle benötigten Dateien ein inklusive aller Hostdefinitionen aus dem Inventory ein, auch wenn diese gerade nicht zum Abarbeiten des Playbooks benötigt werden. Zum Abarbeiten benötigt Ansible natürlich die temporär entschlüsselten Informationen. Damit Ansible nun die verschlüsselten Informationen herankommt, benötigt Ansible natürlich vorübergehend das Vault-Passwort/-Passphrase, welches sich nun selbst verschlüsselt in einem Ansible-Vault befindet. Durch den Passwortmanager pass
und unserem PGP-Schlüssel kommen wir nun direkt zu dem Ansible Vault Passwort. Wir brauchen also nur einmal das für den PGP zugehörige Passwort oder im Falle der Verwendung eines Security-Hardware-Devices wie eines Nitrokey Start.
Der Aufruf des Scripts 01_create-user.ym
aus Beispiel 1 würde dann lauten:
$ ansible-playbook -v 01_create-user.yml --limit=demo
Nach der Abfrage des PGP-Passwortes
bzw. der PIN bei Verwendung eines Nitrokey Start wird dann sofort das Playbook ausgeführt. Eine zusätzliche Eingabe eines become_password
ist nunmehr nicht mehr nötig.
Aus dem Blickwinkel Sicherheit haben wir nun zum einen erreicht, dass schützenswerte Informationen nicht mehr als plain-text in unserer Ansible-Entwicklungsumgebnung ungeschützt herumliegen. Darüber hinaus haben wir nun quasi einen zweiten Faktor bei der Abarbeitung unserer Ansible-Playbooks eingeführt - genauer gesagt sind es ja eher drei Dinge, über die der Admin verfügen muss:
- Der Admin muss den SSH-Privat-Key besitzen und von dessen Passphrase Kenntnis haben. Wird ein Nitrokey Start USB-Schlüssel verwendet, kann bei Bedarf auch der SSH-Key bei Verwendung der SSH benutzt werden. Die Zusätzliche Eingabe einer Passphrase erübrigt sich dadurch auch hier, wenn der SSH-Key auf dem Kryptostick verwendet wird!
- Der Administrator muss beim Aufruf der Playbooks nunmehr nur noch den PGP-Schlüssel durch Eingabe der zugehörigen Passphrase entsperren. Das
become_password
Passwort für die Rechteerweiterung wird nun auch von Ansible aus dem Vault gelesen.
Aus Sicht von IT-Security haben wir auch hier einen erheblicher Zugewinn an Sicherheit. Die Akzeptanzschwelle ist durch Minimierung von mehrfachen Eingaben diverser Passworte durchaus niedrig, so dass für den Admin durchaus ein Mehrwert bei der täglichen administrativen Tätigkeit ausgemacht werden kann.
Fazit und Ausblick
Wir können nun mit Ansible-Vault vertrauliche Informationen in unseren Playbooks bzw. im Inventory ablegen. Diese werden als krypted AES256 Daten abgelegt und können dadurch auch jederzeit in einem verteiltem Versionskontrollsystem wie git vorgehalten werden. Durch Nutzung des Passwort-Manager pass
wird die Handhabung soweit vereinfacht, so dass der Admin auch ohne grosse Not mehrmals hintereinander Ansible-Playbooks ausführen kann, ohne sich durch zigfache Eingabe von Passworten sich selbst das Leben allzu schwer zu machen!
All die in diesem WIKI-Artikel aufgezeigten Konfigurationsschritte müssen wir aber nicht manuell nachvollziehen und auf jedem Administrations-Knoten/-Host via cut'n'paste nachtragen. Wir werden diese Punkte ganz einfach mit Hilfe von Ansible selbst ausrollen, wie genau das gemacht werden kann, werden wir uns im nächsten Kapitel Ansible mit Hilfe von Ansible einrichten/konfigurieren genauer ansehen.