Gabe
Gabe

Reputation: 6347

Programmatically reconnect Endpoint_Security_VPN

My VPN connection drops at regular intervals. I need to be able to programmatically reconnect when that happens.

Software: Endpoint Security VPN
Brand: Check Point

This is the AppleScript that I put together:

on run
  log "VPN auto-connect script started - pinging service accessible only on the VPN.."

  set shellScript to "if echo \"$(ping -c 1 -W 1 10.123.321.123 ; echo $?)\" | grep -q \"100.0% packet loss\"; then echo \"failure\"; else echo \"success\"; fi"
  set pwd to do shell script "openssl enc -base64 -d <<< BaS364Enc0d3dPwdHere=="

  repeat while true
    try
      log "Checking VPN connection pinging GitLab.."
      set networkSuccess to do shell script shellScript
      if not (networkSuccess = "success") then
        log "VPN GOT DISCONNECTED! Reconnecting.."
        do shell script "pkill -f \"Endpoint_Security_VPN\""
        delay 10
        tell application "Endpoint Security VPN" to activate
        log "Launching VPN client.."
        delay 3
        tell application "System Events"
          tell process "TextExpander"
            keystroke pwd
            delay 0.5
            keystroke return
          end tell
        end tell
      end if
      log "Sleeping 1 min.."
      delay 60
    on error errMsg number errorNumber
      if (errorNumber = -128) then
        log "VPN script terminated"
        exit repeat
      end if
      log ("An error occurred! " & errorNumber as text) & " - " & errMsg as text
      delay 3
    end try
  end repeat
end run

Most of the times this does the trick but quite often instead, after killing "Endpoint Security VPN" and programmatically relaunching it, the software is ran only in the background (the icon appears in the MacOS toolbar). The fact that the GUI is not presented means that the AppleScript cannot interact with the GUI to re-enter the credentials and submit. (I can do so clicking on the icon in the toolbar and selecting Show Client).

How can I programmatically force the VPN client to appear?

This script did not work because I don't have /Library/Extensions/cpfw.kext. Also, I would like to avoid sudo.

Upvotes: 0

Views: 726

Answers (1)

Ted Wrigley
Ted Wrigley

Reputation: 3184

First things first: if you're going to have a constantly running script like this, it is much more efficient (and much more aesthetically pleasing) to create a stay-open script application with an on idle handler. Using delay commands aren't bad per se but they freeze the script and clog up Script Editor. so I've rewritten your script with that in mind (note that I've used an external log file because we can't read the logs on a running script application).

Copy the following into Script Editor, then save it, choosing "Application" from the File Format popup, and clicking the "Stay open after run handler" checkbox. Then run the resulting app file like normal. It will sit in the background watching your VPN connection.

Aside from turning this into a script app, I've added loop-checks to ensure that actions are completing. The script waits until the VPN has definitely quit, it waits until it is definitively reopened, it waits until a window exists. If the window doesn't show it will try every 5 seconds to pull the app to the foreground again, but since I don't own this app I don't know that this will automatically open a window. If it doesn't, we may have to modify the script to open a window directly.

property logPath : POSIX path of (path to home folder from user domain) & "logFile.txt"
property shellScript : "if echo \"$(ping -c 1 -W 1 10.123.321.123 ; echo $?)\" | grep -q \"100.0% packet loss\"; then echo \"failure\"; else echo \"success\"; fi"
property pwd : ""

on run
    externalLog("VPN auto-connect script started - pinging service accessible only on the VPN..")
    set pwd to do shell script "openssl enc -base64 -d <<< BaS364Enc0d3dPwdHere=="
end run

on idle
    (*
        when you return a number from an idle handler, the app idles for that many seconds.
        Thus "return 60" causes the app to idle for one minute
    *)
    try
        externalLog("Checking VPN connection pinging GitLab..")
        set networkSuccess to do shell script shellScript
        if not (networkSuccess = "success") then
            externalLog("VPN GOT DISCONNECTED! Reconnecting..")
            -- pushed all these routines into handlers for clarity
            my killApp()
            my restartApp()
            my doConnect()
        end if
        externalLog("Sleeping 1 min..")
        return 60
    on error errMsg number errorNumber
        if (errorNumber = -128) then
            externalLog("VPN script terminated")
            quit
        end if
        externalLog(("An error occurred! " & errorNumber as text) & " - " & errMsg as text)
        return 3
    end try
    return 30
end idle

on killApp()
    tell application "System Events"
        -- make sure the process has fully quit
        tell process "Endpoint Security VPN" to quit
        repeat while exists process "Endpoint Security VPN"
            delay 0.2
        end repeat
    end tell
end killApp

on restartApp()
    externalLog("Launching VPN client..")
    tell application "Endpoint Security VPN" to activate
    tell application "System Events"
        -- make sure the process has started again
        repeat until (exists process "Endpoint Security VPN")
            delay 0.5
        end repeat

        -- make sure the process has a window
        set timeCount to 0
        tell process "Endpoint Security VPN"
            repeat until exists first window
                set timeCount to timeCount + 0.5
                if timeCount ≥ 20 then
                    -- no window in 20 seconds, something more serious whent wrong
                    my quit
                else if timeCount mod 5 = 0 then
                    -- try bringing the process forward every 5 seconds
                    set its frontmost to true
                end if
                delay 0.5
            end repeat
        end tell
    end tell
end restartApp

on doConnect()
    tell application "System Events"
        tell process "TextExpander"
            keystroke pwd
            delay 0.5
            keystroke return
        end tell
    end tell
end doConnect

on externalLog(t)
    try
        set fp to open for access logPath with write permission
    on error
        close access logPath
        set fp to open for access logPath with write permission
    end try
    write return & "--------" & return to fp starting at ((get eof fp) + 1)
    write t to fp starting at ((get eof fp) + 1)
    close access fp
end externalLog

Last point: you are using an app called "TextExpander" to paste in the password. You could do that directly from AppleScript; I'm not sure what the advantages of TextExpander are. Just so you know you have options, in case it turns out the TextExpander is causing the problem.

Upvotes: 1

Related Questions