Skip to content

Instantly share code, notes, and snippets.

@kaleksandrov
Last active July 15, 2024 11:57
Show Gist options
  • Save kaleksandrov/3cfee92845a403da995e7e44ba771183 to your computer and use it in GitHub Desktop.
Save kaleksandrov/3cfee92845a403da995e7e44ba771183 to your computer and use it in GitHub Desktop.
Simple script that starts and stops GlobalProtect.app on Mac OSX.
#!/bin/bash
case $# in
0)
echo "Usage: $0 {start|stop}"
exit 1
;;
1)
case $1 in
start)
echo "Starting GlobalProtect..."
launchctl load /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist
launchctl load /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
echo "Done!"
;;
stop)
echo "Stopping GlobalProtect..."
launchctl remove com.paloaltonetworks.gp.pangps
launchctl remove com.paloaltonetworks.gp.pangpa
echo "Done!"
;;
*)
echo "'$1' is not a valid verb."
echo "Usage: $0 {start|stop}"
exit 2
;;
esac
;;
*)
echo "Too many args provided ($#)."
echo "Usage: $0 {start|stop}"
exit 3
;;
esac
@Aadil-Mir-Rubrik
Copy link

Aadil-Mir-Rubrik commented Jan 8, 2023

Here is what I modified it to , check for connection state after every 30 minutes(you can modify this ) and then connect again

`➜  ~ cat gp.sh
#!/usr/bin/env bash


osascript <<EOF
tell application "System Events" to tell process "GlobalProtect"
	click menu bar item 1 of menu bar 2 -- Activates the GlobalProtect "window" in the menubar
	set frontmost to false -- keep window 1 active
	tell window 1
	  -- Find the status
	  tell (first UI element whose title is "Connect") to if exists then set message to "VPN is connecting now..."
	  --tell (first UI element whose title is "Disconnect") to if exists then set message to "VPN is connected."
	  -- Click connect button
	  tell (first UI element whose title is "Connect") to if exists then click
	end tell
	click menu bar item 1 of menu bar 2 -- This will close the GlobalProtect "window" after clicking Connect/Disconnect. This is optional.
end tell
EOF
➜  ~ cat com.example.globalprotect.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.example.globalprotect</string>
    <key>Program</key>
    <string>/Users/Aadil.Mir/gp.sh</string>
    <key>StartInterval</key>
    <integer>1800</integer>
  </dict>
</plist>



cp com.example.globalprotect.plist ~/Library/LaunchAgents
launchctl load ~/Library/LaunchAgents/com.example.globalprotect.plist


launchctl unload ~/Library/LaunchAgents/com.example.globalprotect.plist
`

@EvilJordan
Copy link

Hi, Friends.

I found that none of the above worked for me on MacOS Ventura 13.2.1 running GlobalProtect 6.0.5, so I created a simple script that does.

Perhaps I am different in that I have also disabled the underlying system LaunchDaemon service (pangpsd) when this thing is not running because I like to know what's happening on my machine at all times, to the best extent possible. I have no Login Items enabled and modified the plists directly with a text editor to keep them from launching on startup.

This quick script is part of my ~/.bash_profile and invoked by calling vpn on the command line and will start the requisite services, and then launch GlobalProtect. If you have a different install location, you may need to change the open -a /Applications/GlobalProtect.app line to the appropriate directory.

To quit, vpn unload will stop and disable all services and kill the app as well. Errors are suppressed, with the routing > /dev/null 2>&1 because I don't care if the shutdown process isn't clean. Your milage may vary.

vpn() {
	if [ "$1" = "unload" ]; then
		launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist > /dev/null 2>&1
		launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist > /dev/null 2>&1
		launchctl bootout gui/$(id -u) /Library/LaunchDaemons/com.paloaltonetworks.gp.pangpsd.plist > /dev/null 2>&1
		PID="$(launchctl list | grep palo | cut -f 1)"
		kill $PID
		echo "VPN unloaded"
	else
		launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist
		launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist 
		launchctl bootstrap gui/$(id -u) /Library/LaunchDaemons/com.paloaltonetworks.gp.pangpsd.plist
		open -a /Applications/GlobalProtect.app
	fi
}

@reynardmarx
Copy link

Is there a way to fill in your 2FA code when prompted for this when connecting to a specific VPN portal?

@kaleksandrov
Copy link
Author

Is there a way to fill in your 2FA code when prompted for this when connecting to a specific VPN portal?

This script doesn't supports this. All it does is to register/unregister the global protect application as an autostart service. It doesn't use any global protect API.

@reynardmarx
Copy link

@kaleksandrov thank you, I understand that. However, do you think it would be possible, seeing that some of the scripts above are using the click functionality?

@erseco
Copy link

erseco commented Mar 11, 2024

This is a easier version that works for me in macOS Sonoma

vpn() {
    if [ "$1" = "stop" ]; then
        launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist > /dev/null 2>&1
        launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist > /dev/null 2>&1
        echo "VPN unloaded"
    elif [ "$1" = "start" ]; then
        #statements
        launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
        launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist
        echo "VPN loaded"
    fi
}

@damosse31
Copy link

damosse31 commented Apr 1, 2024

I adapted the script to kill globalprotect icon in tray on stop and open globalprotect app when start :

