Mach mich Wurzel
Ziel/Problem
Ich habe ein Ansible-Playbook welches ich beim Aufsetzen von Servern (oder auch anderen Maschinen) nutze.
Nutzt man ein Standard-Debian-Image legt man einen Nicht-Root-User bei der Installation an der sich per ssh einglogen kann.
Allerdings ist per Default kein sudo installiert und der Nicht-Root-Nutzer ist nicht in den sudoer-Dateien, kann also keine Befehle per sudo ausführen.
Man kann also nicht per ansible root-Befehle ausführen ohne ein Passwort hinterlegen/angeben zu müssen.
Ziel ist es das zu ändern:
-
Sicherstellen das sudo installiert ist
-
Festellen ob sudo (ohne Passwort) für den Nicht-Root-Nutzer funktioniert
-
ggf. ihn in die sudoers einzutragen
-
wenn notwendig interaktiv einmalig das root-Passwort abfragen
-
Lösung
Es muss ggf. das community.general-Modul nachinstalliert werden
ansible-galaxy -vv collection install community.general
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
- name: Checking/configure sudo
hosts: all
tasks:
- name: Test if sudo works - refreshing the apt cache
become: true
become_method: sudo
block:
- name: Refresh apt repo
ansible.builtin.apt:
update_cache: true
rescue:
- pause:
prompt: "Enter root password"
echo: no
register: prompt_data
- ansible.builtin.set_fact:
ansible_become_pass: "{{ prompt_data.user_input }}"
- name: Install sudo
become: true
become_method: su
ansible.builtin.apt:
update_cache: true
name: sudo
state: present
- name: Add login user to sudoers
become: true
become_method: su
community.general.sudoers:
commands: ALL
name: "{{ ansible_user }}_ALL"
user: "{{ ansible_user }}"
nopassword: true
Check-Check
In Zeile 4 beginnt ein Task der nur dazu dient festzustellen das per sudo ohne Passwort root-Rechte erlangt werden können.
- name: Test if sudo works - refreshing the apt cache
become: true
become_method: sudo
block:
- name: Refresh apt repo
ansible.builtin.apt:
update_cache: true
become_method: sudo versucht die höheren Rechte zu bekommen
Der eigentliche Task ist das auffrischen des apt-Caches, man könnte hier auch irgendetwas anderes ausführen.
Der block dient dazu weiter unten (Zeile 11) eine Fehlerbehandlung per rescue machen zu können.
To the Rescue
rescue:
- pause:
prompt: "Enter root password"
echo: no
register: prompt_data
Zeile 11 definiert per rescue Aktionen die ausgeführt werden wenn der block fehlschlägt.
Das wäre dann der Fall wenn entweder sudo nicht installiert ist oder der Nutzer keine sudo-Rechte hat oder kein sudo ohne Passwort ausführen kann (oder wenn apt update fehlschlagen würde).
Das wäre der else-Block einer if-else-Anweisung.
Mach mal Pause
- pause:
prompt: "Enter root password"
echo: no
register: prompt_data
Der Pause-Block unterbricht die Ausführung und fragt das root-Passwort ab.
-
prompt-Parameter führt zu einer Eingabeaufforderung für den Benutzer
-
echo: no verhindert das das eingegebene Passwort auf der Kommandozeile sichtbar wird
-
register: prompt_data speichert das Ergebnis des Modul-Aufrufs pause in der Variable prompt_data
📝
|
Module können mehr als einen Rückgabewert haben → siehe Dokumentation für Modul Sektion Return Values . Das pause-Modul z.B. gibt eine Reihe von Daten zurück. prompt_data enthält eine Hash-Map/Dictionary mit den Werten, u.a. user_input (die Benutzereingabe), delta (die Zeit die gewartet wurde) usw. |
Fakten schaffen
- ansible.builtin.set_fact:
ansible_become_pass: "{{ prompt_data.user_input }}"
Setzt die Variable ansible_become_pass auf den Inhalt von prompt_data.user_input .
prompt_data waren die Rückgabewerte des pause-Moduls und user_input ist der Index an dem sich die Benutzereingabe befindet aka. das eingegeben Passwort.
ansible_become_pass ist eine interne Variable die das Passwort enthält sollte sudo oder su eines verlangen, kann auch per ansible-playbook -k angegeben werden (wird dann interaktiv abgefragt).
Werkzeug zur Macht installieren
- name: Install sudo
become: true
become_method: su
ansible.builtin.apt:
update_cache: true
name: sudo
state: present
become_method wird explizit auf su gesetzt, da sudo möglicherweise nicht installiert ist.
Anschließend installiert ansible.builtin.apt sudo
Allmächtig werden
- name: Add login user to sudoers
become: true
become_method: su
community.general.sudoers:
commands: ALL
name: "{{ ansible_user }}_ALL"
user: "{{ ansible_user }}"
nopassword: true
become_method ist explizit auf su gesetzt, da der Benutzer wahrscheinlich noch keine sudo-Rechte hat und sudo damit fehlschlagen würde.
community.general.sudoers erzeugt in /etc/sudoers.d/ eine neue Datei mit den folgenden Parametern:
-
commands: ALL → der Benutzer kann per sudo alles ausführen, sudo ist also nicht auf bestimmte Programme/Befehle beschränkt
-
name: "{{ ansible_user }}_ALL" → Name der Datei.
-
ansible_user ist die Variable die den Namen des Login-Nutzers enthält
-
Datei würde dann also shellkraut_ALL heißen, wenn shellkraut der Login-User war
-
-
user: "{{ ansible_user }}" → Benutzer für den die Erlaubnis/Regel sein soll. Hier für den Login-Nutzer
-
nopassword: true → es wird kein Passwort abgefragt wenn sudo ausgeführt wird
In Summe hat der Nutzer sobald er eingelogt ist damit root-Rechte via sudo.