Was sollte man immer als erstes tun, wenn man einen produktiven Linux Server erfolgreich an den Start bringt? Klar, als erstes frönt man dem Gott des Hochprozentigen, flutet zur Feier des Tages die Hirnsynapsen mit feinstem schottischen Fusel und tanzt die ganze Nacht über mit Marusha und Scooter zu ultrafetten Techno-Raves 🙂 Aber was sollte man, nachdem man wieder zu sich gekommen ist, als nächstes tun? Ganz genau! Man sollte sich schön brav einen aktuellen Ist-Zustand des frisch aufgesetzten Linux-Servers ziehen, damit man bei Sicherheits-, System- und oder Performance-Problemen einen Vergleich zwischen dem Ausgangszustand und einem späteren, sich vielleicht nicht mehr so geschmeidig anfühlenden Zustand des geliebten Systems hat.
Solch eine Inventarisierung nennt man im Admin-Fachjargon auch Baselining. Beim Baselining sammelt ein Programm oder ein Skript frivol wichtige Serverparameter wie System-, Netzwerk-, Security- und Performance-Infos eines Linux-Servers zusammen. Verkackt z.B. ein Admin-Kollege (man selbst macht ja NIEMALS Fehler) die ACL-Berechtigungen einer wichtigen Ordnerstruktur, so kann dank des erstellten Baselinings, fix der Fehler wieder ausgebadet werden. Ein weiteres Beispiel wäre z.B. wenn aus unerklärlichen Gründen die Performance einer Datenbank auf einmal zu wünschen übrig lässt. Klappert man Bilderbuch-mäßig und in bester OSI-Manier die Fehlerquellen ab und kommt an den Punkt, an dem man die aktuelle Festplattengeschwindigkeit mit der aus dem Baselining vergleicht, merkt man, dass die Daten wegen eines Festplattenfehlers nur noch im Schneckentempo auf die Platte gefeuert werden.
Einige knusprige Vorteile des Baselining:
- Verbesserte Transparenz des Servers
- Bessere Einhaltung von Compliance-Regeln
- Detaillierte Hardware- und Systeminformationen
- Man/Frau bekommt ein besseres Gefühl für das System
- Ermöglicht schnellere Identifizierung von Fehlern und Sicherheitsproblemen
- Erkennung von Anomalien auf dem System (bei der Neuinstallation, nach dem Patchday)
- Unterstützt bei der Durchführung von Audits und der Erstellung von hocherotischen Berichten
- Ermittlung von Systemressourcen und -konfigurationen zur Verbesserung der Leistung und Stabilität des Systems
Da ich es wie immer sehr einfach, gechillt und unkompliziert halte, habe ich mir zu dem Thema Baselining vor über 15 Jahren ein wirklich sehr einfach gestricktes, total unkompliziertes Baselining/Inventarisierungs-Skript für Debian-basierte Systeme zusammengebastelt, welches bei jeder Debian/Ubuntu Neuinstallation und vor jedem Update/Upgrade eines Linux-Systems zum Einsatz kam. Dieses sehr leicht an die eigenen Bedürfnisse anpass- und erweiterbares Skript habe ich dann vor kurzem etwas entstaubt, ein wenig gepimpt, mit Osquery (einem coolen Sicherheitsüberprüfungsprogramm) erweitert und knalle es, in der Hoffnung, dass es irgend jemandem da draußen was bringen möge, in den Blog.
Einsatzzwecke des Baselining:
- Forensik-Vorbereitung: Snapshot für spätere Vergleiche nach Incidents – „Was war vorher?“
- Nachschlagewerk/Dokumentation: Nachschlagewerk oft genutzter Administrationsbefehle
- Security-Baselining: Vergleich gegen sichere Sollkonfigurationen (z. B. offene Ports, SUID, ACLs)
- Backup-Validierung: Prüfsummen & Metadaten sichern Struktur, Größe und Existenz von Dateien
- Incident Response: Schnelle Sicht auf Prozesse, Benutzer, Verbindungen bei verdächtigen Aktivitäten
- Schwachstellen-Analyse: Grundlage für CVE-/Patchmanagement (in Kombination mit Tools wie vuls)
- Revisionssicherheit: Wiederherstellbarkeit und Transparenz durch regelmäßige, versionierte Snapshots
- Compliance & Auditing: Nachweisbare Systemzustände für DSGVO, ISO 27001, BSI IT-Grundschutz etc
- System-Inventarisierung: Vollständige Erfassung von Hardware, Software, Diensten, Usern, Netzwerk etc
- Change-/Patch-Impact-Analyse: Analyse von Systemverhalten nach Updates, Konfigänderungen, Deployments
- Systemvergleiche / Drift Detection: Erkennung von Abweichungen zwischen Hosts oder vor/nach Änderungen
Vorbereitung für die Inventarisierung
Als erstes werden die benötigten Pakete installiert und eine Passwort-Datei für die automatisch Verschlüsselung der gesammelten Daten angelegt.
# Grundpakete installieren apt install acl bind9-dnsutils dstat dmidecode gnupg2 lynis nmap osquery pigz psmisc rng-tools-debian ufw # Osquery installieren export OSQUERY_KEY=1484120AC4E9F8A1A577AEEE97A80C63C9D8B80B apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys $OSQUERY_KEY add-apt-repository 'deb [arch=amd64] https://pkg.osquery.io/deb deb main' apt update && apt install osquery # Lynis installieren apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C80E383C3DE9F082E01391A0366C67DE91CA5D5F echo "deb https://packages.cisofy.com/community/lynis/deb/ stable main" > /etc/apt/sources.list.d/cisofy-lynis.list apt update && apt install lynis # GPG-Key Passwortdatei für das verschlüsselte Inventory-Backup erstellen PASSWORD=$(apg -m16 -n 1 -M NCS -E '/\#') echo $PASSWORD > /root/.inventory
Das Inventarisierungs-Skript
Das Skript legt mit den Variablen INVENT_DIR und BACKUP_DIR die Ordnerstruktur an, setzt für diese stabile Berechtigungen fest und fängt dann mit der sch(w)eißtreibenden Inventarisierung (Baselining) an. Alle Infos zu dem System werden in dafür vorgegebenen Dateien gepumpt. Am Ende wird zur Sicherheit eine Checksumme für alle gesammelten Dateien erstellt, die Dateien gepackt, verschlüsselt, das unverschlüsselte Archive entfernt und als letztes werden alte Inventarisierungen entfernt. Somit bleiben zum inspizieren die gesammelten Dateien und das verschlüsseltes Archiv übrig, welches man z.B per SCP auf einen Remote-Server pumpen sollte.
Aufbau der Baselinig-Dateien:
# sys=Systeminfos, net=Network, sec=Security, perf=Performance, osq=Osquery System-Infos -> sys-memory.txt Netzwerk-Infos -> net-ip-addr.txt Security-Infos -> sec-ufw-firewall.txt Performance-Infos -> perf-dd-disk-speed.txt Osquery-Abfragen -> osq-sys-osversion.txt
inventory.sh
#!/usr/bin/env bash #============================================================ # Script Name: sec-os-inventory.sh # Script Path: /root/server-scripts/ # Autor: Hackspoiler # URL: https://hackspoiler.de # Git Repository: https://gitlab.hsp.de/root/server-scripts/ # Version: 2.3.0 # Shellcheck: True # Date Created: 2020-05-02 # Date Modified: 2025-07-13 # Used Packages: acl bind9-dnsutils dd dstat dmidecode gnupg2 lynis nmap osquery pigz psmisc rng-tools-debian ufw xargs # Glossar: net=Network, osq=Osquery, perf=Performance, sec=Security, sys=Systeminfos # Description: Erstellt eine Inventarisierung (Baselining) eines Linux Servers #============================================================ #============================================================ # Check for root permissions #============================================================ if [[ "$EUID" -ne 0 ]]; then echo "Script requires root permissions" >&2 exit 1 fi #============================================================ # Set Bash-Defaults #============================================================ set -o nounset # Beenden, falls ein ungesetzter Variablenname verwendet wird set -o pipefail # Beenden, falls eine Pipeline fehlschlägt #============================================================ # Les Variables #============================================================ SCRIPT_NAME=$(basename "$0" .sh) HOSTNAME_SHORT="$(hostname --short)" LOG_FILE="/var/log/${SCRIPT_NAME}.log" CURRENT_TIMESTAMP=$(date +'%Y-%m-%d_%H-%M-%S') INVENT_DIR="/root/inventory/${CURRENT_TIMESTAMP}" BACKUP_DIR="/var/backups/inventory/${CURRENT_TIMESTAMP}" # BACKUP_SRV="root@$IP_ADDRESS" # Programm-Optionen je nach Ressourcen anpassen CPU_PROCESSES=2 XARGS=("xargs" "--max-procs=${CPU_PROCESSES}") PIGZ="pigz --fast --processes ${CPU_PROCESSES} --keep" #============================================================ # Grundeinstellungen #============================================================ # Ordnerstruktur anlegen und Berechtigung brav setzen install -d -m 700 "${INVENT_DIR}" "${BACKUP_DIR}" #============================================================ # Logging Setup #============================================================ exec > >(tee --append --ignore-interrupts "${LOG_FILE}") 2>&1 #============================================================ # Check if commands are availible #============================================================ check_needed_commands() { for CMD in "$@"; do if ! command -v "$CMD" &>/dev/null; then echo "Error: Required command ${CMD} not found in PATH." >&2 exit 1 fi done } #============================================================ # Datei-Indexierung auf dem System #============================================================ file_index_check() { echo "# Inventory - Datei-Indexierung auf dem System $(hostname -f) startet - $(date +'%H-%M-%S') #" ls -l --all --human-readable /* > "${INVENT_DIR}/sys-list-root-files.txt" find / -xdev ! -path "/mnt/*" ! -path "/proc/*" -print0 | "${XARGS[@]}" --null ls -l > "${INVENT_DIR}/sys-list-all-files.txt" } 2> "${LOG_FILE}.errors.log" #============================================================ # System-Infos #============================================================ system_check() { echo "# Inventory - Systeminfo-Collection startet - $(date +'%H-%M-%S') #" lastlog > "${INVENT_DIR}/sys-lastlog.txt" cp /etc/group "${INVENT_DIR}/sys-group.txt" cp /etc/fstab "${INVENT_DIR}/sys-fstab.txt" cp /etc/passwd "${INVENT_DIR}/sys-user.txt" free --mega > "${INVENT_DIR}/sys-memory.txt" hostnamectl > "${INVENT_DIR}/sys-hostinfo.txt" ps -auxfww > "${INVENT_DIR}/sys-processlist.txt" dpkg --list > "${INVENT_DIR}/sys-deb-packages.txt" apt list --upgradeable > "${INVENT_DIR}/sys-deb-upgradeable.txt" who --all > "${INVENT_DIR}/sys-logged-in-users.txt" uname --all > "${INVENT_DIR}/sys-kernelversion.txt" sysctl --all > "${INVENT_DIR}/sys-sysctl-settings.txt" pstree --arguments > "${INVENT_DIR}/sys-process-pstree.txt" findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS > "${INVENT_DIR}/sys-mounts.txt" dmidecode --type processor --type memory > "${INVENT_DIR}/sys-cpu-ram-info.txt" dmesg --ctime --decode --level=alert,crit,emerg,err,warn > "${INVENT_DIR}/sys-dmesg.txt" systemctl list-timers --all --no-pager > "${INVENT_DIR}/sys-systemctl-timers.txt" systemctl --type=service --state=active > "${INVENT_DIR}/sys-systemctl-active-services.txt" systemctl list-dependencies graphical.target > "${INVENT_DIR}/sys-systemctl-services-tree.txt" systemctl list-units --all --type=service --no-pager > "${INVENT_DIR}/sys-systemctl-services.txt" [[ -r /root/.bash_history ]] && cp /root/.bash_history "${INVENT_DIR}/sys-root-history.txt" grep --extended-regexp --invert-match "^\s*(#|$)" /var/spool/cron/crontabs/* /etc/cron.d/* > "${INVENT_DIR}/sys-crontabs.txt" lsblk --output NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT,UUID,OWNER,GROUP,MODE,RO,MODEL,STATE > "${INVENT_DIR}/sys-disks.txt" du --human-readable --summarize --one-file-system --exclude=/{proc,sys,dev,run} /* | sort -hr > "${INVENT_DIR}/sys-directory-space.txt" find / -xdev ! -path "/proc/*" -type f -size +100M -print0 | "${XARGS[@]}" --null stat --format='%A %U %G %y %n %s' > "${INVENT_DIR}/sys-big-files.txt" { df --human-readable --print-type -x tmpfs -x devtmpfs | sort --key 6 --reverse; echo ""; df --inodes --human-readable --print-type -x tmpfs -x devtmpfs | sort --key 6 --reverse; } > "${INVENT_DIR}/sys-disk-space.txt" grep --extended-regexp --ignore-case '(abort|alert|crit|corrupt|emerg|error|exception|fail|false|fatal|invalid|kill|not found|oom|panic|refused|segfault|timeout|unauthorized|unavailable|warn)' /var/log/syslog > "${INVENT_DIR}/sys-log-syslog.txt" grep --extended-regexp --ignore-case '(abort|alert|crit|corrupt|emerg|error|exception|fail|false|fatal|invalid|kill|not found|oom|panic|refused|segfault|timeout|unauthorized|unavailable|warn)' /var/log/kern.log > "${INVENT_DIR}/sys-log-kern.txt" } 2>> "${LOG_FILE}.errors.log" #============================================================ # Netzwerk-Infos #============================================================ network_check() { echo "# Inventory - Netzwerkinfo-Collection startet - $(date +'%H-%M-%S') #" ip -details addr show > "${INVENT_DIR}/net-ip-addr.txt" ip -stats link show > "${INVENT_DIR}/net-ip-stats.txt" ip -brief route show > "${INVENT_DIR}/net-ip-route.txt" lsof -nP -i -i4 -i6 > "${INVENT_DIR}/net-lsof-networkresources.txt" ss --listening --processes --tcp --udp > "${INVENT_DIR}/net-ss-stat.txt" for NET_IFACE in $(networkctl list --no-pager --no-legend | awk '{print $1}'); do networkctl status "$NET_IFACE" > "${INVENT_DIR}/net-networkctl-${NET_IFACE}.txt"; done } 2>> "${LOG_FILE}.errors.log" #============================================================ # Security-Infos #============================================================ security_check() { echo "# Inventory - Securityinfo-Collection startet - $(date +'%H-%M-%S') #" umask > "${INVENT_DIR}/sec-umask.txt" cp /etc/sudoers "${INVENT_DIR}/sec-sudoers.txt" ufw status verbose > "${INVENT_DIR}/sec-ufw-firewall.txt" # nmap -T4 -p- --max-retries 1 --host-timeout 60s --reason localhost -oN "${INVENT_DIR}/sec-nmap-portscan.txt" # Mehr Performance = Rustscan ss -Hltun | awk '{print $5}' | sed 's/.*://g' | grep -E '^[0-9]+$' | sort -n | uniq > "${INVENT_DIR}/sec-ss-portscan.txt" lynis audit system --auditor "Da-Boss" --quick --quiet --logfile "${INVENT_DIR}/sec-lynis.txt" cat /root/.ssh/{known_hosts,authorized_keys} > "${INVENT_DIR}/sec-root-ssh-keys.txt" find /etc -xdev -type f -print0 | "${XARGS[@]}" --null sha256sum > "${INVENT_DIR}/sec-sha256sum-etc.txt" find /usr -xdev -type f -print0 | "${XARGS[@]}" --null sha256sum > "${INVENT_DIR}/sec-sha256sum-usr.txt" find / -xdev ! -path "/mnt/*" ! -path "/proc/*" -size +0 -print0 | "${XARGS[@]}" --null -I {} getfacl --absolute-names {} > "${INVENT_DIR}/sec-getfacl-permissions.acl" find / -xdev ! -path "/mnt/*" ! -path "/proc/*" \( -nouser -o -nogroup \) -print0 | "${XARGS[@]}" --null ls -l --all --human-readable > "${INVENT_DIR}/sec-nouser-nogroup.txt" find / -xdev ! -path "/mnt/*" ! -path "/proc/*" ! -type l ! -type c ! -type b -perm -2 -print0 | "${XARGS[@]}" --null ls -l --all --human-readable > "${INVENT_DIR}/sec-world-writable.txt" } 2>> "${LOG_FILE}.errors.log" #============================================================ # Performance-Infos #============================================================ performance_check() { echo "# Inventory - Performance-Collection startet - $(date +'%H-%M-%S') #" dstat --top-cpu-adv --top-latency --top-io --top-mem --mem --load --time 1 15 > "${INVENT_DIR}/perf-dstat.txt" dd if=/dev/zero of="${BACKUP_DIR}"/testfile bs=512 count=1000 oflag=dsync 2> "${INVENT_DIR}/perf-dd-disk-speed.txt" && rm "${BACKUP_DIR}/testfile" dd if=/dev/zero of="${BACKUP_DIR}"/testfile bs=1MB count=1 oflag=dsync 2>> "${INVENT_DIR}/perf-dd-disk-speed.txt" && rm "${BACKUP_DIR}/testfile" dd if=/dev/zero of="${BACKUP_DIR}"/testfile bs=100MB count=1 oflag=dsync 2>> "${INVENT_DIR}/perf-dd-disk-speed.txt" && rm "${BACKUP_DIR}/testfile" dd if=/dev/zero of="${BACKUP_DIR}"/testfile bs=500MB count=1 oflag=dsync 2>> "${INVENT_DIR}/perf-dd-disk-speed.txt" && rm "${BACKUP_DIR}/testfile" } 2>> "${LOG_FILE}.errors.log" #============================================================ # Osquery-Abfragen #============================================================ osquery_check() { echo "# Inventory - Osquery-Collection startet - $(date +'%H-%M-%S') #" # Osquery - Config check osqueryi "select config_hash, config_valid from osquery_info;" > "${INVENT_DIR}/osq-configcheck.txt" # Osquery - Systeminfos osqueryi "SELECT * FROM memory_info;" > "${INVENT_DIR}/osq-sys-memory.txt" osqueryi "SELECT * FROM os_version;" > "${INVENT_DIR}/osq-sys-osversion.txt" osqueryi "SELECT count(*) FROM crontab;" > "${INVENT_DIR}/osq-sys-crontabs.txt" osqueryi "SELECT command, path FROM crontab;" >> "${INVENT_DIR}/osq-sys-crontabs.txt" osqueryi "SELECT days, datetime(time.local_time - uptime.total_seconds, 'unixepoch') AS last_rebooted FROM time, uptime;" > "${INVENT_DIR}/osq-sys-uptime.txt" osqueryi "SELECT hostname, cpu_brand, cpu_physical_cores, cpu_logical_cores, computer_name, physical_memory FROM system_info;" > "${INVENT_DIR}/osq-sys-hardware.txt" osqueryi "SELECT pid, name, ROUND((total_size * '10e-7'), 2) AS used FROM processes ORDER BY total_size DESC LIMIT 10;" > "${INVENT_DIR}/osq-sys-memory-intensive-processes.txt" osqueryi "SELECT pid, name, path, cmdline, state, cwd, root, uid, gid, suid, sgid, on_disk, total_size, user_time, system_time, start_time, parent, pgroup, threads, nice FROM processes LIMIT 20;" >> "${INVENT_DIR}/osq-sys-memory-intensive-processes.txt" osqueryi "SELECT device, path, type, blocks_size, blocks, blocks_free, blocks_available, inodes, inodes_free, flags FROM mounts where type!='cgroup' and type!='tmpfs' and inodes!='0';" > "${INVENT_DIR}/osq-sys-devices.txt" osqueryi "SELECT device, device_alias, path, blocks, blocks_free, inodes, inodes_free, flags, encrypted, encryption_status FROM mounts m, disk_encryption d WHERE m.device_alias = d.name;" > "${INVENT_DIR}/osq-sys-devices-encrypted.txt" osqueryi "SELECT pid, uid, name, ROUND(( (user_time + system_time) / (cpu_time.tsb - cpu_time.itsb)) * 100, 2) AS percentage FROM processes, (SELECT (SUM(user) + SUM(nice) + SUM(system) + SUM(idle) * 1.0) AS tsb, SUM(COALESCE(idle, 0)) + SUM(COALESCE(iowait, 0)) AS itsb FROM cpu_time) AS cpu_time ORDER BY user_time+system_time DESC LIMIT 20;" > "${INVENT_DIR}/osq-sys-cpu-intensive-processes.txt" # Osquery - Paketmanagement osqueryi "SELECT count(*) FROM deb_packages;" > "${INVENT_DIR}/osq-sys-deb-packages.txt" osqueryi "SELECT name, version, source, size, arch, revision, status FROM deb_packages;" >> "${INVENT_DIR}/osq-sys-deb-packages.txt" osqueryi "SELECT name, base_uri, release, maintainer, components FROM apt_sources ORDER BY name;" > "${INVENT_DIR}/osq-sys-deb-sources.txt" # Osquery - Usermanagement osqueryi "SELECT * FROM last;" > "${INVENT_DIR}/osq-sys-login-users.txt" osqueryi "SELECT * FROM logged_in_users;" > "${INVENT_DIR}/osq-sys-loggedin-users.txt" osqueryi "SELECT * FROM users WHERE gid < 65534 AND uid >= 1000;" > "${INVENT_DIR}/osq-sys-non-system-users.txt" osqueryi "SELECT count(*) FROM users" > "${INVENT_DIR}/osq-sys-all-users.txt" osqueryi "SELECT uid, gid, uid_signed, gid_signed, username, description, directory, shell FROM users;" >> "${INVENT_DIR}/osq-sys-all-users.txt" # Osquery - Aktive Kernelmodule osqueryi "SELECT count(*) FROM kernel_modules WHERE status='Live';" > "${INVENT_DIR}/osq-sys-kernelmodule.txt" osqueryi "SELECT name, used_by, status FROM kernel_modules WHERE status='Live';" >> "${INVENT_DIR}/osq-sys-kernelmodule.txt" # Osquery - Securitymanagement osqueryi "SELECT count(*) FROM suid_bin;" > "${INVENT_DIR}/osq-sec-setuid.txt" osqueryi "SELECT * FROM suid_bin;" >> "${INVENT_DIR}/osq-sec-setuid.txt" osqueryi "SELECT count(*) FROM sudoers;" > "${INVENT_DIR}/osq-sec-sudoers.txt" osqueryi "SELECT * FROM sudoers;" >> "${INVENT_DIR}/osq-sec-sudoers.txt" osqueryi "SELECT count(*) FROM iptables;" > "${INVENT_DIR}/osq-sec-firewall-all.txt" osqueryi "SELECT * FROM iptables;" >> "${INVENT_DIR}/osq-sec-firewall-all.txt" osqueryi "SELECT chain, policy, src_ip, dst_ip FROM iptables;" > "${INVENT_DIR}/osq-sec-firewall-short.txt" osqueryi "SELECT suid_bin.path, username, groupname, permissions, hash.sha256 FROM hash JOIN suid_bin USING (path);" >> "${INVENT_DIR}/osq-sec-setuid.txt" # Osquery - Network osqueryi "SELECT count(*) FROM routes;" > "${INVENT_DIR}/osq-net-routes.txt" osqueryi "SELECT * FROM routes;" >> "${INVENT_DIR}/osq-net-routes.txt" osqueryi "SELECT * FROM etc_hosts;" > "${INVENT_DIR}/osq-net-hosts.txt" osqueryi "SELECT count(*) FROM listening_ports;" > "${INVENT_DIR}/osq-net-listening-ports.txt" osqueryi "SELECT DISTINCT processes.name, listening_ports.path, processes.pid, listening_ports.port, listening_ports.protocol, listening_ports.family, listening_ports.address, listening_ports.socket FROM listening_ports JOIN processes using (pid);" >> "${INVENT_DIR}/osq-net-listening-ports.txt" osqueryi "SELECT p.cmdline, pos.local_address, pos.remote_address, local_port, pos.remote_port from process_open_sockets as pos JOIN processes as p ON pos.pid=p.pid WHERE pos.state='ESTABLISHED';" > "${INVENT_DIR}/osq-net-established-connections.txt" # Osquery - Docker osqueryi "SELECT id, key, value FROM docker_image_labels;" > "${INVENT_DIR}/osq-docker-images.txt" osqueryi "SELECT name, id, os, cpus, memory, containers, containers_running, containers_paused, containers_stopped, images, storage_driver, server_version, root_dir FROM docker_info;" > "${INVENT_DIR}/osq-docker-infos.txt" } 2>> "${LOG_FILE}.errors.log" #============================================================ # Abschluss #============================================================ abschluss() { # Checksum aus allen Dateien bilden echo "# Inventory - Checksum startet - $(date +'%H-%M-%S') #" find "${INVENT_DIR}"/ -type f -print0 | "${XARGS[@]}" --null sha256sum > "${INVENT_DIR}/sec-sha256sum-inventory.txt" # Inventory-Archiv inklusive wichtiger Systemdaten (Beispiel etc, usr) erstellen echo "# Inventory - Inventory-Archivierung startet - $(date +'%H-%M-%S') #" tar --use-compress-program="${PIGZ}" --create --file "${BACKUP_DIR}"/sec-os-inventory-$(hostname --fqdn)-"${CURRENT_TIMESTAMP}".tgz \ /etc \ "${INVENT_DIR}"/* 2> /dev/null # Inventory-Archiv verschlüsseln echo "# Inventory - Inventory-Archiv-Encryption startet - $(date +'%H-%M-%S') #" [[ -r /root/.inventory ]] || { echo "Error: No Passphrase-File under /root/.inventory found." >&2; exit 1; } gpg --batch --yes --passphrase-file /root/.inventory --symmetric "${BACKUP_DIR}/sec-os-inventory-$(hostname --fqdn)-${CURRENT_TIMESTAMP}.tgz" # Unverschlüsseltes Inventory-Archiv entfernen echo "# Inventory - Entfernung des einfachen Inventory-Archiv startet #" rm --force --preserve-root "${BACKUP_DIR}"/sec-os-inventory-$(hostname --fqdn)-"${CURRENT_TIMESTAMP}".tgz # Inventory-Archive älter als einen Tag rasieren echo "# Inventory - Entfernung alter Inventory-Archive startet - $(date +'%H-%M-%S') #" find /root/inventory/ /var/backups/inventory/ -mindepth 1 -type d -mtime +1 -print0 | "${XARGS[@]}" --null -I {} rm --force --preserve-root --recursive {} # Archiv auf Backup-Server pumpen #rsync --progress --bwlimit=100k --verbose "${BACKUP_DIR}"/inventory-*.tgz "${BACKUP_SRV}":/"${BACKUP_DIR}"/ # Haben fertig echo "# Inventory - Inventory wurde um $(date +'%H-%M-%S') in ${BACKUP_DIR} erstellt - Zeit für ein hochverdientes Bio-Bierchen #" } #============================================================ # Function calls #============================================================ main() { check_needed_commands acl bind9-dnsutils dd dstat dmidecode gnupg2 lynis nmap osquery pigz psmisc rng-tools-debian ufw xargs file_index_check system_check network_check security_check performance_check [ -x "$(command -v osqueryi)" ] && osquery_check abschluss } main "$@" #============================================================ # Decrypt + Dekomprimierung #============================================================ # gpg --batch --passphrase $PASSWD --decrypt "${BACKUP_DIR}"/sec-os-inventory-$(hostname --fqdn)-"${CURRENT_TIMESTAMP}".tgz.gpg | tar --extract --gunzip # cat /root/.inventory | /usr/bin/gpg --batch --yes --passphrase-fd 0 -d "${BACKUP_DIR}"/sec-os-inventory-$(hostname --fqdn)-"${CURRENT_TIMESTAMP}".tgz.gpg | tar --extract --gunzip
Ist das Skript durchgerödelt hat man es sich auf jeden Fall wieder verdient, dem Gott des Hochprozentigen zu frönen und zur Feier des Tages grüßt täglich das Murmeltier.