0x1949 Team - FAZEMRX - MANAGER
Edit File: imav-deploy.sh
#!/bin/bash # Short Description :Deploy imunify360/ImunifyAV # Description :Installs imunify360/ImunifyAV repository # Copyright :Cloud Linux Zug GmbH # License :Cloud Linux Commercial License # Do not edit/move/reformat this line except for actual version bump # it is used by old versions of deploy scripts to check for update version="2.112" readonly package="imunify-antivirus" readonly imunify360="imunify360-firewall" readonly imunify_av="imunify-antivirus" if [[ "$package" != "$imunify360" ]] && [[ "$package" != "$imunify_av" ]]; then exit 1 fi if [[ "$package" = "$imunify_av" ]]; then PRODUCT="ImunifyAV" UI_PACKAGE="imunify-ui-antivirus" COMMAND="imunify-antivirus" STAND_ALONE_URL="https://docs.imunifyav.com/stand_alone_mode" LOG_FILE="/var/log/imav-deploy.log" LOCK="/var/lock/imav-deploy.lck" # packages mentioned in the update command in the daily cron job readonly additional_packages_to_remove="ai-bolit\ alt-php-hyperscan\ imunify-common\ imunify-notifier\ imunify-core\ imunify-ui\ imunify360-venv\ alt-php-internal\ app-version-detector" readonly additional_packages_to_remove_cl="ai-bolit\ alt-php-hyperscan\ imunify-common\ imunify-notifier\ imunify-core\ imunify-ui\ imunify360-venv" readonly additional_packages_to_remove_centos="minidaemon" readonly additional_packages_to_remove_debian="" fi readonly YUM_DISABLED_PHP_REPOS_OPTION="--disablerepo=imunify360-alt-php,imunify360-ea-php-hardened" OS_RELEASE_INFO=/etc/os-release set -o pipefail # fail if any error: will not #set -e # error for unbound variable: not for now #set -eu # $1 = Message prompt # Returns ans=0 for yes, ans=1 for no yesno() { local YES=0 local NO=1 local PENDING=2 if [ $dry_run -eq 1 ]; then echo "Would be asked here if you wanted to" echo "$1 (y/n - y is assumed)" local ans=$YES elif [ "$assumeyes" = "true" ]; then local ans=$YES else local ans=$PENDING fi while [ $ans -eq $PENDING ]; do echo "Do you want to $1 (y/n) ?" ; read -r reply case "$reply" in Y*|y*) ans=$YES ;; N*|n*) ans=$NO ;; *) echo "Please answer y or n" ;; esac done return "$ans" } prepend_timestamp() { # Prepend current time to each line # # Usage: source-program | prepend_timestamp # # Note: it may fail if the input contains \0 bytes while IFS= read -r line do printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$line" done } log() { # Run given command and append its duplicated stdout/stderr to # $LOG_FILE. # # Usage: log <command> [<args>...] # "$@" |& prepend_timestamp | tee -a "$LOG_FILE" return "${PIPESTATUS[0]}" } exit_with_error() { log echo -e "$@" rm -rf "$lock" exit 1 } print_debug_info() { if [ "$DEBUG" == "true" ]; then echo "$@" fi } set_panel_detection_path() { readonly CPANEL_BIN="/usr/local/cpanel/cpanel" readonly DA_BIN="/usr/local/directadmin/directadmin" readonly PLESK_BIN="/usr/sbin/plesk" readonly INTEGRATION_CONF_PATH="/etc/sysconfig/imunify360/integration.conf" } detect_python () { # python executable is not present in CentOS 8 if hash python2 2>/dev/null; then PYTHON=python2 CONFIG_PARSER="ConfigParser" elif hash python3 2>/dev/null; then PYTHON=python3 CONFIG_PARSER="configparser" else exit_with_error "Neither python2 nor python3 executables found" fi } detect_panel () { # note: keep the panel test order in sync with agent's get_hosting_panel(), # to avoid detecting conflicting panels in agent vs. the deploy script PANEL="" if [ -f "$INTEGRATION_CONF_PATH" ] ; then PANEL="generic" elif [ -f "$PLESK_BIN" ]; then PANEL="plesk" elif [ -f "$CPANEL_BIN" ]; then PANEL="cpanel" elif [ -f "$DA_BIN" ]; then PANEL="directadmin" else exit_with_error "$PRODUCT has not detected any compatible hosting panel as well as integration.conf file to run the installation without a panel. \ Please, follow the instructions on $STAND_ALONE_URL" fi print_debug_info "$PANEL panel was detected." } # Only for imunify360-firewall set_low_resource_usage_mode_if_necessary() { local _package=$1 local _package_version=$2 imunify360_low_mem_limit=2147483648 imunify360_python38_datadir=$venv_path/share/imunify360 # total usable memory in bytes mem_total=$(</proc/meminfo awk '$1 == "MemTotal:" { printf "%.0f", $2 * 1024 }') if (( mem_total < imunify360_low_mem_limit )); then # enable "Low Resource Usage" mode local low_mem_config="$imunify360_python38_datadir/20-low-mem-settings.config" if [ -f "$low_mem_config" ]; then log echo "Installing $low_mem_config from $_package $_package_version" ln -s "$low_mem_config" /etc/sysconfig/imunify360/imunify360.config.d/ && log echo "Done." fi fi } populate_os_release_vars() { # shellcheck source=/etc/os-release [ -f "$OS_RELEASE_INFO" ] && source "$OS_RELEASE_INFO" } detect_ostype() { echo -n "Detecting ostype... " if [ ! -f "$OS_RELEASE_INFO" ]; then ostype=centos else populate_os_release_vars if echo "$ID" "$ID_LIKE" | grep debian >/dev/null then ostype=debian else ostype=centos fi fi echo $ostype } is_ubuntu() { populate_os_release_vars [ "$ID" == "ubuntu" ] } is_debian() { populate_os_release_vars [ "$ID" == "debian" ] } UNSUPPORTED_OS_MSG="You are running an unsupported OS. $PRODUCT supports only x86_64 processors." check_debian_release() { populate_os_release_vars if is_debian && ([ "$VERSION_ID" -lt 10 ] || [ "$VERSION_ID" -gt 12 ]) then exit_with_error "You are running unsupported version of debian based OS. $PRODUCT supports only Debian [10, 11, 12]" fi if is_ubuntu && [ "$VERSION_ID" != 16.04 ] && [ "$VERSION_ID" != 18.04 ] && [ "$VERSION_ID" != 20.04 ] && [ "$VERSION_ID" != 22.04 ] then exit_with_error "You are running unsupported version of debian based OS. $PRODUCT supports only Ubuntu 16.04, 18.04, 20.04 and 22.04" fi if [ "$(uname -m)" != x86_64 ] then exit_with_error "$UNSUPPORTED_OS_MSG" fi } check_centos_release() { rpm -q --whatprovides redhat-release > /dev/null 2>&1 check_exit_code 0 "There is no package providing /etc/redhat-release, please install redhat-release or centos-release first" ARCH=$(uname -i) # handle 32bit xen with x86_64 host kernel if (! rpm -q glibc.x86_64 > /dev/null 2>&1) || [ "$ARCH" != "x86_64" ] ; then exit_with_error "$UNSUPPORTED_OS_MSG" fi check_centos_compatible check_virtuozzo_compatible } check_virtuozzo_compatible() { if [ -f /proc/vz/vestat ]; then if version "$(uname -r)" -lt "$VZ_VERSION_BRIEF"; then echo "You are inside VZ." echo "Virtuozzo 7 with kernel $VZ_VERSION_LONG or later has support for ipset in Containers." exit_with_error "Please upgrade your OpenVZ hypervisor kernel version to $VZ_VERSION_LONG or later." fi fi } check_centos_compatible() { local os_version="${1:-$(rpm --eval '%{rhel}')}" # shellcheck disable=SC2015 [ "${os_version}" -lt 10 ] 2>/dev/null && [ "${os_version}" -gt 5 ] || \ exit_with_error "Only CentOS/CloudLinux 6, 7, 8 and 9 are supported at the moment, but got os_version='${os_version}'" } check_exit_code() { if [ $? -ne "$1" ]; then exit_with_error "$2"; fi; } disable_3rd_party_ids() { if [ -d "$venv_path" ]; then echo "imunify360-venv detected" imunify360_python38_datadir=$venv_path/share/imunify360 fi if [ -d "$imunify360_python38_datadir" ]; then datadir="$imunify360_python38_datadir" else datadir="$imunify360_python35_datadir" fi $datadir/scripts/disable_3rd_party_ids } install_first_install_default_overrides() { local first_install_package=$1 local package_version=$2 if [ -d "$venv_path" ]; then echo "imunify360-venv detected" imunify360_python38_datadir=$venv_path/share/imunify360 fi local first_install_config_deprecated="$imunify360_python38_datadir/10_on_first_install.config" local first_install_config_core="$imunify360_python38_datadir/10_on_first_install_core.config" local first_install_config_av="$imunify360_python38_datadir/10_on_first_install_av.config" local first_install_config_ids="$imunify360_python38_datadir/10_on_first_install_ids.config" if [ -f "$first_install_config_deprecated" ]; then log echo "Installing $first_install_config_deprecated from $first_install_package $package_version" cp -v "$first_install_config_deprecated" /etc/sysconfig/imunify360/imunify360.config.d/ && log echo "Done." else log echo "Installing $first_install_config_core from $first_install_package $package_version" cp -v "$first_install_config_core" /etc/sysconfig/imunify360/imunify360.config.d/ && log echo "Done." log echo "Installing $first_install_config_av from $first_install_package $package_version" cp -v "$first_install_config_av" /etc/sysconfig/imunify360/imunify360.config.d/ && log echo "Done." if [[ "$package" = "$imunify360" ]]; then log echo "Installing $first_install_config_ids from $first_install_package $package_version" cp -v "$first_install_config_ids" /etc/sysconfig/imunify360/imunify360.config.d/ && log echo "Done." fi fi } remove_first_install_default_overrides() { unlink /etc/sysconfig/imunify360/imunify360.config.d/10_on_first_install.config 2>/dev/null || true unlink /etc/sysconfig/imunify360/imunify360.config.d/10_on_first_install_core.config 2>/dev/null || true unlink /etc/sysconfig/imunify360/imunify360.config.d/10_on_first_install_av.config 2>/dev/null || true unlink /etc/sysconfig/imunify360/imunify360.config.d/10_on_first_install_ids.config 2>/dev/null || true } init_vars() { wget="/usr/bin/wget" wget_options="-q --retry-connrefused --waitretry=15 --read-timeout=20 --timeout=15 -t 15" uninstall=false conversion=false beta=false install_vendors=false freemium=false # get full path to the current script script="$1" case "$script" in ./*) script="$(pwd)/${script#*/}" ;; /*) script="$script" ;; *) script="$(pwd)/$script" ;; esac scriptname=$(basename "$script") script_run_args="$2" # Update checker URL checksite="https://repo.imunify360.cloudlinux.com/defense360/" checksite_forcurl='https://defense360:nraW!F%40%24x4Xd6HHQ@repo.imunify360.cloudlinux.com/defense360/' upgradeurl="$checksite$scriptname" dry_run="0" assumeyes=false modifying_call=false yum_beta_option="" yum_beta_repo_enable=0 apt_force="" apt_allow_unauthenticated="" if [[ "$package" = "$imunify360" ]]; then # Virtuozzo 7 with kernel 3.10.0 or later has support for ipset in Container VZ_VERSION_LONG=3.10.0-327.10.1.vz7.12.8 # Inside VZ version is provided without release VZ_VERSION_BRIEF=3.10.0 readonly imunify360_python35_datadir=/opt/alt/python35/share/imunify360 fi imunify360_python38_datadir=/opt/alt/python38/share/imunify360 venv_path=/opt/imunify360/venv } version() { local lhs=$1 local op=$2 local rhs=$3 case $op in -lt) test "$(echo -e "$lhs\\n$rhs" | sort --version-sort | head -1)" = "$lhs" && \ test "$lhs" != "$rhs" return $? ;; *) echo "function version(): operator $op is not supported." return 2 ;; esac } check_package_version() { version="$1" if [ -z "$version" ]; then echo "No available package detected" return 1 else echo "$version" fi } get_available_debian_package_version() { version=$(apt-cache policy "$1" 2>/dev/null | sed -n '3p' | awk '{split($0, candidate); print candidate[2]}') check_package_version "$version" return $? } get_available_centos_package_version() { version=$(yum $yum_beta_option $YUM_DISABLED_PHP_REPOS_OPTION list available "$1" 2>/dev/null | grep -E "$1.x86_64|$1.noarch" | awk '{split($0, candidate); print candidate[2]}' | sort --version-sort | tail -n 1) check_package_version "$version" return $? } check_integration_conf() { # # Check whether $INTEGRATION_CONF_PATH is sufficiently valid to continue the installation, exit with an error message otherwise # # Globals: # Uses (reads) $INTEGRATION_CONF_PATH; # Populates (writes) $PYTHON, $CONFIG_PARSER and uses them to parse $INTEGRATION_CONF_PATH ini-file # detect_python # sanity check: the integration.conf is a valid ini-like file $PYTHON -c "from $CONFIG_PARSER import ConfigParser; conf = ConfigParser(); conf.read('$INTEGRATION_CONF_PATH')" 2>/dev/null check_exit_code 0 "syntax error in $INTEGRATION_CONF_PATH \ Read the manual $STAND_ALONE_URL on how to create a valid config file. " # sanity check: ui_path should be present in the config local ui_path="$($PYTHON -c "from $CONFIG_PARSER import ConfigParser; conf = ConfigParser(); conf.read('$INTEGRATION_CONF_PATH'); print(conf.get('paths', 'ui_path'))" 2>/dev/null)" check_exit_code 0 "$PRODUCT has detected $INTEGRATION_CONF_PATH file from the stand-alone version of $PRODUCT. \ Stand-alone version requires \"ui_path\" parameter specified in the $INTEGRATION_CONF_PATH. \ Read the manual $STAND_ALONE_URL on how to create a valid config file. " # ui_path must not be empty if [ -z "$ui_path" ]; then exit_with_error "Could not get ui_path from $INTEGRATION_CONF_PATH. UI will not be installed. \ Please ensure that you have provided ui_path in $INTEGRATION_CONF_PATH \ More details is at $STAND_ALONE_URL." # even if ui_path doesn't refer to a directory (first install), # its parent directory must exist elif [ ! -d "$ui_path" ]; then # first install log mkdir -m 0700 "$ui_path" check_exit_code 0 "An error occurred during creating $ui_path directory. \ Possibly parent directory doesn't exist or path point to file" # symlinks are not supported (current behavior) elif [[ -L "$ui_path" ]]; then exit_with_error "ui_path specified in $INTEGRATION_CONF_PATH file $ui_path points to an existing symlink. \ Installation is aborted, to avoid overwriting it. \ ui_path must point to an empty web directory. More details is at $STAND_ALONE_URL." # ui_path dir must be empty or point to an existing imunify installation; # use bin/execute.py as a heuristic for detecting the agent install elif [[ -n "$(ls -A "$ui_path" 2>/dev/null)" ]] && [[ ! -e "$ui_path/bin/execute.py" ]]; then exit_with_error "ui_path specified in $INTEGRATION_CONF_PATH file $ui_path points to a non-empty directory. \ Installation is aborted, to avoid overwriting data in it. \ ui_path must point to an empty web directory. More details is at $STAND_ALONE_URL." fi # sanity check: panel_info should be present in the config $PYTHON -c "from $CONFIG_PARSER import ConfigParser; conf = ConfigParser(); conf.read('$INTEGRATION_CONF_PATH'); print(conf.get('integration_scripts', 'panel_info'))" 2>/dev/null if [ $? -ne "0" ]; then yesno "WARNING: integration_scripts.panel_info field will be mandatory soon, please refer to [documentation](https://docs.imunify360.com/control_panel_integration/#specifying-panel-information) and fill it! Do you want to continue? [y/N]" else # sanity check: panel_info must be a valid json with name and version fields in data object local panel_info=$($PYTHON -c "from $CONFIG_PARSER import ConfigParser; conf = ConfigParser(); conf.read('$INTEGRATION_CONF_PATH'); print(conf.get('integration_scripts', 'panel_info'))" 2>/dev/null) $panel_info | $PYTHON -c 'import sys,json; d=json.load(sys.stdin); print("Panel info:", d["data"]["name"], d["data"]["version"]);' check_exit_code 0 "panel_info script should be executable and return valid json with name and version fields in data object. Please refer to the [documentation](https://docs.imunify360.com/control_panel_integration/#specifying-panel-information)." fi } install_plugin() { local plugin_package=$1 local panel=$2 echo "Installing $PRODUCT $panel plugin..." install_${ostype}_pkgs "$plugin_package-$panel" check_exit_code 0 "Failed to install $PRODUCT $panel plugin." } install_ui_part() { local ui_package=$1 local panel=$2 echo "Installing UI part of $PRODUCT $panel plugin..." install_${ostype}_pkgs "$ui_package-$panel" check_exit_code 0 "Failed to install UI part of $PRODUCT $panel plugin." } check_and_install() { local package_to_install=$1 local package_version=$2 local ui_package=$3 local panel=$4 if version "$package_version" -lt "7.3"; then install_plugin "$package_to_install" "$panel" else if [[ "$package_to_install" = "$imunify360" ]]; then install_plugin $package_to_install $panel fi install_ui_part "$ui_package" "$panel" fi } check_hardened_php_status() { local agent_bin='/usr/bin/imunify360-agent' local python_bin='/opt/imunify360/venv/bin/python' local status=$(\ ${agent_bin} features status hardened-php --json |\ ${python_bin} -c 'import json; print(json.loads(input()).get("items", {}).get("status"))'\ ) echo ${status} } remove_hardened_php_feature() { local agent_bin='/usr/bin/imunify360-agent' local python_bin='/opt/imunify360/venv/bin/python' local timeout=900 if [ ! -f ${agent_bin} ] || [ ! -f ${python_bin} ]; then return fi if [ "$(check_hardened_php_status)" != "installed" ]; then return fi echo "Warning: Hardened PHP packages will be removed"\ "and replaced with the default ones if possible."\ "Some sites may stop working" echo -n "Starting removal, this may take a couple of minutes" local logfile="$(${agent_bin} features remove hardened-php)" local start_ts=$(date +%s) while true; do removal_status="$(check_hardened_php_status)" [ "${removal_status}" = "not_installed" ] && echo OK && break local current_ts=$(date +%s) if [ $((current_ts - start_ts)) -gt ${timeout} ]; then echo TIMEOUT exit_with_error "Error occured while trying to remove Hardened PHP packages."\ "See log: ${logfile}" fi echo -n "." sleep 5 done } install_vendors_in_cw_environment() { # log output but hide it from stdout log echo "Run vendor installation in background for Cloudways" file_path="/var/imunify360/files/modsec/v2/description.json" while [ ! -f "$file_path" ]; do log echo "Waiting for $file_path to appear" sleep 5 done log echo "Installing vendors" log /usr/bin/imunify360-agent --console-log-level=WARNING install-vendors } run_with_retries() { cmd=$1 expected_error_text=$2 ignore_res=$3 min_timeout=2 max_timeout=30 nattempts=10 for ((i=1;i<=nattempts;i++)); do output=$( { $cmd ; } 2>&1 ) res=$? if [ $res -eq 0 ] && [[ "$ignore_res" != "true" ]]; then echo "$output" break else if echo "$output" | grep -q "$expected_error_text"; then echo "$output" echo "Attempt #$i/$nattempts: to run $cmd." timeout=$(($RANDOM%($max_timeout-$min_timeout+1)+$min_timeout)) [ $i -ne $nattempts ] && echo "Retrying in $timeout seconds.." sleep $timeout else echo "$output" break fi fi done return $res } reopen_log() { echo "-- $(date -R): $script $script_run_args --" >> "$LOG_FILE" chmod 0600 "$LOG_FILE" } check_debian_pkg_presence() { test "$(dpkg-query --show --showformat='${db:Status-Status}\n' "$1" 2>/dev/null)" = "installed" } check_centos_pkg_presence() { rpm --query "$1" >/dev/null } remove_debian_imunify() { local pkgs_to_remove="$package $additional_packages_to_remove $additional_packages_to_remove_debian" # shellcheck disable=SC2086 apt-get remove --autoremove --ignore-missing --dry-run $pkgs_to_remove yesno "apt-get --AUTOREMOVE to remove $pkgs_to_remove plus \ aforementioned packages [y] or just $pkgs_to_remove [n]" local res=$? if [ $res = 0 ]; then local autoremove="--autoremove" else local autoremove="" fi # --ignore-missing doesn't work if apt doesn't know about package # shellcheck disable=SC2086 apt-get remove $autoremove -y --ignore-missing $(dpkg-query -W -f='${binary:Package}\n' $pkgs_to_remove 2>/dev/null) } remove_centos_imunify() { if rpm -q cloudlinux-release &>/dev/null; then local pkgs_to_remove="$package $additional_packages_to_remove_cl $additional_packages_to_remove_centos" else local pkgs_to_remove="$package $additional_packages_to_remove $additional_packages_to_remove_centos" fi yum remove -y $yum_beta_option $YUM_DISABLED_PHP_REPOS_OPTION \ $pkgs_to_remove --setopt=clean_requirements_on_remove=1 } remove_freemium_flag() { if [ ! -f "/var/imunify360/myimunify-freemium.flag" ]; then return fi rm -f "/var/imunify360/myimunify-freemium.flag" } get_debian_pkgs_manager() { pkgs_manager="apt-get" } get_centos_pkgs_manager() { pkgs_manager="yum" } remove_debian_pkgs() { run_with_retries "apt-get remove -y $*" "Could not get lock" } remove_centos_pkgs() { yum remove -y "$@" } install_debian_pkgs() { local pkgs=$* run_with_retries "apt-get $apt_opts install -y $apt_allow_unauthenticated $apt_force $pkgs" "" } install_centos_pkgs() { local pkgs=$* yum install -y $yum_beta_option $YUM_DISABLED_PHP_REPOS_OPTION $pkgs } install_debian_ipset() { install_debian_pkgs ipset } install_centos_ipset() { yum install -y ipset } detect_first_install() { if check_${ostype}_pkg_presence "$package" >/dev/null then first_install=false else first_install=true fi } is_systemctl_avail() { command -v systemctl >/dev/null 2>&1 } # $1 = Full URL to download # $2 = Optional basename to save to (if omitted, then = basename $1) # Also allow download to fail without exit if $2 is set download_file() { if [ "$2" = "" ]; then dlbase="$(basename "$1")" else dlbase="$2" fi if [ $dry_run -eq 1 ]; then echo "Would download this URL to $dlbase :" echo "$1" ; echo return fi old_dlbase="$dlbase.old" if [ -f "$dlbase" ]; then rm -f "$old_dlbase" mv -f "$dlbase" "$old_dlbase" fi echo "Downloading $dlbase (please wait)" $wget $wget_options -O "$dlbase" "$1" if [ ! -s "$dlbase" ]; then if [ -f "$old_dlbase" ]; then mv -f "$old_dlbase" "$dlbase" fi if [ "$2" = "" ]; then echo "Failed to download $dlbase" exit 1 fi fi } # Make sure that we are running the latest version # $* = Params passed to script check_version() { echo "Checking for an update to $scriptname" script_from_repo="$scriptname.repo_version" download_file "$upgradeurl" "$script_from_repo" newversion=$(grep "^version=" "$script_from_repo" | sed 's/[^0-9.]*//g') if [ -z "$newversion" ]; then newversion=$version fi if [ $dry_run -eq 1 ]; then echo -e "Would check if this running script (version $version) is out of date. \n" \ "If it's been superseded, the new version would be downloaded and you'd be asked \n" \ "if you want to upgrade to it and run the new version. \n" return fi local latest_version latest_version=$(echo -e "$version\\n$newversion" | sort --reverse --version-sort | head -1) if [ "$latest_version" = "$version" ]; then echo "$scriptname is already the latest version ($version) - continuing" rm -f "$script_from_repo" else echo "New version ($newversion) of $scriptname detected" if yesno "run $scriptname $newversion now" then echo "OK, executing $script_from_repo $*" # replace the current script with a new one mv -f "$script_from_repo" "$script" chmod u+x "$script" echo "Download of $scriptname $newversion successful" rm "$LOCK" echo "Run $script $script_run_args" # use $script_run_args without quotes to avoid error # `getopt: unrecognized option` if there are more than 1 arguments # shellcheck disable=SC2086 exec "$script" --skip-version-check $script_run_args error "Failed to run $script $script_run_args" else echo -e "New version of script is available: $upgradeurl \n" \ "It was downloaded to $script_from_repo \n" \ "If you prefer to use current version, run it with \"--skip-version-check\" key. \n" exit 1 fi fi } save_debian_repo() { log install_debian_pkgs gnupg $wget $wget_options -O- https://repo.imunify360.cloudlinux.com/defense360/RPM-GPG-KEY-CloudLinux \ | gpg --dearmor > /etc/apt/trusted.gpg.d/RPM-GPG-KEY-CloudLinux.gpg echo "deb [arch=amd64] https://repo.imunify360.cloudlinux.com/imunify360/$ID/$VERSION_ID/ $VERSION_CODENAME main" \ > /etc/apt/sources.list.d/imunify360.list if [ "$beta" = "true" ]; then echo "deb [arch=amd64] https://repo.imunify360.cloudlinux.com/imunify360/$ID-testing/$VERSION_ID/ $VERSION_CODENAME main" \ > /etc/apt/sources.list.d/imunify360-testing.list fi if ! log run_with_retries "apt-get update" ""; then test "$dev_install" = true check_exit_code 0 "apt-get update error." fi } save_centos_repo() { local RPM_KEY=$checksite/RPM-GPG-KEY-CloudLinux local RPM_KEY_forcurl=$checksite_forcurl/RPM-GPG-KEY-CloudLinux cat >/etc/yum.repos.d/imunify360.repo <<-EOF [imunify360] name=EL-\$releasever - Imunify360 baseurl=$checksite/el/\$releasever/updates/x86_64/ enabled=1 gpgcheck=1 gpgkey=$RPM_KEY EOF # add testing repo as disabled by default cat >/etc/yum.repos.d/imunify360-testing.repo <<-EOF [imunify360-testing] name=EL-\$releasever - Imunify360 baseurl=$checksite/el/\$releasever/updates-testing/x86_64/ enabled=$yum_beta_repo_enable gpgcheck=1 gpgkey=$RPM_KEY EOF log rpm --import "$RPM_KEY_forcurl" check_exit_code 0 "RPM import error." modifying_call=true } remove_debian_repo() { rm /etc/apt/sources.list.d/imunify360.list \ /etc/apt/sources.list.d/imunify360-testing.list \ /etc/apt/sources.list.d/imunify360-alt-php.list 2>/dev/null } remove_centos_repo() { rm /etc/yum.repos.d/imunify360.repo \ /etc/yum.repos.d/imunify360-testing.repo \ /etc/yum.repos.d/imunify360-ea-php-hardened \ /etc/yum.repos.d/imunify360-alt-php 2>/dev/null } remove_acronis_agent() { [ ! -e /usr/bin/restore_infected ] && return if /usr/bin/restore_infected acronis extra is_installed 2> /dev/null; then # If Acronis installation logs are present in restore_infected folder, # then remove Acronis and the logs if ls /var/restore_infected/acronis_installation*.log; then /usr/bin/restore_infected acronis extra uninstall > /dev/null || : rm -f /var/restore_infected/acronis_installation*.log fi fi } terminate_detached_scans () { for file in /var/imunify360/aibolit/run/*/pid; do test -e "$file" && kill -9 "$(cat "$file")" done rm -rf /var/imunify360/aibolit/run/ rm -rf /var/imunify360/aibolit/scans.pickle } # Only for imunify360-firewall check_users() { CHECK_GROUPS="ossec" CHECK_USERS="ossec ossecr ossecm ossece" SYS_GID_MAX=$(awk '/^SYS_GID_MAX/ {print $2}' /etc/login.defs) SYS_UID_MAX=$(awk '/^SYS_UID_MAX/ {print $2}' /etc/login.defs) # detect SYS_GID_MAX, SYS_UID_MAX indirectly (Ubuntu 16.04) GID_MIN=$(awk '/^GID_MIN/ {print $2}' /etc/login.defs) UID_MIN=$(awk '/^UID_MIN/ {print $2}' /etc/login.defs) if [ "$SYS_GID_MAX" = "" -a "$GID_MIN" != "" ]; then SYS_GID_MAX=$((GID_MIN - 1)) fi if [ "$SYS_UID_MAX" = "" -a "$UID_MIN" != "" ]; then SYS_UID_MAX=$((UID_MIN - 1)) fi for grp in $CHECK_GROUPS; do gid=$(getent group $grp 2> /dev/null | cut -d ':' -f 3) if [ -z "$gid" ]; then gid='-1' fi if [ "$SYS_GID_MAX" != "" ]; then if [ "$gid" -gt "$SYS_GID_MAX" ]; then exit_with_error "Non-system group $grp already exists" fi elif [ "$first_install" = "true" -a "$gid" != "-1" ]; then exit_with_error "Group $grp already exists" fi done for usr in $CHECK_USERS; do uid=$(id -u "$usr" 2>/dev/null || echo -1) if [ "$SYS_UID_MAX" != "" ]; then if [ "$uid" -gt "$SYS_UID_MAX" ]; then exit_with_error "Non-system user $usr already exists" fi elif [ "$first_install" = "true" -a "$uid" != "-1" ]; then exit_with_error "User $usr already exists" fi done } # Only for imunify360-firewall remove_hardened_php_repos() { if [[ $ostype = centos ]]; then ALT_PHP=imunify360-alt-php.repo EA_PHP=imunify360-ea-php-hardened.repo REPOS_DIR=/etc/yum.repos.d # fix permissions for REPO in $ALT_PHP $EA_PHP; do test -f $REPOS_DIR/$REPO || continue chattr -i $REPOS_DIR/$REPO chmod 644 $REPOS_DIR/$REPO done # remove unconditionally rm -f $REPOS_DIR/$ALT_PHP rm -f $REPOS_DIR/$EA_PHP fi } print_help () { cat << EOF >&2 Usage: -h, --help Print this message --version Print script's version and exit -k, --key <key> Deploy $PRODUCT with activation key -c, --uninstall Uninstall $PRODUCT --skip-version-check Do not check for script updates --skip-registration Do not register, just install (the default) --dev-install Turn off software defect reporting --beta Install packages from 'testing' repo --check Check if imunify360 Agent can be installed and exit -y, --yes Assume "yes" as answer to all prompts and run non-interactively EOF } print_version() { echo "$scriptname $version" } check_centos_iptables_compatibility() { # dummy function that does nothing : } check_debian_iptables_compatibility() { if is_debian && [ "$VERSION_ID" == "10" ] then local apt_opts="-t buster-backports" log install_debian_pkgs iptables check_exit_code 0 "iptables >= 1.8.5 required on Debian 10. \n\ Please, turn on buster-backports repository and run the script/installation again. \n\ Buster-backports repository may be turned on by following command: \n\ echo "deb http://ftp.debian.org/debian buster-backports main" > /etc/apt/sources.list.d/buster-backports.list \n\ Then run: \n\ apt-get update \n" fi } detect_cloudways_environment() { hostname=$(hostname -f) lowercase_hostname=$(echo "$hostname" | tr '[:upper:]' '[:lower:]') if echo "$lowercase_hostname" | grep -Eq "\.cloudwaysapps\.com|cloudwaysstagingapps\.com"; then is_cloudways=true log echo "Cloudways environment detected" touch /etc/sysconfig/imunify360/.cloudways_environment elif [ -f /usr/local/sbin/apm ]; then if /usr/local/sbin/apm info | grep -q "Cloudways"; then is_cloudways=true log echo "Cloudways environment detected" mkdir -p /var/imunify360 touch /etc/sysconfig/imunify360/.cloudways_environment else is_cloudways=false fi else is_cloudways=false fi } setup_imunify360_dir() { if [ ! -d "/var/imunify360/" ]; then mkdir -m 2755 -p /var/imunify360 fi } cleanup() { rm -f "$LOCK" } rapid_scan_basedir_override() { touch /var/imunify360/rapid_scan_basedir_override } # Lets start # if environment has umask=0000 (if called from plesk extension), all created files have -rw-rw-rw- permission umask 0022 init_vars "$0" "$*" reopen_log if [ -f "$LOCK" ] ; then if [ -d "/proc/$(cat "$LOCK")" ] ; then exit_with_error "$scriptname is already running" fi fi echo $$ > "$LOCK" check_exit_code 0 "Please run $scriptname as root" trap cleanup SIGTERM SIGINT SIGHUP EXIT options=$(getopt -o ychk: -l yes,uninstall,help,version,check,skip-version-check,skip-registration,beta,dev-install,force,apt-force,freemium,key: -- "$@") res=$? if [ "$res" != 0 ]; then print_help exit 1 fi eval set -- "$options" while true; do case "$1" in -h|--help) print_help exit 0 ;; --version) print_version exit 0 ;; -y|--yes) assumeyes=true shift ;; -c|--uninstall) uninstall=true shift ;; -k|--key) conversion=true activationkey="$2" shift 2 ;; --skip-version-check) skipversioncheck=true shift ;; --skip-registration) registration=false shift ;; --beta) beta=true yum_beta_option="--enablerepo=imunify360-testing" yum_beta_repo_enable=1 shift ;; --freemium) freemium=true shift ;; --dev-install) dev_install=true apt_allow_unauthenticated=--allow-unauthenticated shift ;; --force|--apt-force) # used for Plesk extension installation export DEBIAN_FRONTEND=noninteractive apt_force='-o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew' shift ;; --check) detect_ostype check_${ostype}_release EXIT_CODE=$? exit $EXIT_CODE ;; --) shift break ;; -*) echo "$0: error - unrecognized option $1" 1>&2 print_help exit 1 ;; *) exit_with_error "Internal error!" ;; esac done if [ "$skipversioncheck" = "true" ]; then log echo "Skipping check version" else log check_version "$*" fi detect_ostype check_${ostype}_release detect_first_install if [ "$conversion" = "true" ] && [ "$uninstall" = "true" ] ; then exit_with_error "invalid combination"; fi if [ "$conversion" = "false" ] && [ "$registration" != "false" ] ; then # Register by IP is the default now conversion=true activationkey=false fi if [ "$uninstall" = "true" ]; then remove_acronis_agent remove_hardened_php_feature remove_freemium_flag log remove_${ostype}_imunify terminate_detached_scans remove_${ostype}_repo log remove_first_install_default_overrides log echo "Uninstall complete." exit 0 fi set_panel_detection_path detect_panel if [[ "$package" = "$imunify_av" ]]; then if check_${ostype}_pkg_presence imunify360-firewall; then log echo "You are trying to install ImunifyAV over Imunify360 that already includes it. You can open Malware Scanner via UI Imunify360 -> Malware Scanner." exit 1 fi fi if [ "$first_install" = "true" ]; then log echo "In a few moments the script will install latest $package" \ "package (w/dependencies)... (Ctrl-C to cancel)" sleep 4 save_${ostype}_repo package_version=$(get_available_${ostype}_package_version "$package") check_exit_code 0 "Failed to get package version" log install_${ostype}_pkgs $package rc=$? # try installing the config overrides regardless of the installation success log install_first_install_default_overrides "$package" "$package_version" # fail if [ $rc -ne 0 ]; then exit_with_error "Package $package $package_version was not installed." fi if [ "$is_cloudways" = "true" ]; then rapid_scan_basedir_override fi modifying_call=true fi log echo "Installing ui packages..." case "$PANEL" in cpanel) log check_and_install "$package" "$package_version" "$UI_PACKAGE" "$PANEL" check_exit_code 0 "Failed to install $PRODUCT $PANEL plugin." modifying_call=true ;; directadmin) log check_and_install "$package" "$package_version" "$UI_PACKAGE" "$PANEL" check_exit_code 0 "Failed to install $PRODUCT $PANEL plugin." modifying_call=true ;; generic) log check_and_install "$package" "$package_version" "imunify-ui" "$PANEL" check_exit_code 0 "Failed to install $PRODUCT $PANEL plugin." modifying_call=true ;; plesk) log check_and_install "$package" "$package_version" "$UI_PACKAGE" "$PANEL" check_exit_code 0 "Failed to install $PRODUCT $PANEL plugin." # disable ImunifyAV(revisium-antivirus) if it was installed extensionsList=$(/usr/local/psa/bin/extension --list 2>/dev/null) log echo "Checking if ImunifyAV is installed..." log echo "Extensions List: $extensionsList" if [[ "$extensionsList" == *"revisium-antivirus"* ]]; then log echo "Disable ImunifyAV" /usr/local/psa/bin/extension --disable revisium-antivirus fi modifying_call=true ;; *) log echo "UI plugin is not installed." log echo "No supported hosted panel detected and $INTEGRATION_CONF_PATH file is missing." install_vendors=false ;; esac if [ "$conversion" = "true" ] ; then if [[ "$package" = "$imunify_av" ]]; then if imunify-antivirus rstatus >/dev/null 2>&1; then if [ "$activationkey" == false ]; then log echo "Already registered" exit 0 fi imunify-antivirus unregister >/dev/null 2>&1 fi if [ "$activationkey" != false ] && imunify-antivirus register "$activationkey" >/dev/null 2>&1; then log echo "Registered by key" else log echo "Not registered" fi imunify-antivirus rstatus >/dev/null 2>&1 if is_systemctl_avail; then log systemctl start "$package" else log /sbin/service minidaemon start fi fi check_exit_code 0 "Failed to start $package service." agent_start_success=false if [ "$is_cloudways" != "true" ]; then log echo "Waiting for $PRODUCT to start..." for i in {1..10}; do if log $COMMAND version then log echo "$PRODUCT is started" agent_start_success=true break else sleep 60 fi done if ! $agent_start_success; then log echo "Something went wrong during $PRODUCT start up" exit_with_error "See /var/log/imunify360/error.log for details" fi fi elif ! $COMMAND rstatus >/dev/null 2>&1 then log echo "You have to register this software with registration key:" log echo " $script --key <key>" fi if $modifying_call; then log echo "Success" log echo "You can find complete log in $LOG_FILE" fi exit 0