Ansible - einfaches Playbook-Beispiel: mehrere Benutzer anlegen

Bild: Ansible Logo

Im Eingangskapitel Grundlagen haben wir uns mit der Installation bereits befasst. Auch haben wir uns schon in den beiden Kapiteln Playbooks und YAML - was ist das? eingehend mit den Hintergrundinformationen beschäftigt, so dass wir uns nun mit unsere Playbooks beschäftigen können.

Beim dritten Playbook-Beispiel wollen wir mit Hilfe von Ansible nicht nur ein Admin-Konto sondern gleich mehrere anlegen. Dabei kopieren wir dann auch noch gleich die zugehörigen öffentlichen SSH-Schlüssel an Ort und Stelle. Zu guter Letzt stellen wir noch sicher dass der Eintrag %wheel ALL=(ALL) ALL gesetzt ist, hierzu binden wird das YAML-Playbook von Beispiel 02 ein.

Bevor wir unser erstes Script schreiben, wechseln wir in unser zuvor angelegtes Zielverzeichnis:

 $ cd ~/ansible

Nun legen wir nun unser erstes Script ab.

 $ vim 03_create-admins.yml
03_create-admins.yml
---
- hosts: centos8
  become: true
  vars:
    sudoers: ansible
 
  tasks:
    - name: add several users to the system
      user:
        name: "{{ item.name }}"
        comment: "{{ item.fullname }}"
        uid: "{{ item.uid }}"
        groups: "{{ item.groups }}"
        state: present
      with_items:
         - { name: bofh, fullname: "Bastard Operator from Hell", uid: 1020, groups: "wheel, users" }
         - { name: ruben, fullname: "Ruben Nausch", uid: 1010, groups: wheel }
         - { name: ansible, fullname: "Ansible Systemuser", uid: 2003, groups: wheel }
 
    - name: Initial password generation for each user
      shell: usermod -p $(echo '{{ item.secret }}' | openssl passwd -1 -stdin) {{ item.name }}
      with_items:
         - { name: bofh, secret: "/ImTAxBwi++W2Y26195+Q72GbH73i/zQyaq12wsx" }
         - { name: ruben, secret: "lop5YtypT+E6qhOjpZEoAlnyiLH7HlIF1k212qyo" }
         - { name: ansible, secret: "X4z3AEx6WZ2+DDzvuzjx0mBERQ-o03f12qwPOSyx" }
 
    - name: Set authorized keys for each user
      authorized_key:
        user: "{{ item.name }}"
        state: present
        key: "{{ lookup('file', '/home/django/ansible/authkeys/{{ item.name }}.pub') }}"
      with_items:
         - {name: bofh }
         - {name: ruben }
         - {name: ansible }
 
    - include_tasks: 02_passwd_sudo_wheel.yml
...

WICHTIG: Auch hier gilt die Warnung aus Beispiel 1: Es zeigt sehr anschaulich, dass es definitiv keine gute Idee ist, Passworte und Schlüsselmaterial direkt in einem Playbook und/oder Inventory unverschlüsselt vor zuhalten. Dies gilt um so mehr, wenn man seine Ansible bei GitHub oder GitLab vorhält! Jeder der dort Zugriff auf die Repositories hat, gelangt so ohne grosse Mühe an vertraulichen Informationen!

Wie wir dieses Thema elegant und sicher lösen können und auch werden, betrachten wir eingehend in dem Ansible - erweitertes Konfigurationsbeispiel 7: Ansible Vault.

Das Script ist soweit selbsterklärend, werden doch der Reihe nach vier Tasks abgearbeitet:

  • Task 1 : Drei Userkonten anlegen - die betreffenden Daten für unsere User holen wir uns dabei aus einer Liste (array)
  • Task 2 : Setzen der initialen Passwörter je Userkonto
  • Task 3 : Kopieren der jeweiligen öffentlichen SSH-Schlüssel der User. In diesem Konfigurationsbeispiel liegen diese im Verzeichnis /home/django/ansible/authkeys/.
     $ ~/ansible/authkeys/ 
    insgesamt 12
    -rw-r--r--. 1 django django 100  4. Jan 22:12 ansible.pub
    -rw-r--r--. 1 django django 108  4. Jan 22:13 bofh.pub
    -rw-r--r--. 1 django django  98  4. Jan 22:16 ruben.pub
  • Task 4 : Das Anpassen der sudoers-Eigenschaften haben wir in diesem Konfigurationsbeispiel in eine separate YAML-Datei ausgelagert. Hierzu nutzen wir das YAML-Modul include. Das entsprechende Include-Verzeichnis legen wir gleich mal an.
     $ mkdir ~/ansible/includes

    Hier legen wir uns eine YAML-Datei an, die nur den entsprechenden task beinhaltet.

     $ vim  includes/sudoers.yml
    includes/sudoers.yml
    ---
        - name: All users from groub 'wheel' are allowed sudo users
          copy:
            content: "# Allows people in group wheel to run all command\n%wheel    ALL=(ALL)       ALL\n"
            dest: /etc/sudoers.d/10_passwd_sudo_wheel
            owner: root
            group: root
            mode: "0440"
            validate: visudo -cf %s

