Ansible ist ein Open-Source-Softwarebereitstellungs-, Konfigurationsverwaltungs- und Anwendungsbereitstellungstool, das eine Infrastruktur als Code ermöglicht. Es läuft auf vielen Unix-ähnlichen Systemen und kann sowohl Unix-ähnliche Systeme als auch Microsoft Windows konfigurieren.
Voraussetzungen
Um dieser Anleitung zu folgen, benötigen Sie Folgendes:
- Python im lokalen System installiert
- Python Pip installiert
- Ansible lokal installiert
Schritte
- Installieren Sie Abhängigkeiten
- Generieren Sie das Passwort mit dem passlib-Paket
- Erstellen Sie das ansible Playbook, das die erforderlichen Aufgaben definiert
- Das ganze Playbook
1. Abhängigkeiten installieren
Damit das funktioniert, brauchen wir ansible und das passlib-Paket.
Installieren Sie das ansible passlib-Paket:
sudo pip install passlib
Ansible installieren
sudo pip install ansible
2. Generieren Sie das Passwort mit dem passlib-Paket
Ansible fügt das Passwort unverändert für den Benutzer hinzu. Das Passwort ist verschlüsselt, daher funktioniert das Standardpasswort nicht.
Holen Sie sich das verschlüsselte Passwort mit diesem Befehl:
python -c "from passlib.hash import sha512_crypt; import getpass; print(sha512_crypt.using(rounds=5000).hash(getpass.getpass()))"
Ausgabe:
➜ python -c "from passlib.hash import sha512_crypt; import getpass; print(sha512_crypt.using(rounds=5000).hash(getpass.getpass()))"
Password:
$6$8IAGh7Gu2ugAB.sF$zHldDAEBMoiFUPq2RsGpQ.TRwbPOz3/S5ATs5TbfWDLypYjLGfKN8SNxu1Sx5nNfzQgDJqBh37jT9ln7EIHcq0
3. Erstellen Sie das ansible Playbook, das die erforderlichen Aufgaben definiert
Nachdem nun alle Abhängigkeiten installiert sind, können wir unser Playbook definieren.
Zuerst müssen Sie den Namen, die Hosts und zusätzliche Informationen wie Variablen definieren:
- name: Create user on a linux server
hosts: remote-server
become: yes
gather_facts: false
vars:
- user: <username here>
- password: <Password hash generated>
Der nächste Abschnitt ist für Aufgaben.
Ansible-Aufgabe zum Erstellen eines Linux-Benutzers
Da wir einen Benutzer erstellen möchten, verwenden wir den ansiblen user
Modul. Weitere Informationen zum Benutzermodul finden Sie hier.
Diese Aufgabe erstellt einen Benutzer mit dem angegebenen name
und password
die aus den zuvor definierten Variablen interpoliert wird:
- name: Create a login user
user:
name: "{{ user }}"
password: "{{ password }}"
groups:
- wheel
state: present
Optional:Ansible-Aufgabe zum Hinzufügen des öffentlichen Schlüssels zu den authorisierten_Schlüsseln für den Benutzer
Um eine passwortlose Anmeldung am Server zu ermöglichen, können wir unseren öffentlichen SSH-Schlüssel zu den autorisierten Schlüsseln auf dem Server hinzufügen. Um dies zu erreichen, wird das Modul ansible authored_key verwendet.
- name: Add public key to authorized_keys
authorized_key:
user: "{{ user }}"
state: present
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
Optional:Ansible-Task zum Verweigern des Root-SSH-Zugriffs
Der nächste Schritt besteht darin, die Root-Anmeldung über ssh zu verweigern. Es hat sich bewährt, Benutzern ohne Rootberechtigung die Anmeldung zu gestatten. Wir verwenden die lineinfile
Modul, das sicherstellt, dass eine bestimmte Zeile in der angegebenen Datei vorhanden ist. Wir verwenden einen regulären Ausdruck, um die Zeile abzugleichen.
- name: Deny root from logging in
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^(#)?PermitRootLogin \w*$'
line: 'PermitRootLogin no'
state: present
Optional:Ansible-Aufgabe zum Hinzufügen eines Benutzers zur Liste der zulässigen Benutzer
Eine gute Sicherheitspraxis besteht darin, nur bestimmten Benutzern die Anmeldung beim System zu gestatten. Diese Aufgabe erledigt das.
- name: Allow specific users to log in
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^AllowUsers'
line: 'AllowUsers {{ user }}'
state: present
Optional:Benutzer zur sudoers-Datei hinzufügen, damit sie sudo-Befehle ausführen können:
Wenn Sie möchten, dass der erstellte Benutzer den sudo-Befehl ohne Passwortabfrage ausführt, schließen Sie diese Aufgabe ein.
Hier verwenden wir die lineinfile
Modul, um einen regulären Ausdruck zu suchen, der mit dem Benutzer übereinstimmt, und dann mit dem Befehl visudo -cf %s
überprüft, ob alles wie erwartet funktioniert :
- name: Add {{ user }} to sudoers file
ansible.builtin.lineinfile:
path: /etc/sudoers
regexp: '^{{ user }}'
line: '{{ user }} ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
4. Das ganze Playbook
So wird das gesamte Playbook aussehen. Speichern Sie diesen Inhalt in einer .yaml
oder .yml
Datei. In meinem Fall create-user.yaml
:
---
- name: Create user on a linux server
hosts: remote-server
become: yes
gather_facts: false
vars:
- user: user1
- password: $6$8IAGh7Gu2ugAB.sF$zHldDAEBMoiFUPq2RsGpQ.TRwbPOz3/S5ATs5TbfWDLypYjLGfKN8SNxu1Sx5nNfzQgDJqBh37jT9ln7EIHcq0
tasks:
- name: Create a login user
user:
name: "{{ user }}"
password: "{{ password }}"
groups:
- wheel
state: present
- name: Add public key to authorized_keys
authorized_key:
user: "{{ user }}"
state: present
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
- name: Deny root from logging in
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^(#)?PermitRootLogin \w*$'
line: 'PermitRootLogin no'
state: present
- name: Allow specific users to log in
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^AllowUsers'
line: 'AllowUsers {{ user }}'
state: present
- name: Add {{ user }} to sudoers file
ansible.builtin.lineinfile:
path: /etc/sudoers
regexp: '^{{ user }}'
line: '{{ user }} ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
5. Playbook ausführen
Jetzt haben wir das Playbook in der Datei create-user.yaml
erstellt Im aktuellen Verzeichnis müssen wir eine hosts-Datei bereitstellen, die die Verbindung zu unserem Server definiert. Aus der Playbook-Definition definieren wir unseren Server als remote-server
. Jetzt fügen wir das der hosts-Datei hinzu.
Erstellen Sie eine Datei hosts.yaml
mit folgendem Inhalt, der den remote-server
definiert :
all:
hosts:
remote-server:
ansible_ssh_host: 138.68.150.24
ansible_ssh_user: root
Jetzt müssen wir das ansible-playbook
aufrufen Befehl wie folgt:
ansible-playbook -i hosts.yaml create-user.yaml -vv
Im obigen Befehl ist das -i
gibt die Inventardatei an. Das -vv
aktiviert Ausführlichkeit.
Dies ist die Ausgabe von meinem Server:
➜ ansible-playbook -i hosts.yaml create-user.yaml -vv
ansible-playbook [core 2.11.1]
config file = None
configured module search path = ['/Users/citizix/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
ansible collection location = /Users/citizix/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible-playbook
python version = 3.9.5 (default, May 4 2021, 03:36:27) [Clang 12.0.0 (clang-1200.0.32.29)]
jinja version = 2.11.3
libyaml = False
No config file found; using defaults
redirecting (type: modules) ansible.builtin.authorized_key to ansible.posix.authorized_key
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
PLAYBOOK: create-user.yaml *********************************************************************************************************************************************************************************
1 plays in create-user.yaml
PLAY [Create user on a linux server] ***********************************************************************************************************************************************************************
META: ran handlers
TASK [Create a login user] *********************************************************************************************************************************************************************************
task path: /Users/citizix/projects/ansible/create-user.yaml:9
changed: [remote-server] => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "changed": true, "comment": "", "create_home": true, "group": 1000, "groups": "wheel", "home": "/home/rocky", "name": "rocky", "password": "NOT_LOGGING_PASSWORD", "shell": "/bin/bash", "state": "present", "system": false, "uid": 1000}
TASK [Add public key to authorized_keys] *******************************************************************************************************************************************************************
task path: /Users/citizix/projects/ansible/create-user.yaml:17
redirecting (type: modules) ansible.builtin.authorized_key to ansible.posix.authorized_key
changed: [remote-server] => {"changed": true, "comment": null, "exclusive": false, "follow": false, "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC6gM14zM0+L+ERQFVFYbHBAjtyghKKx/N+qsFXxrcJqVqsyn1lp/erPqg3g6WSu/bwiAB+E22RyG9icS7Td8ssWi9vDE73DHgC5NGLm4KeP2FospEFjY6v8XVjkwQZJ+8YyCfXJ4E5cm0FGKZREakDlYeaonTaIjxkXlsZB3Yl93+KZvZ0g1WiBOU6N6NWpEQVvxYccWK4+EuQiCryELL0o4dCNrwLaYOyv/NbSYQ09m3+mvN0VRnTzo7qSOqy1U6oCVA9bhd+tRyoUsUqp3Up8jdfzEGfWr/Pqskjtl8YXySPHLEROXX/Om4AyT62EQxcPMzedPJ6HGLHnlk4EO9cBLawymdWO7AlghujksVBu9S+alOkAmJkkPzeq76WOjCTmoNxlQmEDlucukiujfWKl4hACdNVtARptvuc5+4uMYA4j4Ql+XtQ964UQa4HiGiNpoiDegzDq9GMEsQW4W5frRuOIm4R7thYGatRBkNFw+uemE5HclF8LXOuPkShhFqpDPgI1oH99covroXggV8/ovEf9ZSoshNLMHX5kXWGAWF983Cn2N5RpmqN8rfcGVq6C93njExvHDfl7bHkhT10axOLV/V4vX4lSktWVV4//vq2wMQLi5F1l7ai8scA3eYeSaWnDaJj2jnz6V5JBOPIOH/3lf7qq4oquZhmuWq3w== citizix", "key_options": null, "keyfile": "/home/rocky/.ssh/authorized_keys", "manage_dir": true, "path": null, "state": "present", "user": "rocky", "validate_certs": true}
TASK [Deny root from logging in] ***************************************************************************************************************************************************************************
task path: /Users/citizix/projects/ansible/create-user.yaml:23
changed: [remote-server] => {"backup": "", "changed": true, "msg": "line replaced"}
TASK [Allow specific users to log in] **********************************************************************************************************************************************************************
task path: /Users/citizix/projects/ansible/create-user.yaml:30
changed: [remote-server] => {"backup": "", "changed": true, "msg": "line added"}
TASK [Add my pub key to authorized_keys] *******************************************************************************************************************************************************************
task path: /Users/citizix/projects/ansible/create-user.yaml:37
ok: [remote-server] => {"changed": false, "comment": null, "exclusive": false, "follow": false, "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC6gM14zM0+L+ERQFVFYbHBAjcsTGZKKx/N+qsFXxrcJqVqsyn1lp/erPqg3g6WSu/bwiAB+E22RyG9icS7Td8ssWi9vDE73DHgC5NGLm4KeP2FospEFjY6v8XVjkwQZJ+8YyCfXJ4E5cm0FGKZREakDlYeaonTaIjxkXlsZB3Yl93+KZvZ0g1WiBOU6N6NWpEQVvxYccWK4+EuQiCryELL0o4dCNrwLaYOyv/NbSYQ09m3+mvN0VRnTzo7qSOqy1U6oCVA9bhd+tRyoUsUqp3Up8jdfzEGfWr/Pqskjtl8YXySPHLEROXX/Om4AyT62EQxcPMzedPJ6HGLHnlk4EO9cBLawymdWO7AlghujksVBu9S+alOkAmJkkPzeq76WOjCTmoNxlQmEDlucukiujfWKl4hACdNVtARptvuc5+4uMYA4j4Ql+XtQ964UQa4HiGiNpoiDegzDq9GMEsQW4W5frRuOIm4R7thYGatRBkNFw+uemE5HclF8LXOuPkShhFqpDPgI1oH99covroXggV8/ovEf9ZSoshNLMHX5kXWGAWF983Cn2N5RpmqN8rfcGVq6C93njExvHDfl7bHkhT10axOLV/V4vX4lSktWVV4//vq2wMQLi5F1l7ai8scA3eYeSaWnDaJj2jnz6V5JBOPIOH/3lf7qq4oquZhmuWq3w== [email protected]", "key_options": null, "keyfile": "/home/rocky/.ssh/authorized_keys", "manage_dir": true, "path": null, "state": "present", "user": "rocky", "validate_certs": true}
TASK [Add rocky to sudoers file] ***************************************************************************************************************************************************************************
task path: /Users/citizix/projects/ansible/create-user.yaml:43
changed: [remote-server] => {"backup": "", "changed": true, "msg": "line replaced"}
META: ran handlers
META: ran handlers
PLAY RECAP *************************************************************************************************************************************************************************************************
remote-server : ok=6 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0