Ansible mit Rocky: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
Zeile 206: Zeile 206:
 
     name: sssd
 
     name: sssd
 
     state: restarted
 
     state: restarted
 +
 +
- name: authselect anwenden
 +
  command: authselect apply-changes
 
</syntaxhighlight>
 
</syntaxhighlight>
  

Version vom 5. Juli 2026, 10:06 Uhr

Ansible auf Rocky Linux

Ansible ist ein agentenloser Automatisierungsdienst: Es wird nur auf dem Control Node installiert, die verwalteten Maschinen ("Managed Nodes") brauchen lediglich SSH-Zugang und Python – kein Agent, kein zusätzlicher Dienst.

Im Labor übernimmt client.it2XX.int die Rolle des Control Node und verwaltet von dort aus alle DMZ-Server (fw, ns, www, ldap). Gearbeitet wird durchgehend als unprivilegierter User kit – root-Login ist auf allen Systemen deaktiviert, privilegierte Aktionen laufen über sudo.

Voraussetzungen

Auf jedem Zielsystem muss ein kit-User mit passwortlosem sudo existieren
  • sudo visudo
kit ALL=(ALL) NOPASSWD: ALL

Installation des Control Node

Ansible wird nur auf client.it2XX.int installiert
  • sudo dnf install -y ansible

SSH-Schlüssel vorbereiten

kit braucht auf dem Control Node einen eigenen Schlüssel, der auf allen Zielsystemen beim kit-User hinterlegt wird
  • ssh-keygen -t ed25519 -C "kit@it2XX.int"
Schlüssel als kit auf alle DMZ-Server verteilen – NICHT als root, da PermitRootLogin deaktiviert ist
  • ssh-copy-id kit@fw.it2XX.int
  • ssh-copy-id kit@ns.it2XX.int
  • ssh-copy-id kit@www.it2XX.int
  • ssh-copy-id kit@ldap.it2XX.int

Projektverzeichnis und Inventory

kit hat keine Schreibrechte auf /etc/ansible – deshalb arbeiten wir im Home-Verzeichnis statt mit sudo im systemweiten Pfad
  • mkdir -p ~/ansible
  • cd ~/ansible
ansible.cfg legt fest, wo das Inventory liegt – dann ist kein -i-Parameter mehr nötig
  • vi ~/ansible/ansible.cfg
[defaults]
inventory = ./hosts
Inventory anlegen – Maschinen nach Rolle gruppiert, kit als Verbindungsuser, sudo für privilegierte Tasks
  • vi ~/ansible/hosts
[dmz]
fw.it2XX.int
ns.it2XX.int
www.it2XX.int
ldap.it2XX.int

[dmz:vars]
ansible_user=kit
ansible_become=true
ansible_become_method=sudo

Erster Test

Alle Maschinen anpingen – Ansible nutzt dafür das ping-Modul, nicht ICMP
  • ansible all -m ping
ns.it2XX.int | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
Verbindungsuser prüfen – muss kit sein, nicht root
  • ansible dmz -m command -a "whoami"
sudo-Rechte prüfen – mit -b (become) sollte root erscheinen
  • ansible dmz -b -m command -a "whoami"
Ad-hoc Befehl auf allen Maschinen ausführen
  • ansible all -m command -a "hostname"
Nur die DMZ-Gruppe ansprechen
  • ansible dmz -m command -a "uptime"

Playbooks

Ein Playbook ist eine YAML-Datei, die Tasks in fester Reihenfolge auf einer Zielgruppe ausführt
Einfaches Beispiel – Paket installieren und eine harmlose Testdatei anlegen, läuft dank ansible_become automatisch mit sudo. Nichts hiervon verändert bestehende Konfiguration.
  • vi ~/ansible/test.yml
---
- name: Testplaybook
  hosts: dmz
  tasks:
    - name: htop installieren
      dnf:
        name: htop
        state: present

    - name: Testdatei mit Zeitstempel anlegen
      copy:
        content: "Ansible-Testlauf: {{ ansible_date_time.iso8601 }}\n"
        dest: /tmp/ansible-test.txt
        mode: '0644'
  • ansible-playbook ~/ansible/test.yml
Idempotenz zeigen – zweiter Lauf meldet "changed=0", da nichts mehr zu tun ist
  • ansible-playbook ~/ansible/test.yml
Ergebnis prüfen
  • ansible dmz -m command -a "cat /tmp/ansible-test.txt"

Rollen

Rollen sind wiederverwendbare Ansible-Strukturen – Tasks, Templates und Handler in einem festen Verzeichnisschema
roles/
└── rollenname/
    ├── tasks/
    │   └── main.yml
    ├── templates/
    ├── handlers/
    │   └── main.yml
    └── defaults/
        └── main.yml
