Debian Patchmanagement
Ziel ist es ein einfaches Patchmanagement mit Webinterface für eine Anzahl von Debian Servern zu schaffen.
Voraussetzungen:
Ein Debian Server mit folgenden Paketen:
apache2, php, postgresql-server, php-pgsql, openssh-server, sshpass, sudo
Installation des Management-Servers:
-
-
-
-
-
-
-
- Erzeugen eines RSA-Schlüssel „ssh-keygen“
- Erweitern der „/etc/ssh/ssh_config“ mit dem Wert „StrictHostKeyChecking no“
- anpassen der sudoers für www-data:
# User privilege specification root ALL=(ALL:ALL) ALL www-data ALL=(ALL) NOPASSWD: ALL
- anlegen eines Verzeichnis für das WEB-Frontend „mkdir /var/www/html/patch“
- Postgresql erlauben Kommunikation aus dem internen Netzwerk an zu nehmen:
-
- /etc/postgresql/11/main/postgresql.conf -> listen_addresses = ‚*‘
- /etc/postgres/11/main/pg_hba.conf:
# IPv4 local connections: host all all 192.168.66.1/24 password
- /etc/init.d/postgresql restart
-
- anlegen der Datenbank in Postgresql ‚psql -U postgres -c „create database apt“‚
- einen User für die Datenbank anlegen psql -d apt -U postgres -c „CREATE USER apt WITH PASSWORD ‚apt123‘;“‚
- Eine Tabelle anlegen „psql -d apt -U postgres“
-
CREATE TABLE IF NOT EXISTS zustand ( id SERIAL PRIMARY KEY, server VARCHAR(15) NOT NULL, sys VARCHAR(255) NOT NULL, pu VARCHAR(3) NOT NULL, ul TEXT, root_free VARCHAR(10) NOT NULL, last_run TIMESTAMP NOT NULL );
-
- erzeugen der Startseite (/var/www/html/patch/index.php)
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Server Information</title> <style> body { background-color: #0e0e0e; color: #ffffff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 0; box-sizing: border-box; overflow-x: hidden; } .container { width: 100%; margin: 50px 0; overflow-x: auto; } table { width: 100%; border-collapse: collapse; margin-top: 20px; background-color: #1e1e1e; box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.5); border-radius: 12px; overflow: hidden; } th, td { border: 1px solid #333; padding: 16px; text-align: left; transition: background-color 0.3s ease; } th { background-color: #4CAF50; color: white; } textarea { width: 100%; height: 6em; resize: vertical; background-color: #333; color: #ffffff; border: 1px solid #666; padding: 12px; border-radius: 6px; } .action-button { background-color: #3498db; color: #ffffff; padding: 12px 20px; border: none; border-radius: 8px; cursor: pointer; transition: background-color 0.3s ease; } .action-button:hover { background-color: #2980b9; } .connected { color: #3498db; } .highlight-row { background-color: #2ecc71; color: #ffffff; } </style> </head> <body> <div class="container"> <h2 style="text-align: center;">Server Information</h2> <table> <thead> <tr> <th>Server</th> <th>Debian Version</th> <th>Updates Possible</th> <th style="width: 100%;">Update List</th> <th>Root Free</th> <th>Last Run</th> <th>Action</th> </tr> </thead> <tbody> <?php // PostgreSQL Credentials $host = "192.168.66.31"; $user = "postgres"; $password = "postgres"; $database = "apt"; // Verbindung zur Datenbank herstellen $conn = new PDO("pgsql:host=$host;dbname=$database;user=$user;password=$password"); // SQL-Abfrage //$query = "SELECT * FROM zustand ORDER BY server"; $query = "SELECT * FROM zustand ORDER BY (split_part(server, '.', 4)::int)"; $result = $conn->query($query); if ($result) { foreach ($result as $row) { $name = $row['server']; $version = $row['sys']; $updates = $row['pu']; $updateList = $row['ul']; $rootFree = $row['root_free']; $lastRun = $row['last_run']; $ip = $row['ip']; // Prüfe, ob die IP in der idlist.log vorhanden ist $IPC = shell_exec("cat /var/www/html/patch/idlist.log | grep $name | wc -l"); // $isIPConnected = in_array($ip, file('/var/www/html/patch/idlist.log; // Bestimme den Inhalt der Action-Spalte basierend auf der IP-Verbindung if ($IPC != 0 AND $updates != 0) { $action = '<span class="connected">✔ ssh connected</span><p><button class="action-button" onclick="openUpdatePage(\'' . $name . '\', \'' . $name . '\')">Server Update</button>'; } if ($IPC != 0 AND $updates == 0) { $action = '<span class="connected">✔ ssh connected</span>'; } if ($IPC == 0) { $action = '<button class="action-button" onclick="openSSHPage(\'' . $name . '\', \'' . $name . '\')">connect SSH</button>'; } // Füge eine Klasse für die Hervorhebung hinzu, wenn "Updates Possible" größer als 0 ist $rowClass = ($updates > 0) ? 'highlight-row' : ''; echo "<tr class='$rowClass'>"; echo "<td>$name</td>"; echo "<td>$version</td>"; echo "<td>$updates</td>"; // Wenn "Updates Possible" größer als 0 ist, zeige die Textarea if ($updates > 0) { echo "<td><textarea rows='6' readonly>$updateList</textarea></td>"; } else { echo "<td>$updateList</td>"; } echo "<td>$rootFree</td>"; echo "<td>$lastRun</td>"; echo "<td>$action</td>"; echo "</tr>"; } } else { echo "<tr><td colspan='7'>Error fetching data.</td></tr>"; } $conn = null; // Verbindung schließen ?> </tbody> </table> </div> <script> function openUpdatePage(serverName, serverIP) { window.open('supdate.php?ip=' + serverIP, '_blank'); } function openSSHPage(serverName, serverIP) { window.open('sid.php?ip=' + serverIP, '_blank'); } </script> </body> </html>
-
- erzeugen des Skripts für den Import der SSH-Keys (/var/www/html/patch/imp.sh)
ip=`/bin/cat /var/www/html/patch/simp.tmp` sshpass -p "ROOTPASSWORT" ssh-copy-id -i /root/.ssh/id_rsa.pub root@$ip
- erzeugen des PHP Übergang für den Import der SSH-Keys (/var/www/html/patch/sid.php) <
!--?php $ip=$_GET[ip]; shell_exec("sudo echo $ip > /var/www/html/patch/simp.tmp"); $d=shell_exec("sudo /var/www/html/patch/imp.sh"); shell_exec("sudo echo $ip >> /var/www/html/patch/idlist.log"); echo "$d"; echo $ip ?-->
- erzeugen des PHP-Skrips für das Updaten (/var/www/html/patch/supdate.sh) <
!--?php $ip=$_GET[ip]; //shell_exec("sudo echo $ip > /var/www/html/patch/simp.tmp"); $d=shell_exec("sudo ssh root@$ip 'apt upgrade -y'"); $xd=shell_exec("sudo ssh root@$ip '/local/patch.sh'"); //shell_exec("sudo echo $ip >> /var/www/html/patch/idlist.log"); echo "$d"; echo "$xd"; echo $ip ?-->
- erzeugen des Skripts für die Satellite-Server (/var/www/html/patch/patch.sh)
#!/bin/bash # PostgreSQL Credentials PG_HOST="IP-DES-POSTGRESQL-SERVER" PG_USER="apt" PG_PASSWORD="apt123" PG_DATABASE="apt" # Funktion zum Einfügen oder Aktualisieren von Daten in die PostgreSQL-Tabelle insert_or_update_data() { local server_ip="$1" local debian_version="$2" local updates_possible="$3" local update_list="$4" local root_free="$5" local current_datetime="$(date +'%Y-%m-%d %H:%M:%S')" # SQL-Statement zum Einfügen oder Aktualisieren von Daten in die Tabelle psql -h "$PG_HOST" -U "$PG_USER" -d "$PG_DATABASE" -c "INSERT INTO zustand (server, sys, pu, ul, root_free, last_run) VALUES ('$server_ip', '$debian_version', '$updates_possible', '$update_list', '$root_free', '$current_datetime') ON CONFLICT (server) DO UPDATE SET sys='$debian_version', pu='$updates_possible', ul='$update_list', root_free='$root_free', last_run='$current_datetime';" } # Hauptskript # Aktualisieren Sie die Paketliste apt update if ! command -v psql &> /dev/null then echo "psql is not installed. Installing postgresql-client..." apt install -y postgresql-client fi # Erfassen von Systeminformationen server_ip=$(hostname -I | awk '{print $1}') # IP-Adresse des Servers debian_version=$(lsb_release -ds) # Aktuelle Debian-Version update_output=$(apt list --upgradable 2>/dev/null |grep -v "Listing" |grep -v "Auflistung" 2>/dev/null) # Ausgabe der möglichen Updates updates_possible=$(apt list --upgradable 2>/dev/null |grep -v "Listing" |grep -v "Auflistung" 2>/dev/null | wc -l) # Anzahl der möglichen Updates update_list="$update_output" # Liste der möglichen Updates root_free=$(df -h / | awk 'NR==2 {print $4}') # Freier Speicherplatz auf der Root-Partition # Führen Sie die Funktion zum Einfügen oder Aktualisieren von Daten in die PostgreSQL-Tabelle aus insert_or_update_data "$server_ip" "$debian_version" "$updates_possible" "$update_list" "$root_free" echo "Daten erfolgreich in die PostgreSQL-Tabelle eingefügt oder aktualisiert."
- Einrichtung eines Satellitenserver:
mkdir /local wget http://192.168.66.31/patch/patch.sh -O /local/patch.sh chmod 777 /local/patch.sh echo "59 * * * * /local/patch.sh > /dev/null 2>&1" >> /var/spool/cron/crontabs/root /local/patch.sh
- Nun kann die erstellte Webseite (index.php) mit einem Browser aufgerufen werden.
- Jeder neue Satellit muss mit einem Klick auf den Button „connect-SSH“ zuerst verbunden werden.
- Danach kann er mit dem Button Update-Server aktualisiert werden.
- erzeugen des Skripts für die Satellite-Server (/var/www/html/patch/patch.sh)
-
-