Ansible mit Rocky: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
| Zeile 76: | Zeile 76: | ||
;Ein Playbook ist eine YAML-Datei, die Tasks in fester Reihenfolge auf einer Zielgruppe ausführt | ;Ein Playbook ist eine YAML-Datei, die Tasks in fester Reihenfolge auf einer Zielgruppe ausführt | ||
| − | ;Einfaches Beispiel – Paket installieren, läuft dank ansible_become automatisch mit sudo | + | ;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 | * vi ~/ansible/test.yml | ||
<syntaxhighlight lang="yaml"> | <syntaxhighlight lang="yaml"> | ||
| Zeile 83: | Zeile 83: | ||
hosts: dmz | hosts: dmz | ||
tasks: | tasks: | ||
| − | - name: | + | - name: htop installieren |
dnf: | dnf: | ||
| − | name: | + | name: htop |
state: present | state: present | ||
| + | |||
| + | - name: Testdatei mit Zeitstempel anlegen | ||
| + | copy: | ||
| + | content: "Ansible-Testlauf: {{ ansible_date_time.iso8601 }}\n" | ||
| + | dest: /tmp/ansible-test.txt | ||
| + | mode: '0644' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* ansible-playbook ~/ansible/test.yml | * 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 = | ||
Version vom 5. Juli 2026, 09:41 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: sudoers-Eintrag in nsswitch.conf setzen
lineinfile:
path: /etc/nsswitch.conf
regexp: '^sudoers:'
line: 'sudoers: files sss'
state: present
- name: authselect konfigurieren
command: authselect select sssd with-mkhomedir --force
changed_when: false
- 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
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'
Rolle: SSH-Härtung
- Diese Rolle schaltet Passwort-Authentifizierung ab – ERST nachdem die SSH-Keys für kit auf allen Zielsystemen verteilt wurden. Reihenfolge unbedingt einhalten, sonst sperrt man sich aus.
tasks/main.yml
- vi ~/ansible/roles/ssh-hardening/tasks/main.yml
---
- name: Passwort-Login deaktivieren
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication no'
state: present
notify: sshd neu starten
- name: Root-Login nur mit Key erlauben
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin prohibit-password'
state: present
notify: sshd neu starten
handlers/main.yml
- vi ~/ansible/roles/ssh-hardening/handlers/main.yml
---
- name: sshd neu starten
systemd:
name: sshd
state: restarted
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'] }
- { role: ssh-hardening, tags: ['ssh-hardening'] }
- Zuerst nur SSSD ausrollen und testen
- ansible-playbook ~/ansible/dmz.yml --tags sssd
- Danach SSH-Härtung – erst wenn SSSD und Keys sicher funktionieren
- ansible-playbook ~/ansible/dmz.yml --tags ssh-hardening
- Beide Rollen zusammen
- ansible-playbook ~/ansible/dmz.yml
- 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