#!/bin/bash

# Replace with your own valid web URL path
# If using pre-existing dmg file instead of using installer link, replace string with local filepath
weburl="https://your_EMS_FQDN:10443/installers/Default/FCT_MAC_GA/FortiClient.dmg"

FortiClient_Installerversion="0000000" #Enter your FortiClient installer version using version and build number. e.g FortiClient 7.2.2 would be value "7220776"

# Please modify below values based on the new FCT installer feature set created on the EMS, and please don't modify other part of the script.

av="1"	# Enter 0 when Malware feature is disabled in the FortiClient installer
af="1"	# Enter 0 when Application Firewall  feature is disabled in the FortiClient installer
sb="1"	# Enter 0 when Advanced Persistent Threat (APT) components feature is disabled in the FortiClient installer
sra="1"	# Enter 0 when Secure Access Architecture Components feature is disabled in the FortiClient installer
sso="1"	# Enter 0 when Single Sign-On Mobility Agent feature is disabled in the FortiClient installer
vs="1"	# Enter 0 when vulnerability Scan feature is disabled in the FortiClient installer
wf="1"	# Enter 0 when Web Filtering feature is disabled in the FortiClient installer

# FortiClient 6.4 does not have ZTNA feature, and FCT 7.0 or higher version will always install ZTNA feature regardless of EMS installer setting due to a known issue.

# Please set uninstall value to 1 for FortiClient un-installation only. By default, the uninstall value is '0' for deployment.
uninstall="0"

# For 7.2.3, FCT uses ftgdagent process for webfiltering by default.
# Enabling the new webfilter with https mode will install a new certificate in the system keychain access, which requires admin's permission to trust the certificate.
# With FCT 7.2.5+ and 7.4.0+, certificate gets added to the login keychain and only requires login user's credentials to trust the certificate.
# set httpsmode to "0" to disable https mode inspection (default action), set httpsmode to "1" to enable.
httpsmode="0"

# Please set suppress_certificate_prompt value to 1 if suppressing FortiClient from prompting certificates on its own and certificates will be managed by MDM.
# If suppress_certificate_prompt value not equal to 1, it will be treated as 'disabled', and Forticlient will manage and prompt for its certificates.
# By default, it's set to '1' (enabled).
suppress_certificate_prompt="1"

tempdir="/etc/FortiClient/tmp"
MOUNT_POINT="$tempdir/mount"

appname="FortiClient" # The name of our App deployment script (also used for Octory monitor)

logandmetadir="/Library/Logs/MDM/$appname"
log="$logandmetadir/$appname.log"

function startLog() {
    ## Check if the log directory has been made
    if [ ! -d "$logandmetadir" ]
    then
        ## Creating Metadirectory
        echo "$(date) | Creating [$logandmetadir] to store metadata"
        mkdir -p "$logandmetadir"
    fi

    exec > >(tee -a "$log") 2>&1
}

function cleanup() {
    hdiutil detach $MOUNT_POINT
    rm -rf $tempdir
    rm -rf /etc/fct_upgrade
    rm -rf /etc/FortiClient/upgrade
}

function UninstallFCT () {
    local uninstaller_path="/Applications/FortiClientUninstaller.app/Contents/Library/LaunchServices/com.fortinet.forticlient.uninstall_helper"

    if [ ! -f $uninstaller_path ]; then
        return
    fi

    codesign -dv $uninstaller_path 2>&1 | grep "TeamIdentifier=AH4XFXJ7DK$"
    if [ $? -ne 0 ]; then
        echo "uninstaller has been modified by a third party"
        cleanup
        exit 1
    fi

    $uninstaller_path upgrade-uninstall
    echo "FCT Mac has been uninstalled"
}

