Skip to content

Instantly share code, notes, and snippets.

@lrtfm
Last active February 14, 2025 09:43
Show Gist options
  • Save lrtfm/68d78913cdc8ba5d2e21e832df346a71 to your computer and use it in GitHub Desktop.
Save lrtfm/68d78913cdc8ba5d2e21e832df346a71 to your computer and use it in GitHub Desktop.
Auto Connect to GlobalProtect VPN (PolyU)
(*
Auto Connect to GlobalProtect VPN of PolyU
GlobalProtect version: 6.2.6-838
*)
set appName to "GlobalProtect"
set appLanguage to getAppLanguage(appName)
if appLanguage starts with "zh-Hans" then
set disconnectLabel to "中断连接"
else if appLanguage starts with "zh-Hant" then
set disconnectLabel to "中斷連線"
else if appLanguage starts with "en" then
set disconnectLabel to "Disconnect"
else -- Default: English
set disconnectLabel to "Disconnect"
end if
log "The language of " & appName & " is set to: " & appLanguage & ¬
" and the label is set to " & disconnectLabel & ")"
set privateFolder to POSIX path of (path to library folder from user domain) & ¬
"Application Support/" & appName & "-Connect/"
-- Here, we store the username and password in a specified location.
-- Alternatively, you can manually set the userName and userPassword like this:
--
-- set {userName, userPassword} to {"yourName", "yourPassword"}
set {userName, userPassword} to retrieveRSACredentials(privateFolder)
tell application "System Events" to tell process appName
click menu bar item 1 of menu bar 2
if exists button disconnectLabel of window 1 then
delay 0.2
click menu bar item 1 of menu bar 2
log "VPN is now connected!"
return
end if
click button 2 of window 1 -- Clicks either Connect
repeat until exists (window "GlobalProtect Login")
delay 1 -- Wait 1 second before checking again
end repeat
tell window "GlobalProtect Login"
keystroke userName
delay 0.5
keystroke tab
delay 0.5
keystroke userPassword
delay 0.5
tell group 2 of UI element 1 of scroll area 1 of group 1 of group 1
click UI element 1 of group 5 -- click login
repeat until exists (UI element "PolyU Staff")
delay 1
end repeat
click UI element "PolyU Staff"
end tell
end tell
repeat while exists (window "GlobalProtect Login")
delay 1
end repeat
delay 2
click menu bar item 1 of menu bar 2
end tell
-- Utils
on getAppLanguage(appName)
set appBundleID to do shell script "osascript -e 'id of app \"" & appName & "\"'"
try
-- Attempt to get the custom language list for the application
-- Command: defaults read com.paloaltonetworks.GlobalProtect.client AppleLanguages
set appLanguages to do shell script "defaults read " & appBundleID & " AppleLanguages"
on error
-- If the custom language list is unavailable, use the system's default language
set appLanguages to do shell script "defaults read NSGlobalDomain AppleLanguages"
end try
-- Extract the first language from the language list
set appLanguage to do shell script "echo " & quoted form of appLanguages & ¬
" | tr -d '()\\r\\n\" ' | cut -f1 -d\\,"
return appLanguage
end getAppLanguage
on fileExists(filePath)
try
do shell script "test -f " & quoted form of filePath
return true
on error
return false
end try
end fileExists
on removeFiles(fileList)
repeat with afile in fileList
if fileExists(afile) then
do shell script "rm " & quoted form of afile
end if
end repeat
end removeFiles
on encryptData(message, rsaKeyFilePath)
return do shell script "echo " & quoted form of message & " | openssl rsautl -encrypt -inkey " & quoted form of rsaKeyFilePath & " | openssl base64"
end encryptData
on decryptData(encryptedData, rsaKeyFilePath)
return do shell script "echo " & quoted form of encryptedData & " | openssl base64 -d | openssl rsautl -decrypt -inkey " & quoted form of rsaKeyFilePath
end decryptData
-- Function to handle RSA key management, encryption, and decryption, returning username and password
on retrieveRSACredentials(privateFolder)
set rsaKeyFilePathFile to privateFolder & "rsakeypath.txt"
set encryptedFile to privateFolder & "credentials.enc"
do shell script "mkdir -p " & quoted form of privateFolder
log "The credentials folder: " & privateFolder
-- Check if the RSA key file path is already stored
set rsaKeyFile to ""
if fileExists(rsaKeyFilePathFile) then
-- If the RSA key file path is already stored, read it
set rsaKeyFile to do shell script "cat " & quoted form of rsaKeyFilePathFile
else
-- Prompt the user to input the RSA key file path with a default value
set promptMessage to "Please enter the path to your OpenSSL RSA key file:
" & ¬
"If the file does not exist, it will be generated using the following command:
" & ¬
" openssl genrsa -out <path-to-key> 4096"
set rsaKeyFile to text returned of (display dialog promptMessage default answer (POSIX path of (path to home folder) & ".ssh/gp_connect_key.pem"))
-- Save the RSA key file path for future use
do shell script "echo " & quoted form of rsaKeyFile & " > " & quoted form of rsaKeyFilePathFile
end if
-- Check if the RSA key file exists
if not fileExists(rsaKeyFile) then
if fileExists(encryptedFile) then
removeFiles({encryptedFile})
end if
do shell script "openssl genrsa -out " & rsaKeyFile & " 4096"
end if
-- Check if the encrypted file already exists
if fileExists(encryptedFile) then
-- If the encrypted file exists, decrypt and return the username and password
set encryptedCredentials to do shell script "cat " & quoted form of encryptedFile
set decryptedCredentials to decryptData(encryptedCredentials, rsaKeyFile)
-- Split the credentials string using the unique delimiter
set AppleScript's text item delimiters to ":"
set encodedUserName to text item 1 of decryptedCredentials
set encodedUserPassword to text item 2 of decryptedCredentials
set AppleScript's text item delimiters to ""
-- Decode the Base64 encoded parts
set userName to do shell script "echo " & quoted form of encodedUserName & " | openssl base64 -d"
set userPassword to do shell script "echo " & quoted form of encodedUserPassword & " | openssl base64 -d"
return {userName, userPassword}
else
-- Prompt the user for username and password
set userName to text returned of (display dialog "Please enter your username:" default answer "")
set passwordCorrect to false
repeat until passwordCorrect
set userPassword to text returned of (display dialog "Please enter your password:" default answer "" with hidden answer)
set userPasswordRepeat to text returned of (display dialog "Please re-enter your password to confirm:" default answer "" with hidden answer)
if userPassword is equal to userPasswordRepeat then
set passwordCorrect to true
else
display dialog ¬
"Passwords do not match. Please try again." buttons {"OK"} default button "OK"
end if
end repeat
-- Encode the username and password using Base64 and combine them
set encodedUserName to do shell script "echo " & quoted form of userName & " | openssl base64"
set encodedUserPassword to do shell script "echo " & quoted form of userPassword & " | openssl base64"
set credentials to encodedUserName & ":" & encodedUserPassword
-- Encrypt the credentials using the RSA public key
set encryptedCredentials to encryptData(credentials, rsaKeyFile)
-- Save the encrypted credentials to the file
do shell script "echo " & quoted form of encryptedCredentials & " > " & quoted form of encryptedFile
display dialog "The credentials have been stored in the folder: " & privateFolder & ". You can remove this folder to reset the settings." buttons {"OK"} default button "OK"
return {userName, userPassword}
end if
end retrieveRSACredentials
@lrtfm
Copy link
Author

