Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung Nächste ÜberarbeitungBeide Seiten der Revision | ||
linux:ansible:playbook_example_08 [22.09.2022 10:14. ] – [Script anlegen] django | linux:ansible:playbook_example_08 [22.09.2022 14:37. ] – [Script anlegen] django | ||
---|---|---|---|
Zeile 275: | Zeile 275: | ||
<WRAP center round info 80%> | <WRAP center round info 80%> | ||
- | Mit Hinblick auf das all umspannende Thema **Sicherheit in der IT** ist eines unserer | + | Mit Hinblick auf das all umspannende Thema **Sicherheit in der IT** ist eines unserer |
Folgende Sicherheitsvorkehrungen wollen wir unseren Admins an die Hand geben: | Folgende Sicherheitsvorkehrungen wollen wir unseren Admins an die Hand geben: | ||
- | - Die Anmeldung an remote Hosts erfolgt mit Hilfe der **SSH** | + | - Die Anmeldung an remote Hosts erfolgt mit Hilfe der **SSH** |
- Der Administrator soll beim Aufruf der Playbooks **__nur noch__** den PGP-Schlüssel durch Eingabe der zugehörigen Passphrase entsperren. Das Passwort für die Rechteerweiterung wird von Ansible aus dem Vault gelesen, genau so wie das **'' | - Der Administrator soll beim Aufruf der Playbooks **__nur noch__** den PGP-Schlüssel durch Eingabe der zugehörigen Passphrase entsperren. Das Passwort für die Rechteerweiterung wird von Ansible aus dem Vault gelesen, genau so wie das **'' | ||
- | Wir wollen vertrauliche Informationen in unseren Playbooks bzw. im Inventory | + | Wir wollen vertrauliche Informationen in unseren Playbooks bzw. im Inventory |
Aus Sicht von **IT-Security** haben wir somit 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. | Aus Sicht von **IT-Security** haben wir somit 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. | ||
Zeile 295: | Zeile 295: | ||
- Ansible Directory Layout anlegen und mit Dummy-Inhalten versorgen. | - Ansible Directory Layout anlegen und mit Dummy-Inhalten versorgen. | ||
- Installation und Konfiguration des Passwortmanagers **'' | - Installation und Konfiguration des Passwortmanagers **'' | ||
- | - Hinterlegen des Ansible Become | + | - Hinterlegen des Ansible Become |
Somit erreichen wir später bequem unser gestecktes Ziel unsere Zeit als Admin effizient zu nutzen und in einer sicheren Umgebung uns zu bewegen. | Somit erreichen wir später bequem unser gestecktes Ziel unsere Zeit als Admin effizient zu nutzen und in einer sicheren Umgebung uns zu bewegen. | ||
Zeile 312: | Zeile 312: | ||
$ vim ~/ | $ vim ~/ | ||
- | <file c++ ~/ | + | <file c++ ~/ |
+ | # Ansible Playbook zum initialen Einrichten der Ansible-Umgebung | ||
+ | # | ||
+ | # Aufruf aus dem entsprechenden Arbeits-Verzeichnis via: | ||
+ | # ansible-playbook playbooks/ansible_grundconfig_v2.ym -K | ||
- | FIXME | + | - name: ansible_grundconfig_v2.yml |
+ | gather_facts: | ||
+ | hosts: localhost | ||
+ | become: true | ||
+ | vars: | ||
+ | ansible_working_dir: | ||
+ | ansible_config: | ||
+ | admin_user: "{{ lookup(' | ||
+ | admin_mail: django@nausch.org | ||
+ | vars_prompt: | ||
+ | - name: pass_secret | ||
+ | prompt: "Enter password for password-store?" | ||
+ | - name: pass_secret_2nd | ||
+ | prompt: " | ||
+ | - name: become_secret | ||
+ | prompt: "Enter become-password for sudo?" | ||
+ | - name: become_secret_2nd | ||
+ | prompt: " | ||
+ | |||
+ | tasks: | ||
+ | - name: " | ||
+ | fail: | ||
+ | msg: " | ||
+ | when: | ||
+ | - pass_secret != pass_secret_2nd | ||
+ | |||
+ | - name: " | ||
+ | fail: | ||
+ | msg: " | ||
+ | when: | ||
+ | - become_secret != become_secret_2nd | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.stat: | ||
+ | path: '{{ ansible_config }}' | ||
+ | register: check_ansible_config | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.fail: | ||
+ | msg: " | ||
+ | when: check_ansible_config.stat.exists != 1 | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.copy: | ||
+ | dest: '/ | ||
+ | group: '{{ admin_user }}' | ||
+ | owner: '{{ admin_user }}' | ||
+ | src: '{{ ansible_config }}' | ||
+ | mode: ' | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.lineinfile: | ||
+ | line: "{{ item.line }}" | ||
+ | path: "/ | ||
+ | regexp: "{{ item.regexp }}" | ||
+ | state: present | ||
+ | with_items: | ||
+ | - { | ||
+ | regexp: " | ||
+ | line: " | ||
+ | # default: | ||
+ | } | ||
+ | - { | ||
+ | regexp: " | ||
+ | line: "# Generated by Ansible on {{ ansible_date_time.date }}, do not edit manually!\n\ | ||
+ | # default: # | ||
+ | inventory | ||
+ | } | ||
+ | - { | ||
+ | regexp: " | ||
+ | line: "# Generated by Ansible on {{ ansible_date_time.date }}, do not edit manually!\n\ | ||
+ | # default: # | ||
+ | roles_path | ||
+ | } | ||
+ | - { | ||
+ | regexp: " | ||
+ | line: "# Generated by Ansible on {{ ansible_date_time.date }}, do not edit manually!\n\ | ||
+ | # default: # | ||
+ | vault_password_file = ~/ | ||
+ | } | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.file: | ||
+ | path: '/ | ||
+ | state: directory | ||
+ | owner: '{{ admin_user }}' | ||
+ | group: '{{ admin_user }}' | ||
+ | mode: ' | ||
+ | with_items: | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | - {directory: " | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.file: | ||
+ | path: '/ | ||
+ | state: touch | ||
+ | owner: '{{ admin_user }}' | ||
+ | group: '{{ admin_user }}' | ||
+ | mode: ' | ||
+ | with_items: | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | - {file: " | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.package: | ||
+ | name: pass | ||
+ | update_cache: | ||
+ | state: latest | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.file: | ||
+ | path: '/ | ||
+ | group: '{{ admin_user }}' | ||
+ | owner: '{{ admin_user }}' | ||
+ | state: directory | ||
+ | mode: ' | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.copy: | ||
+ | dest: '/ | ||
+ | content: | | ||
+ | # | ||
+ | # Ansible generated, do not edit manually! | ||
+ | pass show ansible-vault-password | ||
+ | owner: '{{ admin_user }}' | ||
+ | group: '{{ admin_user }}' | ||
+ | mode: ' | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.file: | ||
+ | path: '/ | ||
+ | state: absent | ||
+ | |||
+ | - name: " | ||
+ | become_user: | ||
+ | become: true | ||
+ | shell: | | ||
+ | set -o pipefail && pass init '{{ admin_mail }}' && / | ||
+ | changed_when: | ||
+ | args: | ||
+ | executable: /bin/bash | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.file: | ||
+ | path: '/ | ||
+ | state: absent | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.copy: | ||
+ | dest: '/ | ||
+ | content: | | ||
+ | ansible_become_pass: | ||
+ | owner: '{{ admin_user }}' | ||
+ | group: '{{ admin_user }}' | ||
+ | mode: ' | ||
+ | |||
+ | - name: " | ||
+ | become_user: | ||
+ | become: true | ||
+ | shell: | | ||
+ | ansible-vault encrypt /home/{{ admin_user }}/ | ||
+ | changed_when: | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.file: | ||
+ | path: '/ | ||
+ | state: absent | ||
+ | |||
+ | - name: " | ||
+ | ansible.builtin.copy: | ||
+ | dest: '/ | ||
+ | content: | | ||
+ | # Generated by Ansible on {{ ansible_date_time.date }}, do not edit manually! | ||
+ | ansible_become: | ||
+ | ansible_become_method: | ||
+ | ansible_become_user: | ||
+ | ansible_become_ask_pass: | ||
+ | owner: '{{ admin_user }}' | ||
+ | group: '{{ admin_user }}' | ||
+ | mode: ' | ||
+ | |||
+ | ... # YML Ende</ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Wichtig: | ||
+ | Die Variable **'' | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Script Beschreibung === | ||
+ | Mit Hilfe des Playbooks werden alle wesentlichen Konfigurationsoptionen definiert, die im Kapitel **[[first# | ||
+ | |||
+ | Nacheinander werden folgende Punkte abgearbeitet: | ||
+ | - Ermitteln des angemeldeten (Admin-)Usernamens **'' | ||
+ | - Abfrage des Passwortes für den **Password-Store** und des **'' | ||
+ | - Prüfen, ob die Konfigurationsdatei **''/ | ||
+ | - Kopieren der Ansible Konfigurationsdatei **''/ | ||
+ | - Setzen der Ansible-Konfigurationsoptionen | ||
+ | * **'' | ||
+ | * **'' | ||
+ | * **'' | ||
+ | * **'' | ||
+ | - Ansible Directory Layout anlegen und anschliessend | ||
+ | - Ansible Directory Layout mit dummy-files main.yml befüllen. | ||
+ | - Installation des Passwort-Managers **'' | ||
+ | - vault-Wrapperscript im **'' | ||
+ | - Store-Passwort für **'' | ||
+ | - Im Inventory das **'' | ||
+ | - Ansible-Vault Datei, die zuvor angelegt wurde, mit dem Ansible-Vault-Passwort sicher verschlüsseln. | ||
+ | - Im Inventory die Definitionen zu privilege_escalation anlegen und auch hier ggf. ein bereits existierende Konfigurationsdatei vorher löschen. | ||
+ | |||
+ | === Script starten === | ||
+ | Das Ansible-Playbook lässt sich wie folgt auf dem Ansible-Controll-Host bzw. der Admin-Workstation aufrufen: | ||
+ | |||
+ | $ ansible-playbook ~/ | ||
+ | |||
+ | < | ||
+ | <pre class=" | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match ' | ||
+ | <font style=" | ||
+ | Retype password for password-store?: | ||
+ | Enter become-password for sudo?: | ||
+ | Retype become-password for sudo?: | ||
+ | |||
+ | PLAY [ansible_grundconfig_v2.yml] ************************************************************************************************* | ||
+ | |||
+ | TASK [Gathering Facts] ************************************************************************************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Playbooklauf abbrechen sofern die beiden eigegebenen Passwörter nicht übereinstimmen!] **************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Playbooklauf abbrechen sofern die beiden eigegebenen Passwörter nicht übereinstimmen!] **************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Ansible Konfigurationsdatei / | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Fehlerhinweis im Fehlerfall ausgeben] ***************************************************************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Ansible Konfigurationsverzeichnis in das User/ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Ansible Konfiguration anpassen] *********************************************************************************************</ | ||
+ | <font style=" | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | <font style=" | ||
+ | TASK [Ansible Directory Layout anlegen] *******************************************************************************************</ | ||
+ | <font style=" | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | ok: [localhost] => (item={' | ||
+ | <font style=" | ||
+ | TASK [Ansible Directory Layout mit dummy-files main.yml befüllen] ***************************************************************</ | ||
+ | <font style=" | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | changed: [localhost] => (item={' | ||
+ | <font style=" | ||
+ | TASK [Passwort-Manager pass installieren] ***********************************************************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Verzeichnis ~/bin anlegen] ********************************************************************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [vault-Wrapperscript anlegen] ******************************************************************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Sicherstellen dass das pass Store-Verzeichnis nicht existiert] ********************************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Pass-Store Passwort ablegen] ******************************************************************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Sicherstellen dass das File für das verschlüsselte become-password noch nicht existiert] ******************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Ansible Become Password für sudo Rechteerweiterung anlegen] ***********************************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Ansible Become Password mit ansible-vault verschlüsseln] **************************************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Sicherstellen dass das File mit der Ansible-Konfiguration nicht existiert] ********************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | TASK [Ansible Konfigurationsdatei mit den Definitionen zu privilege_escalation anlegen] *************************************</ | ||
+ | <font style=" | ||
+ | <font style=" | ||
+ | PLAY RECAP ********************************************************************************************************************</ | ||
+ | <font style=" | ||
+ | |||
+ | </ | ||
+ | </ | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | Der Aufruf des Scripts **'' | ||
+ | $ ansible-playbook -v 01_create-user.yml --limit=demo | ||
+ | |||
+ | Nach der Abfrage des **'' | ||
+ | |||
+ | ===== Fazit und Ausblick ===== | ||
+ | <WRAP center round info 60%> | ||
+ | Wir haben nun Dank der beiden gezeigten Ansible-Playbooks zur Konfiguration unserer Ansible-Umgebung die Möglichkeit, | ||
+ | </ | ||
+ | |||
+ | ====== Links ====== | ||
+ | * **[[detail|zurück zum Kapitel " | ||
+ | * **=> [[playbook_example_08|weiter zum Kapitel " | ||
+ | * **[[start|Zurück zur " | ||
+ | * **[[wiki: | ||
+ | * **[[http:// |