## Install DMG Function
function installDMG () {
    cd "$tempdir"
    mkdir -p $MOUNT_POINT
    echo "made directory $MOUNT_POINT"
    echo $PWD

    hdiutil attach installer.dmg -mountpoint $MOUNT_POINT -noverify -nobrowse -noautoopen

    # Call the upgrade FCT's preuninstall scripts if it needs to perform any operations before uninstalling
    # Need to check the version of the uninstaller as only newer versions have this argument
    local bundle_version=$(defaults read $MOUNT_POINT/Uninstall.app/Contents/Info.plist CFBundleVersion)
    if [[ $(echo "$bundle_version >= 1.2" | bc) -eq 1 ]]; then
        $MOUNT_POINT/Uninstall.app/Contents/Library/LaunchServices/com.fortinet.forticlient.uninstall_helper preuninstall
    fi

    # Uninstall using the uninstaller of the currently installed FortiClient
    UninstallFCT

    # Suppress FortiClient from prompting certificates on its own since it will be managed by MDM
    if [[ $suppress_certificate_prompt == 1 ]]; then
        mkdir -p /Library/Application\ Support/Fortinet/FortiClient/data
        touch /Library/Application\ Support/Fortinet/FortiClient/data/external_cert_trust
        echo "Certificate Prompt Suppressed."
    fi

    /usr/sbin/installer -pkg $MOUNT_POINT/Install.mpkg -target /
    if [[ $httpsmode == 0 ]]; then
        DisableHTTPSMode
    else
        echo "Https Mode is enabled."
    fi
    echo "New FCT Has been installed successfully"
    cleanup
    echo "Unmount FCT mount point"
}

function downloadApp () {
    rm -rf "$tempdir"
    mkdir -p "$tempdir"
    cd "$tempdir"

    if [[ $weburl == http* ]]; then
        echo "Tries to Download FortiClient deployment Package from MIS EMS server"
        curl -k --connect-timeout 30 --retry 5 --retry-delay 60 -L -J -O "$weburl"
        if [ $? -eq 0 ]; then
            echo "Download successful from URL"
            # We have downloaded a file, we need to know what the file is called and what type of file it is
            tempSearchPath="$tempdir/"
            for f in $tempSearchPath*; do
                tempfile=$f
                echo "tempfile 0 $tempfile"
            done
            mv "$tempfile" "$tempdir/installer.dmg"
        else
            echo "$(date) | Failure to download [$weburl] to [$tempdir]"
            exit 1
        fi
    else
        localpath="$weburl"
        echo "Using local file path"
        if [[ -f $localpath ]]; then
            cp "$localpath" "$tempdir/installer.dmg"
            if [ $? -eq 0 ]; then
                echo "Copied local file successfully"
            else
                echo "$(date) | Failure to copy [$localpath] to [$tempdir/installer.dmg]"
                exit 1
            fi
        else
            echo "$(date) | Invalid local file path [$localpath]"
            exit 1
        fi
    fi
}


function DisableHTTPSMode () {
    rm /Library/Application\ Support/Fortinet/FortiClient/data/enable_wf_https_mode
    echo "https mode disabled"
}

if [ $EUID -ne 0 ] || [ "$(id -u)" != "0" ]; then
    echo "Please run as root"
    exit 1
fi

startLog
echo ""
echo "##################################################################"
echo "# $(date) | Logging Deployment of FortiCLient Mac"
echo "##################################################################"
echo ""
echo $4

if [[ $uninstall == 1 ]]; then
    UninstallFCT
    exit 0
