[Mac] 用 AppleScript 自動以 SecurID 密碼登入 Junos Pulse VPN
在家裡要連上公司的電腦時,都是要先用 SecurID 產生一次性的密碼,
再用 Junos Pulse 登入 VPN~
懶人如我之前就已經寫了一個 shell script,
執行後自動把 SecurID 叫起來,然後一直去 ping 公司電腦,
如果連上的話就關掉 SecurID~
只是,中間打密碼給 SecurID 和複製密碼貼上的過程是手動的,
是不是還能再自動化呢?
研究了一下 Mac 內建的 AppleScript,說實話 AppleScript 雖然看起來是自然語言,
不過反倒比一般的程式語言要難學的感覺,
尤其是每個應用程式究竟提供了哪些介面供使用,
得用 Script Editor 的 Dictionary 去查,
可是查出來的資料又常常覺得太簡略,難以理解…
只能上網去找看看有沒有人寫過類似的 AppleScript 來參考,
可是老實說資料真的不多,
像是我想找 Junos Pulse 相關的,大概只有兩三個可以參考…
1. 學習 AppleScript
這邊可以自己上網去查一下 AppleScript 關鍵字,
有些文章有一些簡單介紹,有空的話可以多看幾篇,
像我是先看了 The Ultimate Beginner’s Guide To AppleScript~
2. 用 AppleScript 開啟 SecurID 打密碼
懶人如我看了幾篇介紹文就頭昏腦脹了,還是直接寫寫看再說吧…
打開 Script Editor,就可以開始寫 AppleScript~
上網參考了一下範例程式 AnyConnect_SecurID,複製後改一下:
tell application "SecurID" activate delay 0.75 tell application "System Events" keystroke "12345678" -- type the pin number key code 36 -- return key delay 0.75 -- wait for token appear key code 48 -- press tab key code 49 -- space (to hit the copy button) end tell end tell
上面這一段是先用 tell application “SecurID” 表示要跟 SecurID 互動,
先執行 activate 把程式叫出來,delay 等一下下後,再開始打 PIN 碼上去~
要打字的話,需要跟 System Events 互動,
可以用 keystroke 直接打字 (像我這邊的 12345678 是 PIN 碼 (假的啦)),
按下 Enter 鍵後,再按 Tab 跳到 SecurID 上的 Copy 鈕,
再按 Space 鍵就會複製產生出來的一次性密碼到剪貼簿~
要打 Enter, Tab 和 Space 等特殊鍵的話,需要用 key code 的方式打進去~
想知道所有的 virtual key code 的話,可以看一下
/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/
HIToolbox.framework/Versions/A/Headers/Events.h,
記得這 Events.h 裡放的是十六進位碼,放到 AppleScript 時要先轉成十進位碼:
/* keycodes for keys that are independent of keyboard layout*/ enum { kVK_Return = 0x24, kVK_Tab = 0x30, kVK_Space = 0x31, kVK_Delete = 0x33, kVK_Escape = 0x35, kVK_Command = 0x37, kVK_Shift = 0x38, kVK_CapsLock = 0x39, kVK_Option = 0x3A, kVK_Control = 0x3B, kVK_RightShift = 0x3C, kVK_RightOption = 0x3D, kVK_RightControl = 0x3E, kVK_Function = 0x3F, kVK_F17 = 0x40, kVK_VolumeUp = 0x48, kVK_VolumeDown = 0x49, kVK_Mute = 0x4A, kVK_F18 = 0x4F, kVK_F19 = 0x50, kVK_F20 = 0x5A, kVK_F5 = 0x60, kVK_F6 = 0x61, kVK_F7 = 0x62, kVK_F3 = 0x63, kVK_F8 = 0x64, kVK_F9 = 0x65, kVK_F11 = 0x67, kVK_F13 = 0x69, kVK_F16 = 0x6A, kVK_F14 = 0x6B, kVK_F10 = 0x6D, kVK_F12 = 0x6F, kVK_F15 = 0x71, kVK_Help = 0x72, kVK_Home = 0x73, kVK_PageUp = 0x74, kVK_ForwardDelete = 0x75, kVK_F4 = 0x76, kVK_End = 0x77, kVK_F2 = 0x78, kVK_PageDown = 0x79, kVK_F1 = 0x7A, kVK_LeftArrow = 0x7B, kVK_RightArrow = 0x7C, kVK_DownArrow = 0x7D, kVK_UpArrow = 0x7E };
上面這一整段的 AppleScipt 程式執行完之後,
就會開啟 SecurID,自動打入 12345678 這個 PIN 碼,
並把產生出來的密碼複製到剪貼簿了~
3. 用 AppleScript 將密碼打進 Junos Pulse
接下來用 tell application “Junos Pulse” 跟 Junos Pulse 互動,
一樣先 activate 叫出程式視窗,
接著要列舉出 Junos Pulse 裡面儲存好的連線清單,這要怎麼做呢?
這邊需要開 Script Editor > File > Open Dictionary:
接著選到想參考的應用程式,本例中是 Junos Pulse:
接著就可以看到 Junos Pulse 提供了哪些介面給外界使用~
可以看到 application 裡面包含了 connections 物件,
而每個 connection 物件都有 connectionDisplayName 這個屬性:
使用 repeat with 這個敘述來檢視 connections 中的每個 connection,
如果 connectionDisplayName 是 My VPN 的話,
就去執行 connect to 這個函式:
tell application "Junos Pulse" activate repeat with c in connections if connectionDisplayName of c is "My VPN" then tell me to connect to c exit repeat end if end repeat end tell
這個 connect to 是什麼東西呢?原來是範例程式裡定義的一個函式~
關於 AppleScript 的函式,可以參考 AppleScript: About Handlers,
以 on connect to c 來說,函式名稱是 connect,
to 代表一個參數的 label,c 則是實際的參數值 (每個參數值前面要有 label name):
on connect to c tell me to push_button for c to "connect" end connect
上面的函式定義裡,它又呼叫了另一個 push_button 的函式:
on push_button for c to which if which is "connect" then set notdone to "Disconnected" set isdone to "Connected" end if tell application "Junos Pulse" if connectionStatus of c is not isdone then -- Time to connect set istr to indexStr of c do PulseMainUI command "SELECTCONNECTION" ConnectionIndexStr istr do PulseMainUI command "CLICKCONNECTBUTTON" ConnectionIndexStr istr -- Paste password delay 2 tell application "System Events" keystroke (the clipboard) -- type the pin number key code 36 -- return key end tell -- Wait until connection status is changed repeat if connectionStatus of c is isdone then exit repeat delay 0.1 end repeat else if connectionStatus of c is isdone then tell application "Finder" to display dialog "isdone" display dialog "Connection is already " & connectionStatus of c else tell application "Finder" to display dialog "others" display dialog "Connection status is " & connectionStatus of c end if -- Quit Junos Pulse quit -- Quit SecurID tell application "SecurID" to quit end tell end push_button
這個 push_button 函式有點複雜,
一開始先看傳進來的參數,如果是 “connect” 的話,
那麼還沒完成前 notdone 就是 “Disconnected”,如果完成了 isdone 會是 “Connected”~
接著 tell application “Junos Pulse” 看一下這個 c 的狀態,
如果跟 isdone 不一樣的話,表示需要登入 VPN,
接著需要用 Junos Pulse 提供的 do PulseMainUI command 指令,
選擇連線 (SELECTCONNECTBUTTON) 後,按下連線按鈕 (CLICKCONNECTBUTTON)~
不過這邊有個難題,Dictionary 裡面是有 do PulseMainUI command 沒錯,
可是沒有什麼 SELECTCONNECTBUTTON 和 CLICKCONNECTBUTTON,
我怎麼知道要填這個呢?
其實我不知道,這是從網路上的範例程式複製下來的,
這邊我覺得這類的資訊相當的不清楚,而且 do PulseMainUI command 的用法也很不清楚,
所以我都只能照著範例寫…
作完上面的步驟,就會跳出 Junos Pulse 的輸入密碼對話框:
這邊可以用 (the clipboard) 取得剪貼簿裡的密碼,
再用上述 System Events 方式,把密碼打上去,
當連線建立後,if connectionStatus of c is isdone then exit repeat 就會離開迴圈了~
這個 AppleScript 還不算完美,
如果連線狀態是錯誤或連線中的話,就會出現問題,
還需要再改進囉~
參考資料:
stackoverflow: Where can I find a list of Mac virtual key codes?
stackoverflow: Copy pure text from clipboard using AppleScript
stackoverflow: Add MAC Application into Junos Pulse Programeticaly