Linux-Benutzerkonten mit Ansible verwalten

Wie bereits in diesem Beitrag erwähnt, beschäftige ich mich aktuell mit der Evaluierung von Ansible.

In diesem Artikel dokumentiere ich ein Beispiel, wie das Modul user zur Administration von Linux-Benutzerkonten verwendet werden kann. Der Link zur offiziellen Dokumentation des user-Moduls befindet sich am Ende dieses Artikels.[1. Ansible Module: user – Manage user accounts {en}]

Hinweis: Die folgende Konfiguration ist nicht zur Nachahmung empfohlen. Es handelt sich dabei um meine ersten Schritte mit Ansible. Es ist daher wahrscheinlich, dass die Konfiguration noch Fehler enthält, nicht optimiert ist und ein großes Verbesserungspotenzial besitzt. Die Nachahmung erfolgt ausdrücklich auf eigene Gefahr. Über Hinweise, wie man es besser machen kann, freue ich mich jederzeit.

Anforderungen

  • Es soll ein lokales Benutzerkonto angelegt werden
  • Der Benutzer soll Mitglied der Gruppe „wheel“ werden
  • Es soll ein initiales Passwort für das Benutzerkonto gesetzt werden
  • Ein öffentlicher SSH-Schlüssel soll in die Datei authorized_keys des zu erstellenden Benutzers eingetragen werden
  • Konfiguration des SSH-Daemons

Vorbereitung

Abgeleitet aus den „Best Practices“[2. Ansible Best Practices – Directory Layout] verwende ich auf meiner Spielwiese folgende Verzeichnisstruktur:

ansible/
|-- autoupdate.txt            # ignore
|-- autoupdate.yml            # ignore
|-- check_reboot.             # playbook which sets the repos
|-- group_vars
|   `-- e-stage               # variables for group e-stage
|-- hosts                     # inventory file
|-- host_vars                 # for system specific variables
|-- roles
|   |-- common                # this hierarchy represents a "role"
|   |   |-- defaults          
|   |   |-- files
|   |   |-- handlers
|   |   |   `-- main.yml      # handlers file
|   |   |-- meta
|   |   |-- tasks
|   |   |   `-- main.yml      # tasks file can include smaller files if warranted
|   |   `-- vars
|   `-- e-stage
|       |-- defaults
|       |-- files
|       |-- handlers
|       |-- meta
|       |-- templates
|       `-- vars
|-- create_johnd.yml          # playbook which creates user johnd
|-- site.yml                  # master playbook file
`-- staging                   # inventory file for staging environment

17 directories, 11 files

Um das Passwort für den neuen Benutzer erstellen zu können, muss zuerst der passende Passwort-Hash generiert werden[3. How do I generate crypted passwords for the user module?]:

python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())"

Der generierte Hash wird auf der Standardausgabe ausgegeben. Dieser wird für das Playbook benötigt.

Playbook und Tasks

Das Playbook ist sehr kurz gehalten und gibt im Wesentlichen nur an, welche Hosts auf welche Rolle gemapped werden sollen.

# create_johnd.yml
---
- hosts: all
  roles:
    - common

Bei Verwendung dieses Playbooks werden die Tasks aus der Datei roles/common/tasks/main.yml ausgeführt, welche wie folgt aufgebaut wurde:

---
# Configure sshd_config on target system
- name: Enable Public-Key-Authentication
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: "^PubkeyAuthentication"
    line: "PubkeyAuthentication yes"
    state: present
  notify:
    - reload sshd

- name: Set AuthorizedKeyFile
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: "^AuthorizedKeysFile"
    line: "AuthorizedKeysFile      .ssh/authorized_keys"
    state: present
  notify:
    - reload sshd

- name: Disable PasswordAuthentication
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: "^PasswordAuthentication"
    line: "PasswordAuthentication no"
    state: present
  notify:
    - reload sshd

# Add user johnd with specific uid in group 'wheel'
- user: name=johnd comment="John Doe" uid=100 groups=wheel password="PASSWORDHASH" shell=/bin/bash append=yes state=present
  notify:
    - deploy ssh-pub-keys

Die hier spezifizierten Tasks setzen die folgenden Aufgaben um:

  • Aktivierung der Public-Key-Authentication
  • Spezifikation des Standard-AuthorizedKeysFile
  • Deaktivierung der Password-Authentication

Was in dieser Datei noch nicht zu sehen ist, ist die Verteilung eines öffentlichen SSH-Schlüssels. Dies wird von dem Handler[4. Ansible Handlers – Running Operations On Change] deploy ssh-pub-keys übernommen.

Der Handler ist in der Datei roles/common/handlers/main.yml definiert. Es handelt sich dabei um einen Task, welcher nur ausgeführt wird, wenn der Benutzer erfolgreich erstellt wurde.

Fazit

Soweit zu meinen ersten Gehversuchen mit Ansible Playbooks. Meine Anforderungen können mit dem hier dokumentierten Playbook erfüllt werden.

In dem hier beschriebenen Beispiel habe ich angenommen, dass es sich bei dem zu erstellenden Benutzer um das erste lokale Benutzerkonto neben root handelt. Dieses soll über die Berechtigung verfügen, Kommandos mit sudo auszuführen und primär für die Arbeit auf dem System verwendet werden.

Die Verteilung des SSH-Schlüssels über einen Handler anzustoßen erscheint mir jedoch nicht optimal. Der Handler wird nur dann ausgeführt, wenn durch das user-Modul Änderungen am Zielsystem vorgenommen wurden. Weitere SSH-Schlüssel bzw. Änderungen an bereits vorhandenen SSH-Schlüsseln lassen sich auf diesem Weg nicht vornehmen.

Daher erscheint es mir sinnvoll, die Verteilung von SSH-Schlüsseln über das Modul authorized_key[5. Ansible Module: authorized_key – Adds or removes an SSH authorized key] in ein eigenes Playbook auszulagern.

5 Gedanken zu „Linux-Benutzerkonten mit Ansible verwalten

  1. hefeweiz3n

    Alternativ das Passwort in einer vault-Datei speichern oder interaktiv einlesen lassen, dann kannst du das auch direkt durch ansible hashen lassen: {{ plaintext_passwort_variable | password_hash(’sha512′) }}

    Antworten
  2. Pingback: Ansible – Die Module copy und cron | My-IT-Brain

  3. Pingback: Ansible: Patch-Management für Red Hat Systeme | My-IT-Brain

  4. Pingback: Labor-Umgebung mit Ansible in KVM erstellen | My-IT-Brain

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert