Endlich ist es passiert. Sie sind mit Ansible All-in gegangen. Sie haben all die großartigen Artikel gelesen, die Anwendungsfälle gesehen und freuen sich darauf, mit dem Aufbau einer wiederholbaren Infrastruktur zu beginnen und Ihre Konfiguration als Code zu verwalten. Es gibt nur ein Problem:Sie haben eine Konfigurationsdatei oder eine Aufgabe, die ein Passwort oder andere geschäftskritische Informationen erfordert. Sie wissen, dass Sie das Passwort nicht in Ihren Klartextdateien speichern sollten, also sind Sie sich nicht ganz sicher, wo es hingehört.
Keine Sorge, dieser Artikel führt Sie durch die verschiedenen Optionen für den Umgang mit vertraulichen Informationen in Ihren Playbooks. Egal, ob Sie nach einfachen Lösungen suchen, z. B. die Aufforderung an einen Administrator, ein Passwort einzugeben, oder nach komplexeren Optionen, z. B. die Integration in eine vorhandene Umgebung zur Verwaltung von Geheimnissen, Ansible hat alles für Sie.
[Das könnte Ihnen auch gefallen: Entmystifizierung von Ansible für Linux-Systemadministratoren]
Eingabeaufforderungen
Wenn Sie Ihre Ansible-Reise gerade erst beginnen und alle Ihre Playbooks manuell ausführen, ist die Verwendung einer interaktiven Eingabeaufforderung direkt in Ihrem Playbook eine einfache Lösung. Eine Eingabeaufforderung bewirkt, dass Ansible den Benutzer nach den gewünschten Variablen fragt und sie jedes Mal speichert, wenn ein Playbook ausgeführt wird. Betrachten Sie das folgende Playbook, das sicherstellt, dass ein API-Schlüssel in einer Konfigurationsdatei vorhanden ist:
---
- hosts: all
gather_facts: false
vars_prompt:
- name: api_key
prompt: Enter the API key
tasks:
- name: Ensure API key is present in config file
ansible.builtin.lineinfile:
path: /etc/app/configuration.ini
line: "API_KEY={{ api_key }}"
Wenn ich dieses Playbook ausführe, fordert Ansible mich an der Befehlszeile auf, indem ich die Nachricht im Eingabeaufforderungsparameter verwende:
# ansible-playbook -i inventory.ini main.yml
Enter the API key:
Die in der Befehlszeile bereitgestellte Eingabe wird im api_key gespeichert Variable, die dann im Spiel wie jede normale Variable verwendet werden kann.
Obwohl variable Eingabeaufforderungen einfach zu implementieren sind, werden Sie ihnen entwachsen, wenn Sie in die Verwendung von Ansible für die vollständige Konfigurationsverwaltung investieren. Wenn Ihr Konfigurationsmanagement ausgereift ist, werden Sie damit beginnen, Playbooks nicht interaktiv auszuführen, und es wird niemand vor dem Terminal stehen, um Passwörter einzugeben. Hier kommt Ansible Vault ins Spiel.
Ansible Vault
Eine meiner persönlichen Lieblingsfunktionen von Ansible ist Ansible Vault, das native Funktionen zur Verschlüsselung von Inhalten bietet. Ansible Vault kann beliebige Variablen und Dateien verschlüsseln und entschlüsseln, was bedeutet, dass Sie es verwenden können, um variable Dateien zu schützen, die Geheimnisse enthalten, oder sogar ganze sensible Konfigurationsdateien zu verschlüsseln. Ansible Vaults haben viele erweiterte Funktionen, aber dieser Artikel konzentriert sich auf die Grundlagen.
Standard-YAML-Dateien, die Klartext-Geheimnisse enthalten, können einfach mit ansible-vault encrypt
verschlüsselt werden Befehl:
# Plaintext YAML file
$ cat secrets_file.enc
api_key: SuperSecretPassword
# Encrypt the file with ansible-vault
$ ansible-vault encrypt secrets_file.enc
New Vault password:
Confirm New Vault password:
Encryption successful
# Confirm that the file now contains encrypted content
$ cat secrets_file.enc
$ANSIBLE_VAULT;1.1;AES256
38396162626134393935663839666463306231653861336630613938303662633538633836656465
3637353766613339663032363538626430316135623665340a653961303730353962386134393162
62343936366265353935346336643865643833353737613962643539373230616239346133653464
6435353361373263640a376632613336366430663761363339333737386637383961363833303830
34336535623736313031313162353831666139343662653665366134633832646661
Wenn ich mein Playbook ausführe, kann ich die verschlüsselte Variablendatei übergeben und Ansible anweisen, mich zur Eingabe des Passworts aufzufordern. Ansible entschlüsselt die Datei und verwendet die von mir definierten Variablen, als ob ich eine normale Variablendatei übergeben hätte:
$ cat main.yml
---
- hosts: all
gather_facts: false
tasks:
- name: Ensure API key is present in config file
ansible.builtin.lineinfile:
path: /etc/app/configuration.ini
line: "API_KEY={{ api_key }}"
$ ansible-playbook -i inventory.ini -e @secrets_file.enc --ask-vault-pass main.yml
Vault password:
PLAY [all] ***********************************************************************************
TASK [Ensure API key is present in config file] **********************************************
changed: [localhost]
PLAY RECAP ***********************************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ cat /etc/app/configuration.ini
API_KEY=SuperSecretPassword
Ich habe zuvor beschrieben, warum ein vars_prompt verwendet wird ist in einer automatisierten Umgebung nicht ideal, da ein manueller Benutzereingriff erforderlich ist. Wie unterscheidet sich ein Ansible Vault? Mit Ansible Vault können Sie eine Kennwortdatei angeben, die das Entschlüsselungskennwort für den Tresor enthält:
$ cat password_file
password
$ ansible-playbook -i inventory.ini -e @secrets_file.enc --vault-password-file password_file main.yml
PLAY [all] ***********************************************************************************
TASK [Ensure API key is present in config file] **********************************************
changed: [localhost]
PLAY RECAP ***********************************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Stellen Sie sicher, dass Sie die entsprechenden Berechtigungen für die Entschlüsselungskennwortdatei festlegen, sodass nur der Benutzer, der das Playbook ausführt, darauf zugreifen kann. Alternativ können Sie auch ein Skript verwenden, um zur Laufzeit von einem externen Passwortspeichersystem auf das Passwort zuzugreifen.
Jetzt, da meine Variablendatei verschlüsselt ist, brauche ich eine Möglichkeit, sie zu bearbeiten. Es gibt zwei Möglichkeiten, einen verschlüsselten Ansible Vault zu bearbeiten. Sie können die Datei entweder direkt bearbeiten oder vollständig entschlüsseln, bearbeiten und dann erneut verschlüsseln. Beide Methoden werden unten gezeigt.
# The edit command will launch a text editor, such as vim
$ ansible-vault edit secrets_file.enc
Vault password:
# The decrypt command will fully decrypt the file, allowing you to manipulate it how you see fit.
$ ansible-vault decrypt secrets_file.enc
Vault password:
Decryption successful
# Notice that the file has been decrypted
$ cat secrets_file.enc
api_key: SuperSecretPassword
# Don't forget to re-encrypt the file when you're done!
$ ansible-vault encrypt secrets_file.enc
New Vault password:
Confirm New Vault password:
Encryption successful
$ cat secrets_file.enc
$ANSIBLE_VAULT;1.1;AES256
33373832393864613335393836616538373639353538306462366464303939303838316337336662
6235303936636465366363643761383462356335336239640a356161653166643134663762323136
34616431303434646338343265666135666263633162383662323164396266616638313936303863
3337626365313666630a326465663239653731613637303437666164346531636361653837326166
34396232623138616364393130303036653564643435636639316264636531336161
Die Verwendung eines Ansible Vault für Geheimnisse ist eine meiner bevorzugten Methoden zum Speichern sensibler Daten. Der Vorteil dieses Ansatzes besteht darin, dass Sie Ihre vertraulichen Daten tatsächlich in der Quellcodeverwaltung neben Ihren regulären Playbooks speichern können. Da diese Dateien verschlüsselt sind, besteht bei diesem Ansatz nur ein geringes Risiko, solange Sie ein starkes Passwort wählen. Wie bei jedem gemeinsamen Geheimnis ist es eine gute Idee, das Verschlüsselungspasswort häufig zu wechseln. Ansible bietet auch mehrere erweiterte Funktionen für Tresore, z. B. die Möglichkeit, unterschiedliche Passwörter für verschiedene Tresore zu haben. Sehen Sie sich unbedingt die Dokumentation an, um zu erfahren, wie Sie Ihre Geheimnisse mit den nativen Funktionen von Ansible sichern können.
Einen vorhandenen Passwortmanager verwenden
Die beiden vorherigen Ansätze sind reine Ansible-Ansätze zur Verwaltung von Geheimnissen. Viele Unternehmen verfügen jedoch bereits über Tools wie HashiCorp Vault oder Thycotic Secret Server. Die Ansible-Community hat eine Reihe von benutzerdefinierten Modulen für die Interaktion mit diesen Systemtypen geschrieben.
Das folgende Playbook verwendet eine Suche, um ein Geheimnis von HashiCorp Vault abzurufen und dieses Geheimnis dann in einer Aufgabe zu verwenden:
---
- hosts: all
gather_facts: false
tasks:
- name: Ensure API key is present in config file
ansible.builtin.lineinfile:
path: /etc/app/configuration.ini
line: "API_KEY={{ lookup('hashi_vault', 'secret=config-secrets/data/app/api-key:data token=s.FOmpGEHjzSdxGixLNi0AkdA7 url=http://localhost:8201')['key'] }}"
Auf Ansible Galaxy finden Sie eine Vielzahl von Plugins für verschiedene Secret-Management-Tools. Wie bei jedem von der Community unterstützten Projekt ist es eine gute Idee, den Code zu prüfen, damit Sie verstehen, wie er mit Ihren Daten und Geheimnissen umgeht. Vielleicht möchten Sie sogar Ihre eigenen schreiben.
Die Verwendung eines Lookup-Plugins oder -Moduls eignet sich gut für Organisationen, die bereits über ein ausgereiftes Tool zur Verwaltung von Geheimnissen verfügen und einfach möchten, dass Ansible Geheimnisse aus diesem vorhandenen System nutzt. Der offensichtliche Nachteil ist die reduzierte Einfachheit:Die Ausführung von Playbooks hängt jetzt von der Verfügbarkeit eines externen Systems ab, und es kann zeitaufwändig sein, sich auf ein von der Community unterstütztes Modul zu verlassen (oder ein eigenes zu schreiben).
Ein Hinweis zur Protokollierung
Es ist wichtig, sich daran zu erinnern, dass die Verschlüsselung von Daten im Ruhezustand (z. B. in einem Ansible Vault oder einem externen Secrets-System) nicht bedeutet, dass Daten davor geschützt sind, versehentlich in einer Ansible-Protokolldatei ausgegeben zu werden. Wenn das Modul, das Sie aufrufen, Ihr Geheimnis während seines normalen Betriebs protokolliert oder wenn ein Fehler auftritt, wird dieses Geheimnis möglicherweise in Ihren Protokolldateien offengelegt. Unabhängig davon, ob Sie diese Protokolle in einem zentralen System speichern oder einfach die standardmäßige Standardausgabeansicht verwenden, ist es wichtig, Ihre Geheimnisse vor versehentlicher Offenlegung zu schützen.
Die folgende Ausgabe stammt aus demselben Ansible-Playbook, das ich für dieses Tutorial verwendet habe. Allerdings habe ich das Ansible-Debug-Level mit -vvv
erhöht . Beachten Sie, dass mein Geheimnis (API_KEY=SuperSecretPassword ) wird direkt in der Debug-Ausgabe angezeigt. Ich habe dieses Snippet ein wenig aufgeräumt, also machen Sie sich keine Sorgen, wenn Sie dies versuchen und Ihre Ausgabe etwas anders aussieht.
TASK [Ensure API key is present in config file] ***********************************************************************************************************************************************
fatal: [localhost]: FAILED! => changed=false
ansible_facts:
discovered_interpreter_python: /usr/bin/python
invocation:
module_args:
attributes: null
backrefs: false
backup: false
content: null
create: false
delimiter: null
directory_mode: null
firstmatch: false
follow: false
force: null
group: null
insertafter: null
insertbefore: null
line: API_KEY=SuperSecretPassword
mode: null
owner: null
path: /etc/app/configuration.ini
regexp: null
remote_src: null
selevel: null
serole: null
setype: null
seuser: null
src: null
state: present
unsafe_writes: null
validate: null
msg: Destination /etc/app/configuration.ini does not exist !
rc: 257
Das ist definitiv nicht ideal:Mein Geheimnis ist genau dort, für alle sichtbar. Glücklicherweise bietet Ansible einen no_log-Parameter für Aufgaben, die vertrauliche Daten schützen:
---
- hosts: all
gather_facts: false
tasks:
- name: Ensure API key is present in config file
ansible.builtin.lineinfile:
path: /etc/app/configuration.ini
line: "API_KEY={{ api_key }}"
no_log: True
Durch Hinzufügen dieses Parameters zu der Aufgabe, die mit sensiblen Daten interagiert, wird die Ausgabe der fehlgeschlagenen Aufgabe unterdrückt und die Vertraulichkeit meines Geheimnisses gewahrt:
TASK [Ensure API key is present in config file] ***********************************************************************************************************************************************
fatal: [localhost]: FAILED! => changed=false
censored: 'the output has been hidden due to the fact that ''no_log: true'' was specified for this result'
Es ist eine gute Idee, no_log zu verwenden bei jeder Aufgabe, die mit sensiblen Daten interagiert. Sie sollten sich auch seiner Einschränkungen bewusst sein:Es wird die Protokollierung nicht verhindern, wenn das Ansible-Debugging aktiviert ist.
[ Suchen Sie nach mehr Informationen zur Systemautomatisierung? Beginnen Sie mit The Automated Enterprise, einem kostenlosen Buch von Red Hat. ]
Abschließende Gedanken
Die ordnungsgemäße Verwaltung von Geheimnissen ist eine häufige frühe Herausforderung, mit der viele Systemadministratoren konfrontiert sind, wenn sie an der Bereitstellung von Automatisierung arbeiten. In diesem Artikel habe ich drei verschiedene Methoden beschrieben und demonstriert, mit denen Sie vertrauliche Daten schützen können, wenn Sie Ansible in Ihrer Umgebung verwenden. Dieser Artikel hat nur an der Oberfläche der Möglichkeiten gekratzt, also lesen Sie unbedingt die Dokumentation, die ich in dieser Diskussion verlinkt habe. Sicherheit ist die Aufgabe aller. Sie können Ihren Teil als Systemadministrator beitragen, indem Sie sicherstellen, dass Sie private Daten in Ihren Automatisierungspipelines mit der Sensibilität behandeln, die sie verdienen.