Skip to content

Instantly share code, notes, and snippets.

@rogeriotaques
Last active July 20, 2020 01:43
Show Gist options
  • Save rogeriotaques/7ed47ef66631e8455a97c33423c54361 to your computer and use it in GitHub Desktop.
Save rogeriotaques/7ed47ef66631e8455a97c33423c54361 to your computer and use it in GitHub Desktop.
Security package watcher in PHP
<?php
/**
* This script checks for security updates in the server and
* it's expected to be scheduled for a daily run.
*
* It will notify the $notify address if one or more security
* package updates are found.
*/
function exceptionErrorHandler($errNo, $errStr, $errFile, $errLine ) {
if (error_reporting() == 0) {
// @ sign temporary disabled error reporting
return;
}
throw new ErrorException($errStr, 0, $errNo, $errFile, $errLine);
} // exceptionErrorHandler
set_error_handler("exceptionErrorHandler");
// Who is sending the notification
$sender = 'admin@domain.tld';
// To who the notification will be sent
$notify = 'you@domain.tld';
// Give a name to identify your server. Usually the hostname.
$server = 'domain.tld';
// What mounted disk should be checked
$mountedDisk = '/dev/sda'; # '/dev/disk1s1' when macOS;
// What's the maximum usage before sending a notification for disk over usage
$diskUsageBoundary = 80; # %
// #############################################
// ### DON'T CHANGE ANYTHING FROM THIS POINT ###
// ### UNLESS YOU KNOW WHAT YOU'RE DOING ###
// #############################################
// If this file exist, a reboot is required
$reboot = file_exists('/var/run/reboot-required');
$matches = [];
// Gather info about available updates
// $note = @file_get_contents('/var/lib/update-notifier/updates-available');
// $note = preg_replace("/\n/", " ", $note);
try {
// Gather info about available updates
$note = file_get_contents('/var/lib/update-notifier/updates-available');
$note = preg_replace("/\n/", " ", $note);
// Gather info about disk usage
$res = exec("df -h | grep {$mountedDisk}");
$res = preg_replace('/\s{2,}/', ' ', $res);
$intUsedRate = 0;
$usedRate = null;
if (!empty($res) && $res) {
list($mountPoint, $totalSize, $usedSpace, $freeSpace, $usedRate) = explode(' ', $res);
$intUsedRate = (int) preg_replace('/[^0-9]/i', '', $usedRate);
}
// Clear used rate when not passed the boundary
if ($diskUsageBoundary > $intUsedRate) {
$usedRate = null;
}
// Set a flag to control whether to send or not send a notification
$shouldNotify = (bool) (preg_match("/\d+\supdates?/i", $note, $matches) || !empty($usedRate) || $reboot);
// Notify when needed
if ($shouldNotify) {
$headers = "From: {$sender} \n";
$body = [
"This is an automated message. \n",
];
$count = (int) preg_replace("/[^0-9]/i", '', $matches[0]);
if ($count) {
$body[] = "{$count} pending security updates has been found.";
}
if (!empty($usedRate)) {
$body[] = "{$mountedDisk} is {$usedRate} used. Needs an urgent review.";
$body[] = "As general it is like: ";
exec("df -h", $out);
$body[] = "\t" . implode("\n\t", $out);
}
if ($reboot) {
$body[] = "** A reboot is required. **";
}
$body[] = "Please review the '{$server}' server ASAP.";
// echo implode("\n", $body) . "\n";
mail($notify, "Server '{$server}' Pending Review", implode("\n", $body) . "\n", $headers, "-f {$sender}");
// For automated updates, if there're security package updates
// it can be automatically ran with :
// sudo unattended-upgrade -d # verbose or
// sudo unattended-upgrade # quitely
}
} cacth(Exception $e) {
$body = "Error Code: {$e->getCode()}\n\nDescription: {$e->getMessage()}\n";
mail($notify, "Server '{$server}' updates review failed", $body, $headers, "-f {$sender}");
}
echo "Daily updates review complete. \n";
@rogeriotaques
Copy link
Author

Hey @MESWEB! Thank you for contributing and sharing the link, now I few the comment is way more constructive! ;) I'm updating the Gist with an implementation that doesn't use the @. 🍻 R.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment