Angenommen, ein Kunde hat Sie gebeten, bei der Skriptmigration für die Bereitstellung einer zentralisierten Sudoers-Datei auf RHEL- und AIX-Servern zu helfen.

Nun, dies ist ein sehr häufiges Szenario, und anhand seines Beispiels können Sie die Verwendung der erweiterten Funktionen von Ansible sowie die Änderungen des Ansatzes demonstrieren - von einem Skript, das eine bestimmte Aufgabe ausführt, bis zu einer idempotenten Beschreibung (ohne Änderungen vorzunehmen) und der Überwachung der Einhaltung des Status der Instanz.
Nimm das Drehbuch:
Es gibt 212 Codezeilen ohne Versionskontrolle in der sudoers-Datei. Der Kunde hat bereits einen Prozess, der einmal pro Woche ausgeführt wird und die Prüfsumme der Datei überprüft, um die Sicherheit zu gewährleisten. Obwohl das Skript einen Verweis auf Solaris enthält, mussten wir diese Anforderung für diesen Kunden nicht übertragen.
Beginnen wir damit, eine Rolle zu erstellen und die sudoers-Datei zur Versionskontrolle in Git abzulegen. Auf diese Weise können wir unter anderem die Notwendigkeit beseitigen, NFS-Volumes bereitzustellen.
Mit den Parametern "validieren" und "sichern" für die
Kopier- und
Vorlagenmodule können wir das Schreiben von Code zum Sichern und Wiederherstellen der Datei vermeiden. In diesem Fall wird die Validierung durchgeführt, bevor die Datei am Zielpunkt abgelegt wird. Wenn die Validierung fehlschlägt, gibt das Modul einen Fehler aus.
Für jede Rolle müssen Aufgaben, Vorlagen und Variablen angegeben werden. Hier ist die Struktur der entsprechenden Datei:

