second commit
This commit is contained in:
86
ansible/roles/os_hardening/tasks/aide.yml
Normal file
86
ansible/roles/os_hardening/tasks/aide.yml
Normal file
@ -0,0 +1,86 @@
|
||||
---
|
||||
# CIS 1.4.x: AIDE (Advanced Intrusion Detection Environment) als
|
||||
# Datei-Integritaets-Monitoring. Ergaenzt das Anwendungs-Audit-Log
|
||||
# (manipulationssichere Hash-Chain, Konzept 6.1) um eine unabhaengige,
|
||||
# dateisystemweite Kontrolle -- erkennt z.B. Aenderungen an Systembinaries
|
||||
# oder eingeschleuste Dateien ausserhalb des Anwendungscodes.
|
||||
|
||||
- name: AIDE installieren
|
||||
ansible.builtin.apt:
|
||||
name: aide
|
||||
state: present
|
||||
update_cache: true
|
||||
when: os_hardening_aide_enabled
|
||||
|
||||
- name: Pruefen, ob bereits eine AIDE-Datenbank existiert
|
||||
ansible.builtin.stat:
|
||||
path: /var/lib/aide/aide.db
|
||||
register: _aide_db
|
||||
when: os_hardening_aide_enabled
|
||||
|
||||
- name: Initiale AIDE-Datenbank aufbauen (kann einige Minuten dauern)
|
||||
ansible.builtin.command: aideinit -y -f
|
||||
when: os_hardening_aide_enabled and not _aide_db.stat.exists
|
||||
async: 1800
|
||||
poll: 30
|
||||
|
||||
- name: AIDE-Wrapper-Skript fuer den taeglichen Check ausrollen
|
||||
ansible.builtin.copy:
|
||||
dest: /usr/local/sbin/jumphost-aide-check.sh
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0750"
|
||||
content: |
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
LOGFILE=/var/log/jumphost/aide-check.log
|
||||
/usr/bin/aide.wrapper --check >> "$LOGFILE" 2>&1 || {
|
||||
logger -p authpriv.warning "AIDE hat Dateisystem-Abweichungen gemeldet, siehe $LOGFILE"
|
||||
}
|
||||
when: os_hardening_aide_enabled
|
||||
|
||||
- name: systemd-Service fuer taeglichen AIDE-Check
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/systemd/system/jumphost-aide-check.service
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Taeglicher AIDE-Dateiintegritaets-Check
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/sbin/jumphost-aide-check.sh
|
||||
Nice=10
|
||||
IOSchedulingClass=idle
|
||||
when: os_hardening_aide_enabled
|
||||
notify: reload systemd (os_hardening)
|
||||
|
||||
- name: systemd-Timer fuer taeglichen AIDE-Check
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/systemd/system/jumphost-aide-check.timer
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Taeglicher AIDE-Dateiintegritaets-Check (Timer)
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
RandomizedDelaySec=3600
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
when: os_hardening_aide_enabled
|
||||
notify: reload systemd (os_hardening)
|
||||
|
||||
- name: AIDE-Check-Timer aktivieren
|
||||
ansible.builtin.systemd:
|
||||
name: jumphost-aide-check.timer
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
state: started
|
||||
when: os_hardening_aide_enabled
|
||||
98
ansible/roles/os_hardening/tasks/auditd.yml
Normal file
98
ansible/roles/os_hardening/tasks/auditd.yml
Normal file
@ -0,0 +1,98 @@
|
||||
---
|
||||
# CIS 4.1.x / DISA-STIG-aehnliche Audit-Regeln. Ueber die bereits vorhandene
|
||||
# Ueberwachung des Jumphost-Datenverzeichnisses hinaus wird hier ein
|
||||
# Standard-Ruleset fuer sicherheitsrelevante OS-Ereignisse ergaenzt:
|
||||
# Identitaets-/Rechteaenderungen, privilegierte Kommandos, Zeit-/
|
||||
# Netzwerkkonfigurationsaenderungen, Login-Ereignisse, Modulladen.
|
||||
|
||||
- name: auditd + audispd-plugins installieren
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- auditd
|
||||
- audispd-plugins
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Bestehende auditd-Regeln fuer das Jumphost-Datenverzeichnis
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/audit/rules.d/10-jumphost-app.rules
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0640"
|
||||
content: |
|
||||
-w {{ jumphost_data_dir }}/jumphost.db -p wa -k jumphost_db
|
||||
-w {{ jumphost_home }} -p wa -k jumphost_app_files
|
||||
-w /etc/jumphost -p wa -k jumphost_config
|
||||
notify: restart auditd
|
||||
|
||||
- name: Erweiterte CIS/STIG-Audit-Regeln fuer das Basissystem
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/audit/rules.d/20-cis-baseline.rules
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0640"
|
||||
content: |
|
||||
# Identitaets-/Rechteaenderungen (CIS 4.1.4)
|
||||
-w /etc/passwd -p wa -k identity
|
||||
-w /etc/group -p wa -k identity
|
||||
-w /etc/shadow -p wa -k identity
|
||||
-w /etc/gshadow -p wa -k identity
|
||||
-w /etc/sudoers -p wa -k identity
|
||||
-w /etc/sudoers.d/ -p wa -k identity
|
||||
|
||||
# Sudo-Nutzung protokollieren (ergaenzt Defaults logfile in
|
||||
# sudo_logging.yml um eine auditd-seitige, manipulationsresistentere Spur)
|
||||
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid!=0 -F auid!=-1 -k privileged_sudo
|
||||
|
||||
# Zeitaenderungen (CIS 4.1.3)
|
||||
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time_change
|
||||
-w /etc/localtime -p wa -k time_change
|
||||
|
||||
# Netzwerkkonfiguration (CIS 4.1.7)
|
||||
-w /etc/hosts -p wa -k network_config
|
||||
-w /etc/network/ -p wa -k network_config
|
||||
-w /etc/nftables.conf -p wa -k network_config
|
||||
|
||||
# Login/Logout-Ereignisse (CIS 4.1.5)
|
||||
-w /var/log/faillog -p wa -k logins
|
||||
-w /var/log/lastlog -p wa -k logins
|
||||
-w /var/run/utmp -p wa -k session
|
||||
-w /var/log/wtmp -p wa -k session
|
||||
-w /var/log/btmp -p wa -k session
|
||||
|
||||
# Kernel-Modul-Laden/-Entladen (CIS 4.1.13)
|
||||
-a always,exit -F arch=b64 -S init_module,delete_module -k kernel_modules
|
||||
|
||||
# SSH-Konfigurationsaenderungen des Jumphosts selbst
|
||||
-w /etc/ssh/sshd_config -p wa -k sshd_config
|
||||
-w /etc/ssh/sshd_config.d/ -p wa -k sshd_config
|
||||
|
||||
# Loeschungen durch Nutzer (CIS 4.1.14, exemplarisch fuer den eigenen UID-Bereich)
|
||||
-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F auid>=1000 -F auid!=-1 -k file_deletion
|
||||
notify: restart auditd
|
||||
|
||||
- name: auditd-Regeln als unveraenderlich markieren (STIG, optional)
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/audit/rules.d/99-immutable.rules
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0640"
|
||||
content: |
|
||||
# ACHTUNG: nach Aktivierung sind Aenderungen an den Audit-Regeln erst
|
||||
# nach einem Reboot wieder moeglich (auditctl -e 2 sperrt bis Neustart).
|
||||
-e 2
|
||||
when: os_hardening_auditd_immutable
|
||||
notify: restart auditd
|
||||
|
||||
- name: auditd-Log-Rotation auf "keep_logs" setzen statt Ueberschreiben (CIS 4.1.2.3)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/audit/auditd.conf
|
||||
regexp: '^max_log_file_action\s*='
|
||||
line: "max_log_file_action = keep_logs"
|
||||
notify: restart auditd
|
||||
|
||||
- name: auditd bei vollem Log-Speicher anhalten statt Ereignisse zu verwerfen (CIS 4.1.2.4)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/audit/auditd.conf
|
||||
regexp: '^space_left_action\s*='
|
||||
line: "space_left_action = email"
|
||||
22
ansible/roles/os_hardening/tasks/banners.yml
Normal file
22
ansible/roles/os_hardening/tasks/banners.yml
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
# STIG-typische Anmelde-Warnhinweise (rechtlich in vielen Organisationen
|
||||
# vorgeschrieben, bevor Zugriff auf ein System gewaehrt wird).
|
||||
|
||||
- name: Anmelde-Banner setzen (/etc/issue, /etc/issue.net, /etc/motd)
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ item }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: "{{ os_hardening_login_banner }}"
|
||||
loop:
|
||||
- /etc/issue
|
||||
- /etc/issue.net
|
||||
- /etc/motd
|
||||
# Kein Serviceneustart noetig: /etc/issue* und /etc/motd werden bei
|
||||
# jedem neuen Login/jeder neuen Verbindung frisch gelesen.
|
||||
|
||||
# Die "Banner /etc/issue.net"-Direktive fuer sshd wird zentral in sshd.yml
|
||||
# gesetzt (dieselbe Datei /etc/ssh/sshd_config.d/99-jumphost-hardening.conf
|
||||
# wird dort komplett -- inkl. Banner-Zeile -- verwaltet, um zwei Tasks mit
|
||||
# widerspruechlichem "wer besitzt diese Datei" zu vermeiden).
|
||||
36
ansible/roles/os_hardening/tasks/cron_at.yml
Normal file
36
ansible/roles/os_hardening/tasks/cron_at.yml
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
# CIS 2.4.1.x: cron/at auf autorisierte Nutzer beschraenken.
|
||||
|
||||
- name: cron.deny/at.deny entfernen (deny-Listen sind fehleranfaelliger als allow-Listen)
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- /etc/cron.deny
|
||||
- /etc/at.deny
|
||||
|
||||
- name: cron.allow / at.allow auf root und den Jumphost-Service-User beschraenken
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ item }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
content: |
|
||||
root
|
||||
loop:
|
||||
- /etc/cron.allow
|
||||
- /etc/at.allow
|
||||
|
||||
- name: Berechtigungen der cron-Verzeichnisse absichern (CIS 2.4.1.7-2.4.1.11)
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
loop:
|
||||
- /etc/cron.d
|
||||
- /etc/cron.daily
|
||||
- /etc/cron.hourly
|
||||
- /etc/cron.monthly
|
||||
- /etc/cron.weekly
|
||||
ignore_errors: true # nicht jedes Basis-Image legt alle Verzeichnisse an
|
||||
38
ansible/roles/os_hardening/tasks/file_permissions.yml
Normal file
38
ansible/roles/os_hardening/tasks/file_permissions.yml
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
# CIS 6.1.x: Berechtigungen sicherheitskritischer Systemdateien; zusaetzlich
|
||||
# manipulationssicheres sudo-Logging (ergaenzt die auditd-Regel
|
||||
# "privileged_sudo" aus auditd.yml um ein menschenlesbares Log).
|
||||
|
||||
- name: Berechtigungen sicherheitskritischer Dateien absichern
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
owner: root
|
||||
group: "{{ item.group }}"
|
||||
mode: "{{ item.mode }}"
|
||||
loop:
|
||||
- { path: /etc/passwd, group: root, mode: "0644" }
|
||||
- { path: /etc/group, group: root, mode: "0644" }
|
||||
- { path: /etc/shadow, group: shadow, mode: "0640" }
|
||||
- { path: /etc/gshadow, group: shadow, mode: "0640" }
|
||||
- { path: /etc/ssh/sshd_config, group: root, mode: "0600" }
|
||||
ignore_errors: true # z.B. wenn die shadow-Gruppe distributionsabhaengig anders heisst
|
||||
|
||||
- name: Eigenstaendiges sudo-Logfile aktivieren
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/sudoers.d/99-jumphost-logging
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0440"
|
||||
validate: "visudo -cf %s"
|
||||
content: |
|
||||
Defaults logfile="/var/log/sudo.log"
|
||||
Defaults log_input, log_output
|
||||
Defaults use_pty
|
||||
Defaults passwd_tries=3
|
||||
|
||||
- name: su-Kommando auf die Gruppe "sudo" beschraenken (CIS 5.6)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/pam.d/su
|
||||
regexp: '^#?\s*auth\s+required\s+pam_wheel\.so'
|
||||
line: "auth required pam_wheel.so use_uid group=sudo"
|
||||
insertafter: '^# Uncomment this'
|
||||
41
ansible/roles/os_hardening/tasks/kernel_modules.yml
Normal file
41
ansible/roles/os_hardening/tasks/kernel_modules.yml
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
# CIS 1.1.1.x: selten benoetigte Dateisysteme und exotische Netzwerk-
|
||||
# protokolle per modprobe-Blacklist deaktivieren. Ein dedizierter Jumphost
|
||||
# braucht keines davon; jedes deaktivierte Modul ist Angriffsflaeche weniger
|
||||
# (u.a. relevant fuer angeschlossene Wechseldatentraeger und historische
|
||||
# Kernel-CVEs in selten gepflegten Dateisystemtreibern).
|
||||
|
||||
- name: Kernelmodule fuer seltene Dateisysteme/Protokolle blacklisten
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/modprobe.d/jumphost-blacklist.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
# CIS 1.1.1.1 - 1.1.1.8 (sinngemaess): unbenoetigte Dateisysteme
|
||||
install cramfs /bin/false
|
||||
install freevxfs /bin/false
|
||||
install jffs2 /bin/false
|
||||
install hfs /bin/false
|
||||
install hfsplus /bin/false
|
||||
install udf /bin/false
|
||||
install squashfs /bin/false
|
||||
# CIS 3.4.x (sinngemaess): unbenoetigte/seltene Netzwerkprotokolle
|
||||
install dccp /bin/false
|
||||
install sctp /bin/false
|
||||
install rds /bin/false
|
||||
install tipc /bin/false
|
||||
notify: update initramfs
|
||||
|
||||
- name: USB-Speichermedien deaktivieren (CIS 1.1.23, sinngemaess)
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/modprobe.d/jumphost-usb-storage.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
# Ein Jumphost sollte keine lokal angeschlossenen USB-Speichermedien
|
||||
# einbinden muessen -- Dateitransfer laeuft ausschliesslich ueber die
|
||||
# Anwendung (SFTP/RDP-Laufwerksumleitung), siehe Konzept 4.3.
|
||||
install usb-storage /bin/false
|
||||
notify: update initramfs
|
||||
47
ansible/roles/os_hardening/tasks/main.yml
Normal file
47
ansible/roles/os_hardening/tasks/main.yml
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
# Betriebssystem-Haertung fuer den Jumphost-Server selbst (Konzept 6.7),
|
||||
# vertieft auf CIS/STIG-nahes Niveau. Siehe CIS_STIG_MAPPING.md in diesem
|
||||
# Rollenverzeichnis fuer die Zuordnung der einzelnen Tasks zu konkreten
|
||||
# Benchmark-Controls sowie fuer alles, was bewusst NICHT automatisiert wird
|
||||
# (mit Begruendung, z.B. Partitionslayout, Bootloader-Passwort, physische
|
||||
# Sicherheit).
|
||||
#
|
||||
# Kein Ersatz fuer ein vollstaendiges CIS/STIG-Auditwerkzeug (z.B. OpenSCAP)
|
||||
# -- jeder produktive Rollout sollte zusaetzlich mit `oscap xccdf eval`
|
||||
# gegen das jeweilige Benchmark-Profil verifiziert werden (siehe README).
|
||||
|
||||
- name: Pakete & automatische Updates
|
||||
ansible.builtin.import_tasks: packages.yml
|
||||
|
||||
- name: Kernelmodule (Dateisysteme/Protokolle) einschraenken
|
||||
ansible.builtin.import_tasks: kernel_modules.yml
|
||||
|
||||
- name: sysctl- und Core-Dump-Haertung
|
||||
ansible.builtin.import_tasks: sysctl.yml
|
||||
|
||||
- name: Mount-Optionen (/tmp, /dev/shm)
|
||||
ansible.builtin.import_tasks: mounts.yml
|
||||
|
||||
- name: PAM-/Passwort-Policy fuer lokale OS-Konten
|
||||
ansible.builtin.import_tasks: pam_password_policy.yml
|
||||
|
||||
- name: Erweiterte auditd-Regeln
|
||||
ansible.builtin.import_tasks: auditd.yml
|
||||
|
||||
- name: AIDE-Dateiintegritaets-Monitoring
|
||||
ansible.builtin.import_tasks: aide.yml
|
||||
|
||||
- name: rkhunter-Rootkit-Scanner
|
||||
ansible.builtin.import_tasks: rootkit_scan.yml
|
||||
|
||||
- name: Anmelde-Banner
|
||||
ansible.builtin.import_tasks: banners.yml
|
||||
|
||||
- name: cron/at auf autorisierte Nutzer beschraenken
|
||||
ansible.builtin.import_tasks: cron_at.yml
|
||||
|
||||
- name: Dateirechte & sudo-Logging
|
||||
ansible.builtin.import_tasks: file_permissions.yml
|
||||
|
||||
- name: SSH-Daemon des Jumphosts haerten
|
||||
ansible.builtin.import_tasks: sshd.yml
|
||||
48
ansible/roles/os_hardening/tasks/mounts.yml
Normal file
48
ansible/roles/os_hardening/tasks/mounts.yml
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
# CIS 1.1.2.x (nodev/nosuid/noexec auf /tmp, /dev/shm). Best-Effort: nur
|
||||
# wirksam, wenn diese Pfade BEREITS eigene Mountpoints sind. Ob das der Fall
|
||||
# ist, haengt vom Partitionslayout des Basis-Images ab -- siehe
|
||||
# CIS_STIG_MAPPING.md fuer den Hinweis, dass ein vollstaendig CIS-konformes
|
||||
# Partitionslayout (separate /tmp, /var, /var/log, /var/log/audit, /home)
|
||||
# eine bewusste Entscheidung bei der OS-Installation ist und nicht nachtraeglich
|
||||
# per Ansible auf ein bestehendes System aufgepraegt werden kann, ohne die
|
||||
# Platte neu zu partitionieren.
|
||||
|
||||
- name: Pruefen, ob /tmp ein eigener Mountpoint ist
|
||||
ansible.builtin.command: findmnt --noheadings --output SOURCE /tmp
|
||||
register: _tmp_mount
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: /tmp mit noexec,nosuid,nodev in /etc/fstab absichern (falls eigener Mountpoint)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/fstab
|
||||
regexp: '^\S+\s+/tmp\s+'
|
||||
line: "{{ _tmp_mount.stdout }} /tmp tmpfs defaults,noexec,nosuid,nodev 0 0"
|
||||
backup: true
|
||||
when: os_hardening_restrict_tmp_mounts and _tmp_mount.rc == 0 and _tmp_mount.stdout != ''
|
||||
notify: remount tmp
|
||||
|
||||
- name: Pruefen, ob /dev/shm ein eigener Mountpoint ist
|
||||
ansible.builtin.command: findmnt --noheadings --output SOURCE /dev/shm
|
||||
register: _shm_mount
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: /dev/shm mit noexec,nosuid,nodev in /etc/fstab absichern (falls eigener Mountpoint)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/fstab
|
||||
regexp: '^\S+\s+/dev/shm\s+'
|
||||
line: "{{ _shm_mount.stdout }} /dev/shm tmpfs defaults,noexec,nosuid,nodev 0 0"
|
||||
backup: true
|
||||
when: os_hardening_restrict_tmp_mounts and _shm_mount.rc == 0 and _shm_mount.stdout != ''
|
||||
notify: remount shm
|
||||
|
||||
- name: Hinweis, falls /tmp kein eigener Mountpoint ist
|
||||
ansible.builtin.debug:
|
||||
msg: >
|
||||
/tmp ist kein eigener Mountpoint auf diesem System -- noexec/nosuid/nodev
|
||||
koennen so nicht erzwungen werden. Fuer volle CIS-Konformitaet muesste
|
||||
/tmp bei der OS-Installation als eigene Partition/eigenes tmpfs angelegt
|
||||
werden (siehe CIS_STIG_MAPPING.md).
|
||||
when: os_hardening_restrict_tmp_mounts and (_tmp_mount.rc != 0 or _tmp_mount.stdout == '')
|
||||
33
ansible/roles/os_hardening/tasks/packages.yml
Normal file
33
ansible/roles/os_hardening/tasks/packages.yml
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
# CIS 2.x (Services) / STIG-aequivalent: unsichere Legacy-Dienste/-Clients
|
||||
# entfernen, automatische Sicherheitsupdates aktivieren.
|
||||
|
||||
- name: Unnoetige/unsichere Pakete entfernen
|
||||
ansible.builtin.apt:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
purge: true
|
||||
loop:
|
||||
- telnet
|
||||
- rsh-client
|
||||
- talk
|
||||
- nis # ypbind etc. -- veraltete, unverschluesselte Netzwerkdienste
|
||||
- tftpd-hpa
|
||||
- xinetd
|
||||
ignore_errors: true
|
||||
|
||||
- name: Automatische Sicherheitsupdates installieren
|
||||
ansible.builtin.apt:
|
||||
name: unattended-upgrades
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Unattended-upgrades aktivieren
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
83
ansible/roles/os_hardening/tasks/pam_password_policy.yml
Normal file
83
ansible/roles/os_hardening/tasks/pam_password_policy.yml
Normal file
@ -0,0 +1,83 @@
|
||||
---
|
||||
# CIS 5.3.x / 5.4.x: Passwortqualitaet, Account-Lockout und Ablaufregeln fuer
|
||||
# LOKALE OS-Konten auf dem Jumphost selbst (Admin-SSH-Zugang zum Jumphost-
|
||||
# Server, siehe ssh_admin_access_cidr in group_vars/all.yml).
|
||||
#
|
||||
# WICHTIG -- Abgrenzung: Dies ist NICHT identisch mit der Argon2id/TOTP-
|
||||
# Pflicht der Jumphost-WEBANWENDUNG (siehe app/security/passwords.py,
|
||||
# app/security/totp.py, app/auth/routes.py). Es handelt sich um zwei
|
||||
# getrennte Konten-/Auth-Systeme: die App verwaltet ihre eigenen Nutzer in
|
||||
# SQLite, waehrend hier die BS-Konten der Administratoren gehaertet werden,
|
||||
# die sich per SSH auf den Jumphost-Server selbst einloggen (z.B. fuer
|
||||
# Wartung, Deployment, Log-Einsicht).
|
||||
|
||||
- name: libpam-pwquality installieren
|
||||
ansible.builtin.apt:
|
||||
name: libpam-pwquality
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Passwortqualitaets-Policy setzen (CIS 5.4.1)
|
||||
# Direkt in pwquality.conf statt eines conf.d-Snippets, da nicht jede
|
||||
# Distributionsversion von libpam-pwquality ein conf.d-Verzeichnis
|
||||
# unterstuetzt -- pwquality.conf selbst wird ueberall gelesen.
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/security/pwquality.conf
|
||||
regexp: "^#?\\s*{{ item.key }}\\s*="
|
||||
line: "{{ item.key }} = {{ item.value }}"
|
||||
create: true
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
loop:
|
||||
- { key: "minlen", value: "{{ os_hardening_password_min_length }}" }
|
||||
- { key: "dcredit", value: "-1" }
|
||||
- { key: "ucredit", value: "-1" }
|
||||
- { key: "ocredit", value: "-1" }
|
||||
- { key: "lcredit", value: "-1" }
|
||||
- { key: "retry", value: "3" }
|
||||
# Kein Service-Neustart noetig: PAM liest die Datei bei jeder neuen
|
||||
# Authentifizierung, kein laufender Daemon haelt sie offen.
|
||||
|
||||
- name: Passwortqualitaet auch fuer root erzwingen
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/security/pwquality.conf
|
||||
regexp: "^#?\\s*enforce_for_root"
|
||||
line: "enforce_for_root"
|
||||
create: true
|
||||
|
||||
- name: pam_faillock fuer Login-Lockout aktivieren (CIS 5.3.1)
|
||||
ansible.builtin.blockinfile:
|
||||
path: /etc/pam.d/common-auth
|
||||
marker: "# {mark} ANSIBLE MANAGED BLOCK (jumphost pam_faillock)"
|
||||
insertbefore: "^auth\\s+\\[success=1"
|
||||
block: |
|
||||
auth required pam_faillock.so preauth silent deny={{ os_hardening_faillock_deny }} unlock_time={{ os_hardening_faillock_unlock_time }}
|
||||
auth [success=1 default=ignore] pam_unix.so nullok
|
||||
auth [default=die] pam_faillock.so authfail deny={{ os_hardening_faillock_deny }} unlock_time={{ os_hardening_faillock_unlock_time }}
|
||||
auth sufficient pam_faillock.so authsucc deny={{ os_hardening_faillock_deny }} unlock_time={{ os_hardening_faillock_unlock_time }}
|
||||
# Hinweis: pam-auth-update-verwaltete Systeme (Debian/Ubuntu-Standard)
|
||||
# ueberschreiben common-auth ggf. bei "pam-auth-update --force". Fuer
|
||||
# produktive Systeme ist die Nutzung eines eigenen pam-auth-update-Profils
|
||||
# (/usr/share/pam-configs/jumphost-faillock) die sauberere, upgrade-feste
|
||||
# Alternative -- hier aus Uebersichtlichkeitsgruenden als direkter Block-
|
||||
# Insert gehalten und im Mapping-Dokument als bekannte Einschraenkung vermerkt.
|
||||
|
||||
- name: Passwort-Ablaufregeln in /etc/login.defs setzen (CIS 5.4.1.1-5.4.1.4)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/login.defs
|
||||
regexp: "^{{ item.key }}\\s"
|
||||
line: "{{ item.key }} {{ item.value }}"
|
||||
loop:
|
||||
- { key: "PASS_MAX_DAYS", value: "90" }
|
||||
- { key: "PASS_MIN_DAYS", value: "7" }
|
||||
- { key: "PASS_WARN_AGE", value: "14" }
|
||||
- { key: "UMASK", value: "027" }
|
||||
- { key: "ENCRYPT_METHOD", value: "SHA512" }
|
||||
|
||||
- name: Passwort-Historie (pam_pwhistory) aktivieren (CIS 5.4.2)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/pam.d/common-password
|
||||
regexp: '^password\s+requisite\s+pam_pwhistory\.so'
|
||||
insertafter: '^password\s+requisite\s+pam_pwquality\.so'
|
||||
line: "password requisite pam_pwhistory.so remember={{ os_hardening_password_remember }} use_authtok"
|
||||
24
ansible/roles/os_hardening/tasks/rootkit_scan.yml
Normal file
24
ansible/roles/os_hardening/tasks/rootkit_scan.yml
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
# Ergaenzender Rootkit-/Anomalie-Scanner (rkhunter). Kein Ersatz fuer AIDE
|
||||
# (dateibasierte Integritaet) oder auditd (Ereignisprotokoll), sondern eine
|
||||
# dritte, unabhaengige Kontrollschicht mit eigener Signaturheuristik.
|
||||
|
||||
- name: rkhunter installieren
|
||||
ansible.builtin.apt:
|
||||
name: rkhunter
|
||||
state: present
|
||||
update_cache: true
|
||||
when: os_hardening_rkhunter_enabled
|
||||
|
||||
- name: rkhunter-Property-Datenbank initialisieren
|
||||
ansible.builtin.command: rkhunter --propupd
|
||||
when: os_hardening_rkhunter_enabled
|
||||
changed_when: true
|
||||
|
||||
- name: Woechentlichen rkhunter-Check per systemd-Timer aktivieren (Debian-Paket-Default nutzen)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/default/rkhunter
|
||||
regexp: '^CRON_DAILY_RUN='
|
||||
line: 'CRON_DAILY_RUN="true"'
|
||||
create: true
|
||||
when: os_hardening_rkhunter_enabled
|
||||
32
ansible/roles/os_hardening/tasks/sshd.yml
Normal file
32
ansible/roles/os_hardening/tasks/sshd.yml
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
# SSH-Daemon des Jumphosts SELBST (administrativer Zugriff auf den Server) --
|
||||
# nicht zu verwechseln mit der SSH-Proxy-Funktion der Anwendung (app/ssh_proxy),
|
||||
# die eigene, unabhaengige Verbindungen zu den Zielsystemen aufbaut.
|
||||
# CIS 5.2.x.
|
||||
|
||||
- name: SSH-Daemon des Jumphosts haerten (vollstaendige Konfiguration inkl. Banner)
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/ssh/sshd_config.d/99-jumphost-hardening.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
PermitRootLogin no
|
||||
PasswordAuthentication no
|
||||
KbdInteractiveAuthentication no
|
||||
PermitEmptyPasswords no
|
||||
X11Forwarding no
|
||||
AllowTcpForwarding no
|
||||
AllowAgentForwarding no
|
||||
PermitTunnel no
|
||||
MaxAuthTries 3
|
||||
MaxSessions 4
|
||||
LoginGraceTime 20
|
||||
ClientAliveInterval 300
|
||||
ClientAliveCountMax 2
|
||||
Banner /etc/issue.net
|
||||
LogLevel VERBOSE
|
||||
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
|
||||
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512
|
||||
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
|
||||
notify: restart sshd
|
||||
58
ansible/roles/os_hardening/tasks/sysctl.yml
Normal file
58
ansible/roles/os_hardening/tasks/sysctl.yml
Normal file
@ -0,0 +1,58 @@
|
||||
---
|
||||
# CIS 3.x (Netzwerk) / 1.5.x (Kernel-Haertung). Bewusst ueber
|
||||
# ansible.builtin.copy + "sysctl --system" statt des ansible.posix.sysctl-
|
||||
# Moduls (siehe Kommentar in Kap. 7/README) -- keine Zusatz-Collection als
|
||||
# Voraussetzung fuer den Betrieb dieses Playbooks.
|
||||
|
||||
- name: Kernel-/Netzwerk-Haertung (sysctl)
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/sysctl.d/99-jumphost-hardening.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
# --- Netzwerk (CIS 3.x) ---
|
||||
net.ipv4.conf.all.rp_filter = 1
|
||||
net.ipv4.conf.default.rp_filter = 1
|
||||
net.ipv4.conf.all.accept_redirects = 0
|
||||
net.ipv4.conf.default.accept_redirects = 0
|
||||
net.ipv4.conf.all.secure_redirects = 0
|
||||
net.ipv4.conf.default.secure_redirects = 0
|
||||
net.ipv4.conf.all.send_redirects = 0
|
||||
net.ipv4.conf.default.send_redirects = 0
|
||||
net.ipv4.conf.all.accept_source_route = 0
|
||||
net.ipv4.conf.default.accept_source_route = 0
|
||||
net.ipv4.conf.all.log_martians = 1
|
||||
net.ipv4.conf.default.log_martians = 1
|
||||
net.ipv4.icmp_echo_ignore_broadcasts = 1
|
||||
net.ipv4.icmp_ignore_bogus_error_responses = 1
|
||||
net.ipv4.tcp_syncookies = 1
|
||||
net.ipv4.ip_forward = 0
|
||||
net.ipv6.conf.all.accept_redirects = 0
|
||||
net.ipv6.conf.default.accept_redirects = 0
|
||||
net.ipv6.conf.all.accept_source_route = 0
|
||||
net.ipv6.conf.default.accept_source_route = 0
|
||||
{% if os_hardening_disable_ipv6 %}
|
||||
net.ipv6.conf.all.disable_ipv6 = 1
|
||||
net.ipv6.conf.default.disable_ipv6 = 1
|
||||
{% endif %}
|
||||
# --- Kernel-Haertung (CIS 1.5.x) ---
|
||||
kernel.kptr_restrict = 2
|
||||
kernel.dmesg_restrict = 1
|
||||
kernel.randomize_va_space = 2
|
||||
kernel.yama.ptrace_scope = 1
|
||||
fs.suid_dumpable = 0
|
||||
fs.protected_hardlinks = 1
|
||||
fs.protected_symlinks = 1
|
||||
fs.protected_fifos = 2
|
||||
fs.protected_regular = 2
|
||||
notify: apply sysctl
|
||||
|
||||
- name: Core Dumps zusaetzlich auf PAM-Ebene deaktivieren (CIS 1.5.1)
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/security/limits.d/99-jumphost-no-coredumps.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
* hard core 0
|
||||
Reference in New Issue
Block a user