elif [[ $uninstall == 0 ]]; then

    # Verifying FortiClient has been already Installed or not.
    if open -Ra "FortiClient" ; then

    # Checking FortiClient Version
    FortiClient_version="$(grep -A1 'version=' /Library/Application\ Support/Fortinet/FortiClient/conf/fctinfo | sed 's/.*=//' | tr -d '.')"
    echo "Current FortiClient Version = ${FortiClient_version}"

        # Comparing FortiClient version
        if [[ "$FortiClient_version" == *"$FortiClient_Installerversion"* ]]; then

            #Checking FCT is only-VPN or Full version
            if [ -f "/Library/Application Support/Fortinet/FortiClient/bin/epctrl" ]; then

                # Extracting feature values from config.plist file
                ep_av="$(grep -A1 '<key>AntiVirus</key>' /Library/Application\ Support/Fortinet/FortiClient/conf/custom.plist)"
                ep_af="$(grep -A1 '<key>ApplicationFirewall</key>' /Library/Application\ Support/Fortinet/FortiClient/conf/custom.plist)"
                ep_sb="$(grep -A1 '<key>Sandboxing</key>' /Library/Application\ Support/Fortinet/FortiClient/conf/custom.plist)"
                ep_sra="$(grep -A1 '<key>SecureRemoteAccess</key>' /Library/Application\ Support/Fortinet/FortiClient/conf/custom.plist)"
                ep_sso="$(grep -A1 '<key>SingleSignOn</key>' /Library/Application\ Support/Fortinet/FortiClient/conf/custom.plist)"
                ep_vs="$(grep -A1 '<key>VulnerabilityScan</key>' /Library/Application\ Support/Fortinet/FortiClient/conf/custom.plist)"
                ep_wf="$(grep -A1 '<key>WebFiltering</key>' /Library/Application\ Support/Fortinet/FortiClient/conf/custom.plist)"

                # You maybe uncomment this once the mantis 0825169 get fixed.
                # ep_ztna="$(grep -A1 '<key>ZeroTrustNetworkAccess</key>' /Library/Application\ Support/Fortinet/FortiClient/conf/custom.plist)"
                # ep_ztna="<key>ZeroTrustNetworkAccess</key><integer>1</integer>"  # Remove this hardcoded ep_ztna once the mantis 0825169 get fixed.

                if [[ -n "$ep_av" ]]; then
                e_av=1
                else
                e_av=0
                fi
                if [[ -n "$ep_af" ]]; then
                e_af=1
                else
                e_af=0
                fi
                if [[ -n "$ep_sb" ]]; then
                e_sb=1
                else
                e_sb=0
                fi
                if [[ -n "$ep_sra" ]]; then
                e_sra=1
                else
                e_sra=0
                fi
                if [[ -n "$ep_sso" ]]; then
                e_sso=1
                else
                e_sso=0
                fi
                if [[ -n "$ep_vs" ]]; then
                e_vs=1
                else
                e_vs=0
                fi
                if [[ -n "$ep_wf" ]]; then
                e_wf=1
                else
                e_wf=0
                fi
                #if [[ -n "$ep_ztna" ]]; then
                #  e_ztna=1
                #else
                #  e_ztna=0
                #fi



            # Comparing Feature set
                if [[ $av == $e_av && $af == $e_af && $sb == $e_sb && $sra == $e_sra && $sso == $e_sso && $vs == $e_vs && $wf == $e_wf ]]; then
                    echo "Same FortiClient has already been installed on the endpoint"
                else
                echo "Currently installed FortiClient features are shown below:"
                echo "##########################################################"
                if [[ -n $ep_av ]]; then
                    echo "Malware feature"
                fi
                if [[ -n $ep_af ]]; then
                    echo "Application Firewall"
                fi
                if [[ -n $ep_sb ]]; then
                    echo "Advanced Persistent Threat (APT) components"
                fi
                if [[ -n $ep_sra ]]; then
                    echo "Secure Access Architecture Components"
                fi
                if [[ -n $ep_sso ]]; then
                    echo "Single Sign-On Mobility Agent"
                fi
                if [[ -n $ep_vs ]]; then
                    echo "Vulnerability Scan"
                fi
                if [[ -n $ep_wf ]]; then
                    echo "Web Filtering"
                fi
                # if [[ -n $ep_ztna ]]; then
                #    echo "Zero Trust Network Access"
                # fi
                echo "##########################################################"
                echo "FortiClient with different feature set would be installed on the endpoint."
                echo "Removing old FortiClient and installing new FortiClient."
                downloadApp
                installDMG
                fi
            else
                echo "FortiClient only-VPN version has been installed on the endpoint. Upgrading FortiClient only-VPN version to Full Version"
                downloadApp
                installDMG
            fi
        else
            echo "FortiClient with different version has been installed on the endpoint. Removing old FortiClient and installing new FortiClient"
            downloadApp
            installDMG
        fi
    else
        echo "No FortiClient is installed on the endpoint. Installing FortiClient now"
        downloadApp
        installDMG
    fi
else
    echo "uninstall value can only be 0 or 1!"
fi
