Tutorial: How to Set Up Client-side Scripting in Access Server
How to write Python scripts for client-side scripting for OpenVPN Connect with Access Server.
Overview
Access Server supports client-side scripting, which uses executable scripts with OpenVPN Connect.
For more specifics about client-side scripting, refer to this topic: Access Server Supports Client-side Scripting
This tutorial covers two ways you can set up client-side scripting:
By user group via the Admin Web UI.
At global, user group, or user levels via the command-line interface (CLI).
Follow the steps below to use the Admin Web UI or the CLI.
Important
The end-user must approve scripts pushed by the VPN server to the VPN client. The first time the script runs, the end-user must allow it. The end-user can click the checkbox present to remember the answer given, so they don’t need to grant the script permission to run each time.
An installed Access Server.
A use case for client-side scripting. (Examples here)
Admin Web UI access or console access with root privileges.
Python script capabilities.
Scripting languages
OpenVPN Connect supports script execution using locally-installed script interpreters such as cmd.exe or PowerShell on Windows.
OpenVPN Connect version 3.x can support Python scripts on Windows and macOS platforms if you install a Python interpreter separately.
To use Powershell, add these lines at the start of a script:
#!"C:\windows\System32\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy ByPass -File #EXT ps1
To pass the script as a file to an interpreter (last argument is the implicit script filename):
#!"C:\Program Files\Foo Corp\interpreter.exe" -a somearg
Access Server supports the following features for client-side scripting for groups:
Scripts defined for Windows and macOS.
Scripts requiring user or admin-level privileges.
Scripts defined with environmental variables.
To turn on client-side scripting:
Sign in to the Admin Web UI.
Click User Management > Group Permissions.
Click the edit icon for More Settings for the preferred group.
Click Yes for Use Client Scripting?
Additional information displays for environment variables, windows script, and mac script.
Click on each available link to set variables, values, and scripts.
Enter the script into the text box that opens upon click.
Tip
Various options display to set scripts for Windows, Mac, and Linux. For each, you can set scripts for on-connect and on-disconnect. On-connect client-side scripts run when the client establishes a VPN connection. On-disconnect client-side scripts run when the user gives the command to disconnect. OpenVPN Connect will not wait for the client-side scripting to execute before disconnecting the VPN tunnel.
Note
Ensure you assign the users to your group that you want to execute the client-side script. You can do this from User Management > User Permissions.
Define environment variables
When you click the Windows or Mac environment variables, fields open to define a variable and a value. Here are three variables you could define:
PREPATH: If defined, will be prepended to the client's PATH before the script is executed.
N_RECONNECTS: The number of reconnects that have occured thus far in the connection session.
GRACEFUL_DISCONNECT: Set to '1' if the disconnect was requested by the user, as opposed to '0' when the disconnect was unexpected.
N_RECONNECTS and GRACEFUL_DISCONNECT are two special environment variables set by the OpenVPN Connect backend before scripts execute.
In the Admin Web UI, you're limited to specifying a client-side script on a group and then assigning users to those groups. There is no more granularity than that for client-side scripting in the Admin Web UI. However, on the command line, you can set a script on a user, group, or the __DEFAULT__ special keyword from which the default properties for users and groups are inherited.
Connect to the console and get root privileges.
Switch to the scripts directory:
cd /usr/local/openvpn_as/scripts/
Use the following commands for specifying client-side script options:
Load an on-connect client-side script for Windows:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.win.user.connect" --value_file "./windows-on-connect.txt" UserPropPut
Load an on-connect client-side script for macOS:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.mac.user.connect" --value_file "./macintosh-on-connect.txt" UserPropPut
Load an on-connect client-side script for Linux:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.linux.user.connect" --value_file "./linux-on-connect.txt" UserPropPut
Load an on-connect client-side script for all three platforms:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.all.user.connect" --value_file "./all-on-connect.txt" UserPropPut
Remove an on-connect client-side script of the four types shown above—note that this does not stop inheriting scripts from a higher level:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.win.user.connect" UserPropDel ./sacli --user <USER_OR_GROUP> --key "prop_cli.script.mac.user.connect" UserPropDel ./sacli --user <USER_OR_GROUP> --key "prop_cli.script.linux.user.connect" UserPropDel ./sacli --user <USER_OR_GROUP> --key "prop_cli.script.all.user.connect" UserPropDel
Load an on-disconnect client-side script for Windows:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.win.user.disconnect" --value_file "./windows-on-disconnect.txt" UserPropPut
Load an on-disconnect client-side script for macOS:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.mac.user.disconnect" --value_file "./macintosh-on-disconnect.txt" UserPropPut
Load an on-disconnect client-side script for Linux:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.linux.user.disconnect" --value_file "./linux-on-disconnect.txt" UserPropPut
Load an on-disconnect client-side script for all three platforms:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.all.user.disconnect" --value_file "./all-on-disconnect.txt" UserPropPut
Remove an on-disconnect client-side script of the four types shown above—note that this does not stop inheriting scripts from a higher level:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.win.user.disconnect" UserPropDel ./sacli --user <USER_OR_GROUP> --key "prop_cli.script.mac.user.disconnect" UserPropDel ./sacli --user <USER_OR_GROUP> --key "prop_cli.script.linux.user.disconnect" UserPropDel ./sacli --user <USER_OR_GROUP> --key "prop_cli.script.all.user.disconnect" UserPropDel
You can set a client-side environment variable in the Admin Web UI on a group via the Group Permissions page. But, in the command line, you can set it per group or user individually. You can push variables to the client program available to the client-side script as specified in the section above.
Connect to the console and get root privileges.
Switch to the scripts directory:
cd /usr/local/openvpn_as/scripts/
Set a client-side environment variable:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script_env.win.username"1 --value "john"2 UserPropPut
In this example, we're setting the "username" variable.
We set the "username" to "john" on the client.
Tip
As with client-side scripting, you can adjust the "win" to "mac", "linux", or "all", to specify if this should apply to Windows, macOS, Linux, or all three of them. In the above example, the key name contains the variable's name. So if you want to specify a variable name "myvariable" then change "username" to "myvariable" in the above example.
Remove the variable setting shown above:
./sacli --user <USER_OR_GROUP> --key "prop_cli.script_env.win.username" UserPropDel
To open a web page with client-side scripting, you specify the command for the OS and the URL you want to open. Windows uses the command, ‘start’ to open the local web browser. Mac uses the command, ‘open’.
Open https://www.openvpn.net in an on-connect script:
macOS:
open https://www.openvpn.net/
Windows:
start https://www.openvpn.net/
Using Python:
#!/usr/bin/env python import os, webbrowser if os.environ['N_RECONNECTS'] == '0': webbrowser.open_new("https://openvpn.net/")
Launch a URL
#!/usr/bin/env python # On VPN connection initiation, launch a URL in the default browser. # Works on all client platforms (Windows, Mac, Linux). # Environmental Variables: # LAUNCH_URL -- URL to launch import os, webbrowser if os.environ['N_RECONNECTS'] == '0': webbrowser.open_new(os.environ['LAUNCH_URL'])
Download and install an application on Windows
#!/usr/bin/env python # Download and install an MSI-based application on Windows. Leave a marker # file behind, so that we only install the application once per local user. # Environmental Variables: # MSI_URL -- URL of MSI file # MSI_HASH -- sha1 hash of MSI file, for security verification # MSI_OPT (optional) -- extra MSI arguments, such as /q for quiet install import os, urllib, scripthelper as sh url = os.environ['MSI_URL'] local = os.path.basename(url) hash = os.environ['MSI_HASH'] if not os.path.exists(hash): urllib.urlretrieve(url, local) if sh.digest_file(local, 'sha1') != hash: raise ValueError("downloaded file has incorrect hash") os.system("msiexec /i %s %s /l* msi.log" % (local, os.environ.get('MSI_OPT', ''))) file(hash, 'w').write('')
Script shebang usage for Windows (on unix, shebangs are processed by the OS)
The "shebang" is a unix construct for designating the interpreter that should process a script, by including a specially coded line beginning with "#!" as the first line of the script. When OpenVPN Connect runs on unix, the OS handles the shebang usage. However since Windows doesn't natively recognize shebang usage, OpenVPN Connect interprets the shebang line and uses it to determine how to execute the script, using the following rules:
[script content] — defaults to cmd.exe processing
#!foo.exe
[script content...—- find foo.exe in path]
#!foo.exe -a somearg
[script content... — pass options (the last option is the implicit script filename)]
#!"c:\Program Files\Foo Corp\foo.exe" -a somearg
[script content... — quote the program exe]
#!foo.exe
#EXT foo
[script content... — script will be written to a .foo file before execution]
#PYTHON
[python code — execute python script using OpenVPN Client built-in python interpreter]
#!/usr/bin/env python
[python code — execute python script using OpenVPN Client built-in python interpreter on Windows, and using default python install on unix.]