scripts/app/check.forticlient.update

330 lines
10 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh
# Purpose {{{
## Create a temp file (to monitor) if an upgrade is available for Forticlient
## from official website.
## Get version number from forticlient_vpn package link :
## https://www.fortinet.com/fr/support/product-downloads#vpn
## It's based on .deb package installation to check the current version.
## It can also compare the current available version in APT repositories
## if "repo" is given as first argument.
## If a new version is available, the script will try to download it.
## How-to use {{{
### 1. Create a cron job, eg:
#00 20 * * * root /opt/repos/ipr.scripts/app/check.forticlient.update
### 2-1 Create a cron job to compare the version available in an APT repository:
#00 20 * * * root /opt/repos/ipr.scripts/app/check.forticlient.update --mode repo
### 2. Monitor the temp file: /tmp/.forticlient.upgrade
# Or enable MAILTO in cronjob and edit the script to print a message.
# Or send a mail.
# …
## }}}
# }}}
# Vars {{{
PROGNAME=$(basename "${0}"); readonly PROGNAME
PROGDIR=$(readlink -m $(dirname "${0}")); readonly PROGDIR
ARGS="${*}"; readonly ARGS
readonly NBARGS="${#}"
[ -z "${DEBUG}" ] && DEBUG=0
## Export DEBUG for sub-script
export DEBUG
## Default values for some vars
CHECK_MODE_DEFAULT="file"
## Colors
readonly PURPLE='\033[1;35m'
readonly RED='\033[0;31m'
readonly RESET='\033[0m'
readonly COLOR_DEBUG="${PURPLE}"
# }}}
usage() { # {{{
cat << HELP
usage: $PROGNAME [check_mode] [-m|-d|-h]
Compare current version of an installed Forticlient and the last available.
EXAMPLES:
- Compare the current version of Forticlient installed from a .deb file
${PROGNAME}
${PROGNAME} --mode file
- Compare the current version of Forticlient available in the APT repo
${PROGNAME} repo
${PROGNAME} --mode repo
OPTIONS:
-m,--mode
Set the check_mode to use to get current version of Forticlient client
Available mode :
* repo
* file (default behaviour)
-d,--debug
Enable debug messages.
-h,--help
Print this help message.
HELP
}
# }}}
debug_message() { # {{{
local_debug_message="${1}"
## Print message if DEBUG is enable (=0)
[ "${DEBUG}" -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' "DEBUG ${PROGNAME}: ${local_debug_message}"
unset local_debug_message
return 0
}
# }}}
error_message() { # {{{
local_error_message="${1}"
local_error_code="${2}"
## Print message
printf '%b\n' "ERROR ${PROGNAME}: ${RED}${local_error_message}${RESET}"
unset local_error_message
exit "${local_error_code:=66}"
}
# }}}
is_var_empty() { # {{{
## Return False by default
return_var_empty="1"
## Total number of variables to test
local_total_var_empty="${#}"
loop_count_var_empty="0"
## While it remains a variable to test
while [ "${local_total_var_empty}" -gt "${loop_count_var_empty}" ]; do
debug_message "is_var_empty \
Test var: ${RED}${1}${COLOR_DEBUG}."
### Test if this is empty and set return value to True
[ -z "${1}" ] && return_var_empty="0"
### Increase the number of tested variables
loop_count_var_empty=$((loop_count_var_empty+1))
### Shift to the next variable
shift
done
unset local_total_var_empty
unset loop_count_var_empty
return "${return_var_empty}"
}
# }}}
define_vars() { # {{{
## If check_mode wasn't defined (argument) {{{
## Use default value
is_var_empty "${check_mode}" \
&& debug_message "define_vars Use default value (${CHECK_MODE_DEFAULT}) for check_mode variable." \
&& check_mode="${CHECK_MODE_DEFAULT}"
## }}}
## Get forticlient_current_version according to the check_mode {{{
case "${check_mode}" in
"repo" ) ## Check forticlient version from repository
forticlient_current_version=$(apt-cache policy -- forticlient | awk '/Candidate:/ {print $2}' | sed 's/.:\(.*\)-.*/\1/')
;;
"file" ) ## Check forticlient version from installed .deb file
forticlient_current_version=$(dpkg --list -- forticlient | awk '/^ii *forticlient/ {print $3}' | sed 's/.:\(.*\)-.*/\1/')
;;
* ) ## unknow mode
error_message "define_vars Invalid check mode: ${check_mode}" 1
;;
esac
## If forticlient_current_version is empty
is_var_empty "${forticlient_current_version}" \
&& error_message "define_vars Error with forticlient_current_version variable (${forticlient_current_version})" 2
## }}}
## Forticlient vars for new version {{{
## Fortinet offer "always" the same URL to download .deb package.
## This URL can be expanded to get package version
forticlient_new_version_expanded_url=$(curl --silent https://unshorten.me/s/https://links.fortinet.com/forticlient/deb/vpnagent)
forticlient_new_version=$(echo "${forticlient_new_version_expanded_url}" | sed -e 's/http.*forticlient_vpn_\(.*\)_amd64.deb/\1/')
is_var_empty "${forticlient_new_version_expanded_url}" "${forticlient_new_version}" \
&& error_message "define_vars Error with new version variables (forticlient_new_version_expanded_url: ${forticlient_new_version_expanded_url} ; forticlient_new_version: ${forticlient_new_version})." 3
## }}}
## Vars for temp files
forticlient_new_version_file="/tmp/.forticlient.upgrade"
forticlient_new_pkg_path="/tmp/forticlient_${forticlient_new_version}_amd64.deb"
forticlient_tmp_pkg_path="/tmp/.forticlient_${forticlient_new_version}_amd64.deb"
}
# }}}
is_version_greater_than() { # {{{
first_value="${1}"
value_to_compare="${2}"
## Return False by default
return_is_version_greater_than="1"
debug_message "is_version_greater_than \
Is first value (${first_value}) greater than the second value (${value_to_compare})."
if printf '%s\n' "${first_value}" "${value_to_compare}" | sort --check=quiet --version-sort; then
debug_message "is_version_greater_than ${first_value} <= ${value_to_compare} ."
return_is_version_greater_than="1"
else
debug_message "is_version_greater_than ${first_value} > ${value_to_compare} ."
return_is_version_greater_than="0"
fi
unset first_value
unset value_to_compare
return "${return_is_version_greater_than}"
}
# }}}
main() { # {{{
define_vars
# Behaviour can be tested by overriding this variable
#forticlient_current_version="7.0.0.0000"
#forticlient_current_version="${forticlient_new_version}"
#forticlient_current_version="9.9.9.9999"
if is_version_greater_than "${forticlient_new_version}" "${forticlient_current_version}"; then
debug_message "Test version \
New version (${forticlient_new_version}) seems more recent than the current one (${forticlient_current_version})."
## If it doesn't already exists, download the package for this new version
if [ ! -f "${forticlient_new_pkg_path}" ]; then
debug_message "Deb file \
Download .deb file from fortinet.com to ${forticlient_new_pkg_path} ."
wget --quiet https://repo.fortinet.com/repo/7.0/debian/pool/non-free/f/forticlient/forticlient_"${forticlient_new_version}"_amd64.deb --output-document="${forticlient_new_pkg_path}"
fi
# Verify downloaded package
# Check the version from dpkg info {{{
forticlient_dpkg_version=$(dpkg --info -- "${forticlient_new_pkg_path}" | awk '/ Version/ { print $2 }')
if [ "${forticlient_dpkg_version}" = "${forticlient_new_version}" ]; then
debug_message "Check dpkg version \
New version and .deb file informations are similar."
## Create a temp file to monitor
touch -- "${forticlient_new_version_file}"
printf '\e[1;35m%-6s\e[m\n' "An upgrade is available for forticlient (current: ${forticlient_current_version}): ${forticlient_new_version}." >> "${forticlient_new_version_file}"
## Exit
exit 0
else
debug_message "Check dpkg version \
New version and .deb file informations mismatch, don't need to go further."
# }}}
# Remove useless file {{{
## Ensure to remove the file to monitor
rm --force -- "${forticlient_new_version_file}"
## Keep a record of the downloaded package because as a new release might come soon
mv --force -- "${forticlient_new_pkg_path}" "${forticlient_tmp_pkg_path}"
## Exit
exit 0
fi
# }}}
else
debug_message "Test version The current version is the same or is more recent than the available one."
## Ensure to remove any temp file and useless .deb file
rm --force -- "${forticlient_new_version_file}" "${forticlient_new_pkg_path}" "${forticlient_tmp_pkg_path}"
## Exit
exit 0
fi
# }}}
}
# }}}
# Manage arguments # {{{
# This code can't be in a function due to arguments
if [ ! "${NBARGS}" -eq "0" ]; then
manage_arg="0"
## If the first argument is not an option
if ! printf -- '%s' "${1}" | grep --quiet --extended-regexp -- "^-+";
then
## Consider it as the mode to use to get current forticlient version
check_mode="${1}"
## Move to the next argument
shift
manage_arg=$((manage_arg+1))
fi
# Parse all options (start with a "-") one by one
while printf -- '%s' "${1}" | grep --quiet --extended-regexp -- "^-+"; do
case "${1}" in
-m|--mode ) ## Define check_mode
## Move to the next argument
shift
## Define var
readonly check_mode="${1}"
;;
-d|--debug ) ## debug
DEBUG=0
;;
-h|--help ) ## help
usage
## Exit after help informations
exit 0
;;
-- ) ## End of options list
## End the while loop
break
;;
* ) ## unknow option
printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
printf '%b\n' "---"
usage
exit 1
;;
esac
debug_message "Arguments management \
${RED}${1}${COLOR_DEBUG} option managed."
## Move to the next argument
shift
manage_arg=$((manage_arg+1))
done
debug_message "Arguments management \
${RED}${manage_arg}${COLOR_DEBUG} argument(s) successfully managed."
else
debug_message "Arguments management \
No arguments/options to manage."
fi
# }}}
main
exit 255