Implementing One-Click OpenConnect VPN Login with Alfred

· 2 min read

I frequently need to connect to the company VPN and have been using scripts for login, but it’s still not efficient enough. To save time, I decided to use Alfred to implement one-click VPN connection.

Workflow

The key points in the workflow include the following steps:

  1. Use keyword to get user input for mobile verification code
  2. Temporarily store keyword in a variable, because users need to further select server nodes
  3. For list filter’s keyword, just enter any value that’s different from the first step’s keyword
  4. The script uses expect, so final execution requires terminal command - cannot use Run Script
  5. Since system password and VPN account use workflow environment variables and command doesn’t support environment variable parsing, I added Run Script to parse variables

Shell Script

Run Script

echo "/Users/qhe/Documents/Shell/vpn.sh $code {query} $mac_password $username $password"

Variable Explanation

  • query is the verification code
  • mac_password is the Mac laptop password
  • username is the VPN login username
  • password is the VPN user password

Notes

  • Variables and environment variables in workflow are parsed using $name in shell
  • As shown above, this prints the final command that terminal wants to execute, including variables
  • Note that if shell script doesn’t have execution permission, you need to add +x

Terminal Command

Just need to parse query, {query}, which is the result printed from the previous step

#!/usr/bin/expect
set code [lindex $argv 0]
set url [lindex $argv 1]
set macPassword [lindex $argv 2]
set username [lindex $argv 3]
set password [lindex $argv 4]

spawn sudo openconnect "$url"
expect "Password" {send "$macPassword\r"}
expect "Enter 'yes' to accept" {send "yes\r"}
expect "Username:" {send "$username\r"}
expect "Password" {send "$password\r"}
expect "Password" {send "$code\r"}
interact
~

Final Thoughts

I previously didn’t understand how to allow users to perform multiple input operations in Alfred. Now I understand that using keyword plus listFilter as shown above can achieve this. To save values after each user operation, use var and arg for storage.