# Add the function below to your .zsh_env or .bash_profile
# Usage : globalprotect start or globalprotect stop

globalprotect() {
    if [ "$1" = "stop" ]; then
        launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist > /dev/null 2>&1
        launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist > /dev/null 2>&1
        PID="$(launchctl list | grep palo | cut -f 1)"

        # Kill the processes IDs only if found
        if [ ! -z "$PID" ]; then
                kill -9 $PID
        fi

        echo "VPN unloaded"
    elif [ "$1" = "start" ]; then
        launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
        launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist
        open -a /Applications/GlobalProtect.app
        echo "VPN loaded"
    fi
}

@githubrobbi
Copy link

githubrobbi commented Jun 26, 2024

Just to share:

Here is my version of start / stop script

# echo "START"
# set -e
# set -x

PORTAL="vpn.nios.net"
MAX_ATTEMPTS=10
SLEEP_INTERVAL=5
WAIT_FOR_APP_TO_BE_READY=5
WAIT_FOR_CONNECTION=15

function check_setup() {
    if [ ! -e "/Applications/GlobalProtect.app" ]; then
        echo "GlobalProtect app is not installed."
        exit 1
    fi

    if [ ! -e "/Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist" ] || [ ! -e "/Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist" ]; then
        echo "GlobalProtect launch agents are not properly set up."
        exit 1
    fi
}

function ensure_app_running() {
    for ((i=1; i<=$MAX_ATTEMPTS; i++)); do
        if osascript -e 'tell application "System Events" to (name of processes) contains "GlobalProtect"' &>/dev/null; then
            sleep $WAIT_FOR_APP_TO_BE_READY
            return 0
        fi
        echo "Waiting for GlobalProtect app to start..."
        sleep $SLEEP_INTERVAL
    done

    echo "Failed to start GlobalProtect app."
    exit 1
}

function start_vpn() {
    echo -e "\nStarting GlobalProtect...\n"
    launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist
    launchctl bootstrap gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist

    ensure_app_running

    connect_vpn

    sleep $WAIT_FOR_CONNECTION

    if check_vpn_status; then
        echo -e "\nVPN is connected to $PORTAL\n"
        return 0
    fi

    for ((i=1; i<=$MAX_ATTEMPTS; i++)); do
        connect_vpn
        sleep $SLEEP_INTERVAL
        if check_vpn_status; then
        echo -e "\nVPN is connected to $PORTAL\n"
            return 0
        fi
    done

    echo -e "\nFailed to connect to VPN after $MAX_ATTEMPTS attempts\n"
    exit 1
}

function connect_vpn() {
    osascript <<EOF &>/dev/null
    tell application "System Events"
        tell process "GlobalProtect"
            if not (exists window 1) then
                click menu bar item 1 of menu bar 2 -- Activates the GlobalProtect "window" in the menubar
                delay 2 -- Wait for 2 seconds
            end if
            set frontmost to true -- keep window 1 active
            tell window 1
                if exists (first button whose title is "Connect") then
                    tell (first button whose title is "Connect") to if exists then click
                end if
            end tell
        end tell
    end tell
EOF
}

function check_vpn_status() {
    VPN_STATUS=$(osascript <<EOF 2>/dev/null
    tell application "System Events"
        tell process "GlobalProtect"
            set frontmost to true -- keep window 1 active
            tell window 1
                if exists (first button whose title is "Disconnect") then
                    return "Connected"
                else
                    return "Not Connected"
                end if
            end tell
        end tell
    end tell
EOF
    )
    echo "VPN status: $VPN_STATUS"
    if [ "$VPN_STATUS" == "Connected" ]; then
        return 0
    elif [ "$VPN_STATUS" == "Not Connected" ]; then
        return 1
    else
        return 1
    fi
}
function stop_vpn() {
    echo -e "\nStopping GlobalProtect...\n"

    if ! launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist 2>/dev/null || \
       ! launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist 2>/dev/null; then
        echo "Failed to bootout as current user, trying with sudo..."
        sudo launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangps.plist 2>/dev/null
        sudo launchctl bootout gui/$(id -u) /Library/LaunchAgents/com.paloaltonetworks.gp.pangpa.plist 2>/dev/null
    fi

    PIDS=$(launchctl list | grep -E 'com\.paloaltonetworks\.gp\.pangpa|com\.paloaltonetworks\.gp\.pangps' | awk '{print $1}')
    if [ ! -z "$PIDS" ]; then
        echo "Killing GlobalProtect processes..."
        for PID in $PIDS; do 
            if sudo kill -9 $PID; then
                echo "Killed process $PID"
            else
                echo "Failed to kill process $PID"
            fi
        done
    fi

    echo -e "\nVPN stopped\n"
}

case $1 in
    start)
        check_setup
        start_vpn
        ;;
    stop)
        stop_vpn
        ;;
    *)
        echo "'$1' is not a valid verb."
        echo "Usage: $0 {start|stop}"
        exit 1
        ;;
esac

@nirazul
Copy link

nirazul commented Jun 27, 2024

I adapted the script to kill globalprotect icon in tray on stop and open globalprotect app when start :

@damosse31 THANK YOU! That's exactly what I was looking for and it works perfectly on macOS Sonoma and GlobalProtect 6.1.4 🫶

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