Die
Rollenskriptdatei (Playbook)
sudoers.yml hat eine einfache Struktur:
---
##
# Role playbook
##
- hosts: all
roles:
- sudoers
...
Rollenvariablen befinden sich in der
Datei vars / main.yml . Diese Datei enthält die Prüfsummendatei und die Anweisungen include / exclude, mit denen eine spezielle Logik zum Überspringen der Lawson-Hosts erstellt und die Datei sudoers.d nur in die HD-Hosts aufgenommen wird.
Hier ist der Inhalt der
Datei vars / main.yml :
---
MD5FILE: /root/.sudoer.md5
EXCLUDE: la
INCLUDE: hd
...
Wenn wir die
Module copy und
lineinfile verwenden , ist die Rolle nicht idempotent. Das Kopiermodul installiert die Basisdatei und lineinfile fügt include bei jedem Start erneut ein. Da diese Rolle auf
Ansible Tower gestartet wird, ist Idempotenz ein Muss. Wir werden die Datei in eine jinja2-Vorlage konvertieren.
In der ersten Zeile fügen wir den folgenden Befehl hinzu,
um Leerzeichen und Einrückungen zu
steuern :
#jinja2: lstrip_blocks: True, trim_blocks: True
Beachten Sie, dass neuere Versionen des
Vorlagenmoduls Parameter für
trim_blocks enthalten (hinzugefügt in Ansible 2.4).
Hier ist der Code, der die
Include- Zeile am Ende der Datei einfügt:
{% if ansible_hostname[0:2] == INCLUDE %}
#includedir /etc/sudoers.d
{% endif %}
Wir verwenden das bedingte Konstrukt ({% if%}, {% endif%}) für den Shell-Befehl, der eine Zeile für Hosts einfügt, deren Namen mit den Zeichen "hd" beginnen. Wir verwenden Ansible-Fakten und einen Filter [0: 2], um den Hostnamen zu analysieren.
Kommen wir nun zu den Aufgaben. Zunächst müssen Sie eine Tatsache zum Parsen des Hostnamens festlegen. Wir werden die Tatsache "parhost" im bedingten Konstrukt verwenden.
---
##
# Parse hostnames to grab 1st 2 characters
##
- name: "Parse hostname's 1st 2 characters"
set_fact: parhost={{ ansible_hostname[0:2] }}
Auf dem RHEL-
Aktienserver gibt es keinen
csum- Parameter. Bei Bedarf können wir eine andere Tatsache verwenden, um den Namen der Binärdatei mit der Prüfsumme bedingt anzugeben. Bitte beachten Sie, dass möglicherweise zusätzlicher Code erforderlich ist, wenn sich diese Funktionen unter AIX, Solaris und Linux unterscheiden.
Außerdem müssen wir das Problem mit Unterschieden in den Stammgruppen unter AIX und RHEL beheben.
##
# Conditionally set name of checksum binary
##
- name: "set checksum binary"
set_fact:
csbin: "{{ 'cksum' if (ansible_distribution == 'RedHat') else 'csum' }}"
##
# Conditionally set name of root group
##
- name: "set system group"
set_fact:
sysgroup: "{{ 'root' if (ansible_distribution == 'RedHat') else 'sys' }}"
Durch die Verwendung von Blöcken können wir die Bedingung für die gesamte Aufgabe festlegen. Wir werden die Bedingung am Ende des Blocks verwenden, um "la" -Hosts auszuschließen.
##
# Enclose in block so we can use parhost to exclude hosts
##
- block:
Das Vorlagenmodul überprüft und installiert die Datei. Wir korrigieren das Ergebnis, damit wir feststellen können, ob sich die Aufgabe geändert hat. Mit dem Parameter validate in diesem Modul können Sie die Gültigkeit der neuen sudoer-Datei überprüfen, bevor Sie sie auf dem Host ablegen.
##
# Validate will prevent bad files, no need to revert
# Jinja2 template will add include line
##
- name: Ensure sudoers file
template:
src: sudoers.j2
dest: /etc/sudoers
owner: root
group: "{{ sysgroup }}"
mode: 0440
backup: yes
validate: /usr/sbin/visudo -cf %s
register: sudochg
Wenn eine neue Vorlage installiert wurde, führen Sie das Shell-Skript aus, um die Prüfsummendatei zu generieren. Das bedingte Konstrukt aktualisiert die Prüfsummendatei, wenn die sudoers-Vorlage installiert wird oder wenn die Prüfsummendatei fehlt. Da der laufende Prozess auch andere Dateien überwacht, verwenden wir den im Quellenskript bereitgestellten Shell-Code:
- name: sudoers checksum
shell: "grep -v '/etc/sudoers' {{ MD5FILE }} > {{ MD5FILE }}.tmp ; {{ csbin }} /etc/sudoers >> {{ MD5FILE }} ; mv {{ MD5FILE }}.tmp {{ MD5FILE }}"
when: sudochg.changed or MD5STAT.exists == false
Das Dateimodul überprüft die Installation der erforderlichen Berechtigungen:
- name: Ensure MD5FILE permissions
file:
path: "{{ MD5FILE }}"
owner: root
group: "{{ sysgroup }}"
mode: 0600
state: file
Da der Sicherungsparameter keine Optionen für die Verarbeitung früherer Sicherungen bietet, müssen wir uns darum kümmern, den entsprechenden Code selbst zu erstellen. Im folgenden Beispiel verwenden wir dazu den Parameter "register" und das Feld "stdout_lines".
##
# List and clean up backup files. Retain 3 copies.
##
- name: List /etc/sudoers.*~ files
shell: "ls -t /etc/sudoers*~ |tail -n +4"
register: LIST_SUDOERS
changed_when: false
- name: Cleanup /etc/sudoers.*~ files
file:
path: "{{ item }}"
state: absent
loop: "{{ LIST_SUDOERS.stdout_lines }}"
when: LIST_SUDOERS.stdout_lines != ""
Blockvervollständigung:
##
# This conditional restricts what hosts this block runs on
##
when: parhost != EXCLUDE
...
Der beabsichtigte Anwendungsfall besteht darin, diese Rolle auf Ansible Tower zu spielen. Ansible Tower-Warnungen können so konfiguriert werden, dass im Falle eines Fehlers bei der Jobausführung Warnungen an E-Mail, an Slack oder auf andere Weise gesendet werden. Diese Rolle wird in Ansible, Ansible Engine oder Ansible Tower ausgeführt.
Infolgedessen haben wir alles Überflüssige aus dem Skript entfernt und eine vollständig idempotente Rolle erstellt, die den gewünschten Status der sudoers-Datei bereitstellen kann. Die Verwendung von SCM ermöglicht die Versionskontrolle, bietet ein effizienteres Änderungsmanagement und Transparenz. Mit CI / CDs mit Jenkins oder anderen Tools können Sie automatisierte Tests von Ansible-Code für zukünftige Änderungen einrichten. Mit der Auditor-Rolle in Ansible Tower können Sie organisatorische Anforderungen überwachen und durchsetzen.
Der Code für die Arbeit mit Prüfsummen könnte aus dem Skript entfernt werden. Dazu müsste der Kunde jedoch zuerst seinen Sicherheitsdienst konsultieren. Bei Bedarf kann das Sudoers-Muster mit Ansible Vault geschützt werden. Schließlich wird durch die Verwendung von Gruppen das Schreiben von Logik mithilfe von Ein- und Ausschlüssen vermieden.
→ Sie können die Rolle von GitHub unter diesem
Link herunterladen