Rollengerüst automatisch erstellen
  • mkdir -p ~/ansible/roles
  • cd ~/ansible/roles
  • ansible-galaxy init sssd
  • ansible-galaxy init ssh-hardening

Rolle: SSSD

Diese Rolle installiert SSSD auf allen DMZ-Servern und bindet sie gegen den LDAP-Server an

tasks/main.yml

  • vi ~/ansible/roles/sssd/tasks/main.yml
- name: Pakete installieren
  dnf:
    name:
      - sssd
      - sssd-ldap
      - oddjob
      - oddjob-mkhomedir
    state: present

- name: sssd.conf schreiben
  template:
    src: sssd.conf.j2
    dest: /etc/sssd/sssd.conf
    owner: root
    group: root
    mode: '0600'
  notify: sssd neu starten

- name: authselect konfigurieren
  command: authselect select sssd with-mkhomedir --force
  changed_when: false

- name: sudoers-Eintrag in user-nsswitch.conf setzen
  lineinfile:
    path: /etc/authselect/user-nsswitch.conf
    regexp: '^sudoers:'
    line: 'sudoers:    files sss'
    state: present
  notify: authselect anwenden

- name: oddjobd starten
  systemd:
    name: oddjobd
    enabled: true
    state: started
Merksatz
sssd.conf definiert die Quelle (sudo_provider = ldap), nsswitch.conf entscheidet ob das System sie überhaupt befragt. Ohne den Eintrag in nsswitch.conf bleibt der sudo_provider wirkungslos.

templates/sssd.conf.j2

Das Template nutzt Ansible-Variablen – so funktioniert dieselbe Rolle für jeden Studenten
  • vi ~/ansible/roles/sssd/templates/sssd.conf.j2
[sssd]
config_file_version = 2
services = nss, pam, sudo
domains = {{ domain }}

[domain/{{ domain }}]
id_provider = ldap
auth_provider = ldap
chpass_provider = ldap
access_provider = permit
sudo_provider = ldap
ldap_uri = ldaps://ldap.{{ domain }}
ldap_search_base = dc={{ dc1 }},dc={{ dc2 }}
ldap_sudo_search_base = ou=sudo,dc={{ dc1 }},dc={{ dc2 }}
ldap_default_bind_dn = cn=admin,dc={{ dc1 }},dc={{ dc2 }}
ldap_default_authtok = {{ ldap_password }}
ldap_tls_cacert = /etc/pki/tls/certs/ca-bundle.crt
ldap_tls_reqcert = hard
cache_credentials = True

[nss]
filter_users = root,daemon,bin,sys,sync,games,man,lp,mail,news,uucp,proxy,nobody,systemd-network,systemd-resolve,dbus,polkitd,unbound,tss,sssd,chrony,sshd,rngd

[pam]
offline_credentials_expiration = 2

handlers/main.yml

  • vi ~/ansible/roles/sssd/handlers/main.yml
---
- name: sssd neu starten
  systemd:
    name: sssd
    state: restarted

- name: authselect anwenden
  command: authselect apply-changes

defaults/main.yml

Standardwerte – werden durch group_vars oder host_vars überschrieben
  • vi ~/ansible/roles/sssd/defaults/main.yml
---
domain: "it2XX.int"
dc1: "it2XX"
dc2: "int"
ldap_password: "123Start$"
Für den produktiven Einsatz
Passwort niemals im Klartext in defaults/main.yml – stattdessen mit ansible-vault verschlüsseln
  • ansible-vault encrypt_string '123Start$' --name 'ldap_password'

Playbook: DMZ ausrollen

Ein Playbook, das beide Rollen nacheinander ausführt – Tags erlauben es, sie einzeln zu testen
  • vi ~/ansible/dmz.yml
---
- name: DMZ-Server konfigurieren
  hosts: dmz
  roles:
    - { role: sssd, tags: ['sssd'] }
Zuerst nur SSSD ausrollen und testen
  • ansible-playbook ~/ansible/dmz.yml --tags sssd


Dry-run – zeigt was sich ändern würde, ohne es anzuwenden
  • ansible-playbook ~/ansible/dmz.yml --check

Kontrolle

SSSD auf einem Server prüfen
  • ansible ns.it2XX.int -m command -a "getent passwd thomas"
SSH-Konfiguration prüfen
  • ansible dmz -m command -a "grep PasswordAuthentication /etc/ssh/sshd_config"
nsswitch.conf prüfen – sudoers-Zeile muss sss enthalten
  • ansible dmz -m command -a "grep sudoers /etc/nsswitch.conf"
Alle Fakten eines Servers anzeigen – nützlich zur Fehlersuche
  • ansible ns.it2XX.int -m setup

Logs und Debugging

  • journalctl -fu sshd
  • ansible-playbook ~/ansible/dmz.yml -v
  • ansible-playbook ~/ansible/dmz.yml -vvv