lrtfm commented Aug 16, 2024

脚本保存为应用程序指南

  1. 导出为应用程序

    1. 使用脚本编辑器 (Script Editor) 打开文件.
    2. 在脚本编辑器中, 点击 文件 菜单, 然后选择 导出....
    3. 在弹出的导出对话框中, 按照以下步骤操作:
      • 文件格式: 选择 应用程序.
      • 代码签名: 选择 签名以在本地运行.
    4. 选择文件保存的位置,给应用程序命名,然后点击 保存.
  2. 打开应用程序并设置辅助功能权限

    1. 运行保存的应用程序.
    2. 如果是第一次运行, 系统可能会提示在 隐私与安全性 -> 辅助功能 中开启权限.
      • 打开 系统设置 -> 隐私与安全性 -> 辅助功能.
      • 找到应用程序并开启辅助功能权限.

注: 代码签名

  1. 如果导出时没有选择 签名以在本地运行, 即使已经在 辅助功能 中为应用程序开启了权限, 运行时也可能会遇到以下错误:
    “System Events”遇到一个错误:“XXXX”不允许辅助访问。 (-1719)
    
  2. 如果保存时没有选择 签名以在本地运行, 可以使用 codesign 命令进行签名
    # If you encounter the error: "resource fork, Finder information, or similar detritus not allowed,"
    # try running the following command before codesigning:
    # 
    #   xattr -rc <path-to-your-app>
    #
    # Then, proceed with codesigning:
    codesign --sign - --force --deep <path-to-your-app>
    

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