Nun wollen wir unser Playbook ausführen, um auf dem Zielhost den gewünschten Benutzer anzulegen; hierzu rufen wir unser Script wie folgt auf:

 $ ansible-playbook -v 03_create-admins.yml03_create-admins.yml

Using /etc/ansible/ansible.cfg as config file
BECOME password: 

PLAY [centos8] ****************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************
ok: [www8.dmz.nausch.org]
TASK [add several users to the system] ************************************************************************************************* changed: [www8.dmz.nausch.org] => (item={'name': 'bofh', 'fullname': 'Bastard Operator from Hell', 'uid': 1020, 'groups': 'wheel, users'}) => {"ansible_loop_var": "item", "changed": true, "comment": "Bastard Operator from Hell", "create_home": true, "group": 1020, "groups": "wheel, users", "home": "/home/bofh", "item": {"fullname": "Bastard Operator from Hell", "groups": "wheel, users", "name": "bofh", "uid": 1020}, "name": "bofh", "shell": "/bin/bash", "state": "present", "system": false, "uid": 1020} changed: [www8.dmz.nausch.org] => (item={'name': 'ruben', 'fullname': 'Ruben Nausch', 'uid': 1010, 'groups': 'wheel'}) => {"ansible_loop_var": "item", "changed": true, "comment": "Ruben Nausch", "create_home": true, "group": 1010, "groups": "wheel", "home": "/home/ruben", "item": {"fullname": "Ruben Nausch", "groups": "wheel", "name": "ruben", "uid": 1010}, "name": "ruben", "shell": "/bin/bash", "state": "present", "system": false, "uid": 1010} ok: [www8.dmz.nausch.org] => (item={'name': 'ansible', 'fullname': 'Ansible Systemuser', 'uid': 500, 'groups': 'wheel'}) => {"ansible_loop_var": "item", "append": false, "changed": false, "comment": "Ansible Systemuser", "group": 500, "groups": "wheel", "home": "/home/ansible", "item": {"fullname": "Ansible Systemuser", "groups": "wheel", "name": "ansible", "uid": 500}, "move_home": false, "name": "ansible", "shell": "/bin/bash", "state": "present", "uid": 500}
TASK [Initial password generation for each user] *************************************************************************************** changed: [www8.dmz.nausch.org] => (item={'name': 'bofh', 'secret': '/ImTAxBwi++W2Y26195+Q72GbH73i/zQyaq12wsx'}) => {"ansible_loop_var": "item", "changed": true, "cmd": "usermod -p $(echo '/ImTAxBwi++W2Y26195+Q72GbH73i/zQyaq12wsx' | openssl passwd -1 -stdin) bofh", "delta": "0:00:00.389066", "end": "2020-01-05 17:04:51.991293", "item": {"name": "bofh", "secret": "/ImTAxBwi++W2Y26195+Q72GbH73i/zQyaq12wsx"}, "rc": 0, "start": "2020-01-05 17:04:51.602227", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []} changed: [www8.dmz.nausch.org] => (item={'name': 'ruben', 'secret': 'lop5YtypT+E6qhOjpZEoAlnyiLH7HlIF1k212qyo'}) => {"ansible_loop_var": "item", "changed": true, "cmd": "usermod -p $(echo 'lop5YtypT+E6qhOjpZEoAlnyiLH7HlIF1k212qyo' | openssl passwd -1 -stdin) ruben", "delta": "0:00:00.382204", "end": "2020-01-05 17:04:53.167841", "item": {"name": "ruben", "secret": "lop5YtypT+E6qhOjpZEoAlnyiLH7HlIF1k212qyo"}, "rc": 0, "start": "2020-01-05 17:04:52.785637", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []} changed: [www8.dmz.nausch.org] => (item={'name': 'ansible', 'secret': 'X4z3AEx6WZ2+DDzvuzjx0mBERQ-o03f12qwPOSyx'}) => {"ansible_loop_var": "item", "changed": true, "cmd": "usermod -p $(echo 'P1r473np4r731' | openssl passwd -1 -stdin) ansible", "delta": "0:00:00.386751", "end": "2020-01-05 17:04:54.313829", "item": {"name": "ansible", "secret": "X4z3AEx6WZ2+DDzvuzjx0mBERQ-o03f12qwPOSyx"}, "rc": 0, "start": "2020-01-05 17:04:53.927078", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
TASK [Set authorized keys for each user] *********************************************************************************************** hanged: [www8.dmz.nausch.org] => (item={'name': 'bofh'}) => {"ansible_loop_var": "item", "changed": true, "comment": null, "exclusive": false, "follow": false, "item": {"name": "bofh"}, "key": "ssh-ed25519 AAAAC3NzaC2lZDI1NTE5AAAAILxi47aZOS3tfvNFxVVqkJAfSKXjpvemB3kRZEQ5q/kf Bastard Operator from Hell", "key_options": null, "keyfile": "/home/bofh/.ssh/authorized_keys", "manage_dir": true, "path": null, "state": "present", "user": "bofh", "validate_certs": true} changed: [www8.dmz.nausch.org] => (item={'name': 'ruben'}) => {"ansible_loop_var": "item", "changed": true, "comment": null, "exclusive": false, "follow": false, "item": {"name": "ruben"}, "key": "ssh-ed25519 AAAAC3TzaC2lZ60DI1NTE5AAILxi47aZOS3tfvNFxq16293SKXjp4tsB3kRZffQ5q/kf ruben@nausch.org", "key_options": null, "keyfile": "/home/ruben/.ssh/authorized_keys", "manage_dir": true, "path": null, "state": "present", "user": "ruben", "validate_certs": true} ok: [www8.dmz.nausch.org] => (item={'name': 'ansible'}) => {"ansible_loop_var": "item", "changed": false, "comment": null, "exclusive": false, "follow": false, "item": {"name": "ansible"}, "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILti47aZOSetfvNFxVVqkJAfSKXjyvemB3kRZEQ5q/kf Ansible Systemuser", "key_options": null, "keyfile": "/home/ansible/.ssh/authorized_keys", "manage_dir": true, "path": null, "state": "present", "user": "ansible", "validate_certs": true}
TASK [All users from groub 'wheel' are allowed sudo users] ***************************************************************************** included: /home/django/ansible/includes/sudoers.yml for www8.dmz.nausch.org
TASK [All users from groub 'wheel' are allowed sudo users] ***************************************************************************** ok: [www8.dmz.nausch.org] => {"changed": false, "checksum": "b51f017f799aca0d0aef9fa29b7da87006ea5c29", "dest": "/etc/sudoers.d/10_passwd_sudo_wheel", "gid": 0, "group": "root", "mode": "0440", "owner": "root", "path": "/etc/sudoers.d/10_passwd_sudo_wheel", "secontext": "system_u:object_r:etc_t:s0", "size": 80, "state": "file", "uid": 0}
PLAY RECAP *************************************************************************************************************************************** www8.dmz.nausch.org : ok=6 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Auf dem Zielhost findet sich nun unsere gewünschte Datei mit dem zugehörigen Inhalt.

 # cat /etc/sudoers.d/10_passwd_sudo_wheel
/etc/sudoers.d/10_passwd_sudo_wheel
# Allows people in group wheel to run all command
%wheel    ALL=(ALL)       ALL

Auch unsere drei Nutzer-/Admin-Konten sind angelet und deren öffentlicher SSH-Schlüssel in diue Datei .ssh/authorized_keys im jeweiligen Homeverzeichnis der User kopiert.

/home/
├── ansible
│   ├── .bash_logout
│   ├── .bash_profile
│   ├── .bashrc
│   ├── .ssh
│   │   └── authorized_keys
├── bofh
│   ├── .bash_logout
│   ├── .bash_profile
│   ├── .bashrc
│   └── .ssh
│       └── authorized_keys
└── ruben
    ├── .bash_logout
    ├── .bash_profile
    ├── .bashrc
    └── .ssh
        └── authorized_keys

Links

Diese Website verwendet Cookies. Durch die Nutzung der Website stimmen Sie dem Speichern von Cookies auf Ihrem Computer zu. Außerdem bestätigen Sie, dass Sie unsere Datenschutzbestimmungen gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
  • linux/ansible/playbook_example_03.txt
  • Zuletzt geändert: 05.10.2022 18:08.
  • von django