pfSense Update Checker

Intro

I LOVE pfSense!
However the one thing I found missing in pfSense is the ability to notify me when an update is available.

After searching the net, I found a Spanish script that will notify me by e-mail when an update of pfSense or any of the installed packages has a newer version available.

Javier Castañon wrote the script I found in 2016 but sadly his site is no longer available. 🙁

I have edited and cleaned up and translated the code to be a bit more international (read: English) and formatted the notification e-mail that is generated.
Here is how the notification e-mail looks like:

UpdateChecker v0.1 is checking for pfSense platform and packages updates.

Checking host:
mypfsense.host.com

Checking pfSense version:
- Installed Version: 2.4.4_3
- Available Version: 2.4.4_3
The system is on the latest version.

Checking installed packages:
pfSense-pkg-acme [0.6.3] : Installed package is Up To Date
pfSense-pkg-Backup [0.5_2] : Installed package is Up To Date
pfSense-pkg-Cron [0.3.7_3] : Installed package is Up To Date
All Packages is up to date.

Installing the script is not the easiest, but I will try to explain it on this page.

(I really hope someone will make a pfSense package with this feature, but in the meantime this has to do..)

Prerequisites

  • pfSense installed and working.. 😉
  • The script needs to be run to check and send notification, so the ‘Cron’ package should be installed.
  • You should have configured and tested the notification e-mail under:
    ‘System’ -> ‘Advanced’ -> ‘Notification’ -> ‘E-Mail’

Installation

So first, to create the script file on your pfSense box.

  • Log in to your pfSense box and from the ‘Diagnostics’ menu choose ‘Edit file’.
  • From here, click in the textbox ‘Path to file to be edited’ and put in:
    /usr/games/updatechecker.php‘ (Without the quotes)
    and paste the script in the big text window below.
    (You can find the script at the bottom of this page)
  • Then click ‘Save’
    The file will now be created on the pfSense box in the ‘games’ folder.
  • Next, we will need to schedule the script to run at some interval. I have mine set up to run daily in the morning. This should be sufficient.
    Keep in mind that the script will send an email every time it is run if there is an update, so if you have it check too often, it will spam you with e-mail when updates are available.

I recommend using the pfSense Package ‘CRON’ to set up the scheduling of the script.

  • Go to ‘System’ -> ‘Package Manager’ and click on ‘Available packages’.
    Find or search for ‘Cron’ and install this package.

After installing ‘Cron’ you will find ‘Cron’ under the ‘Services’ menu.

  • Open ‘Cron’ from the ‘Services’ menu and click ‘Add’
    In the ‘Add a cron schedule’ form, put in the time you want to run the script.

My recommended setting are:

Minute: 0
Hour: 9
Day of the Month: *
Month of the Year: *
Day of the Week: *
User: root
Command: /usr/local/bin/php /usr/games/updatechecker.php 2>&1

It is important that the ‘Command’ field points to the correct file:
/usr/local/bin/php /usr/games/updatechecker.php 2>&1

  • Click ‘Save’ and you are done.

This setup will run the script every morning at 09:00 and will send you an e-mail if there are newer versions of pfSense or any of the installed packages.

Testing:

To test the script, you need to edit the file:
(Diagnostics->Edit File->Browse to /usr/games/updatechecker.php)

  • Edit the line:
    $sendemailalways = "false"; and change "false" to "true"
    and click ‘Save’

This will make the script send an e-mail when it is run even if there are no updates available.

  • To run the script manually, click the ‘Diagnostics’ menu and choose ‘Command Prompt’
  • In the ‘Execute Shell Command’ put(paste) in
    /usr/local/bin/php /usr/games/updatechecker.php 2>&1

This should only generate a blank Shell Output. However you should receive an e-mail right after executing the script.

You can also check the system log under ‘Status’ -> ‘System logs’.
There should be two entries for when the script checked the system and packages for updates.

REMEMBER to change the script line $sendemailalways = "true"; back to "false" and ‘Save’ or you will receive an email every time the script is run.

The Script:

<?php
/*
###############################################
#       "/usr/games/updatechecker.php"        #
# ------------------------------------------  #
#             UpdateChecker  v0.1             #
# Check pfSense System and installed packages #
# for updates, and sends an notification mail #
# --------------------------------------------#
#      Modified and adapted code from:        # 
#   "/usr/local/www/pkg_mgr_installed.php"    #
#   and "mail_package_platform_status.php"    #
#  by JavCasta - PIyMenta - Javier Castañon   #
#       2016 --- https://javcasta.com/        #
#                                             #
#        Edited by Torstein Wikene            #
#               2018 - 2019                   #
###############################################
#       Tested in - pfSense 2.4.4 amd64       #     
###############################################

Necessary conditions:
-----------------------
- Having configured and operational:
  System > Advanced > Notifications > E-Mail

- Put this file "updatechecker.php" in:
  /usr/games/
- Create a cron job running every day or every 12 or 24 hrs: (I recommend the package 'cron' to perform this)
  Cron Command:
  /usr/local/bin/php /usr/games/updatechecker.php 2>&1
  
*/


// If you want to recieve email even if everything is Up To Date, set this to "true"
$sendemailalways = "false";







/*
*********************************
** Do not edit below this line **
*********************************
*/

require_once("pkg-utils.inc");
//Set up script name:
$scriptname = "UpdateChecker v0.1";
//Start the Email Body Variable:
$emailbody = $scriptname . " is checking for pfSense platform and packages updates. \n";
//Set variable default for if mail should be sent.
$sendemail = "false";

//Get pfSense name
$pfsensehostname = gethostname();
$emailbody .= "\nChecking host: \n$pfsensehostname \n";

//Check to see if packages is beeing updated
if (is_subsystem_dirty('packagelock')) {
	shell_exec("logger -f /var/log/system.log '" . $scriptname . " (System): Packages are being updated'");
	exit;
}

//Check if there is an update to pfSense System
$statustext = "";
$system_version = get_system_pkg_version();
if ($system_version === false) {
    $statustext = "Unable to check for updates \n";
}
if (!is_array($system_version) ||
	    !isset($system_version['version']) ||
	    !isset($system_version['installed_version'])) {
    $statustext = "Error in version information";
	exit;
}
$version_compare = pkg_version_compare($system_version['installed_version'], $system_version['version']);
         
switch ($version_compare) {
	case '<':
		$statustext = "The system is not on the latest version";
		break;
	case '=':
		$statustext = "The system is on the latest version.";
		break;
	case '>':
		$statustext = "The system is on a later version than the official release.";
		break;
	default:
		$statustext = "Error comparing installed version with latest available.";
		break;
}
$emailbody .= "\nChecking pfSense version:\n- Installed Version: ".$system_version['installed_version']."\n- Available Version: ".$system_version['version']."\n".$statustext."\n";
 
if (strpos($statustext, "The system is not on the latest version") !== false) {
	$sendemail = "true";
	$emailbody .= "System update is available, please update pfSense to the latest version.\n";
    shell_exec("logger -f /var/log/system.log '" . $scriptname . " (System): Installed Version: ".$system_version['installed_version']."- Available Version: ".$system_version['version'].". System update is available, Sending notification.'");
} ELSE {
	shell_exec("logger -f /var/log/system.log '" . $scriptname . " (System): ".$statustext."'");
}
    

//Check installed packages
$pkgstate = get_pkg_status();
$emailbody .= "\nChecking installed packages:\n". $pkgstate;

//If Update available
if (strpos($pkgstate, "Upgrade available") !== false) {
    //Update IS available
	$sendemail = "true";
	$emailbody .= "Some packages is NOT up to date and attention is needed!";
    shell_exec("logger -f /var/log/system.log '" . $scriptname . " (Packages): Some packages is NOT up to date, Sending notification.'");
} else {
	$emailbody .= "All Packages is up to date.";
    shell_exec("logger -f /var/log/system.log '" . $scriptname . " (Packages): All Packages is up to date.'");
}


//Send email if an update to pfSense OR Packages is available
if ($sendemail == 'true') {
    //echo $emailbody;
    $cmd = "echo " . '"' . $emailbody . '"' . ' | ' . "/usr/local/bin/mail.php -s=". '"' . "UPDATES AVAILABLE for pfSense : $pfsensehostname" . '"';
    shell_exec("$cmd");
} ELSE {
    //echo $emailbody;
	if ($sendemailalways == 'true' || strpos($emailbody, "[Error]") !== false) {
        $cmd = "echo " . '"' . $emailbody . '"' . ' | ' . "/usr/local/bin/mail.php -s=". '"' . "Version Status for pfSense : $pfsensehostname" . '"';
        shell_exec("$cmd");	
	}
}

//###########################
//######## Functions ########
//###########################


function get_pkg_status() {
	$installed_packages = array();
	$package_list = get_pkg_info();

	if (!$package_list) {
		//An error occurred
		return "[Error] - Unable to get list of packages.\n";
		exit;
	}

	foreach ($package_list as $pkg) {
		if (!isset($pkg['installed']) && !isset($pkg['broken'])) {
			continue;
		}
		$installed_packages[] = $pkg;
	}

	$pkgtbl = "";

	if (empty($installed_packages)) {
		//No installed packages found
		return "No installed packages found!\n";
		exit;
	}
  
	
	foreach ($installed_packages as $pkg) {
		if (!$pkg['name']) {
			continue;
		}

		#check package version
		if (isset($pkg['broken'])) {
			// package is configured, but does not exist in the system
			$status = $pkg['name']. ' : ' . gettext('Package is configured, but not installed!');
		} else if (isset($pkg['installed_version']) && isset($pkg['version'])) {
			// Package found, lets compare versions
			$version_compare = pkg_version_compare($pkg['installed_version'], $pkg['version']);

			if ($version_compare == '>') {
				// we're running a newer version of the package
				$status = $pkg['name']. ' [' . $pkg['installed_version']. '] : '. gettext("Installed package is newer than available ") . $pkg['version'];
			} else if ($version_compare == '<') {
				// we're running an older version of the package
				$status = $pkg['name']. ' [' . $pkg['installed_version']. '] : '. gettext("Upgrade available to version ") . $pkg['version'];
			} else if ($version_compare == '=') {
				// we're running the current version
				$status = $pkg['name']. ' [' . $pkg['installed_version']. '] : ' . gettext('Installed package is Up To Date');
			} else {
				$status = gettext('[Error] - Error comparing version');
			}
		} else {
			// unknown available package version
			$status = $pkg['name']. gettext('[Unknown version]');
		}

		$pkgtbl .= $status . "\n";

	}

	return $pkgtbl;
}
?>