Tutorial: Manage Users, Groups, and Access Controls Using the Web API
Manage users, groups, authentication methods, access controls, VPN addressing, and routing settings in OpenVPN Access Server using the Web API. Includes practical API examples for common administration tasks.
Overview
This tutorial provides examples for managing users, groups, and related Access Server properties using the Web API.
You can use these examples to:
Create and delete users and groups.
Manage group membership.
View users and groups.
Configure user and group permissions.
Manage authentication methods.
Configure VPN IP addressing.
Manage access control rules.
Configure split tunnel and DNS settings.
View and disconnect VPN clients.
Control client profile generation.
Tip
This tutorial uses the sacli apicall command, but you can also use cURL or the Swagger UI. Refer to Tutorial: Test the New Web API (OpenAPI) in Access Server 3.0.
Prerequisites
Access Server 3.1.0 or newer.
Root privileges on your Access Server's console.
(Optional) A remote machine for running API calls.
Important
The API specification can change between Access Server versions. Verify the API specification for your version before using these commands.
Refer to: View the API specification.
Before you begin
All examples in this tutorial assume you're connected to the Access Server console with root privileges.
Placeholder values
Replace the following placeholders with values appropriate for your environment:
Placeholder | Description |
|---|---|
| User account name |
| Group name |
| User or group receiving the configuration |
| Authentication method |
| Configuration profile name |
Apply configuration changes
Some configuration changes require a warm restart before they take effect.
When instructed, run:
sacli --method POST --url 'api/server/restart?restartMode=warm' --value '' apicall
Use the following commands to create users and groups.
Create a user
sacli --method POST --url 'api/users/create' --value '{"name": "<USER_NAME>"}' apicallCreate a group
sacli --method POST --url 'api/groups/create' --value '{"name": "<GROUP_NAME>"}' apicallApply the changes
Perform a warm restart if required.
Use the following commands to assign users to groups.
Add a user to a group
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_NAME>", "group": "<GROUP_NAME>"}]' apicallRemove a user from a group
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_NAME>", "group": null}]' apicallApply the changes
Perform a warm restart if required.
List all users
sacli --method POST --url 'api/users/list' --value '' apicall
List a specific user
sacli --method POST --url 'api/users/list' --value '{"users":["<USER_NAME>"]}' apicallList all groups
sacli --method POST --url 'api/groups/list' --value '' apicall
List a specific group
sacli --method POST --url 'api/groups/list' --value '{"groups":["<GROUP_NAME>"]}' apicallBlock a user or group
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "deny": "true"}]' apicallUnblock a user or group
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "deny": "false"}]' apicallRestore inherited behavior
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "deny": null}]' apicallApply the changes
Perform a warm restart if required.
Disconnect a single user
sacli --method POST --url 'api/vpn/client/disconnect' --value '{"users": ["brandonqa"], "reason": "Brandon should not be working after hours", "client_reason": "Clients disconnected for administrative reasons"}' apicallDisconnect all VPN connections for multiple users
sacli --method POST --url 'api/vpn/client/disconnect' --value '{"users": ["brandonqa", "laurenqa"], "reason": "Brandon and Lauren should not be working after hours", "client_reason": "Clients disconnected for administrative reasons"}' apicallDelete a user
sacli --method POST --url 'api/users/delete' --value '{"users": ["<USER_NAME>"]}' apicallDelete a group
sacli --method POST --url 'api/groups/delete' --value '{"groups": ["<GROUP_NAME>"]}' apicallApply the changes
Perform a warm restart if required.
Tip
This endpoint retrieves the OpenVPN server status, including connected clients and information about the OpenVPN daemon(s).
List connected VPN users
sacli --method GET --url 'api/vpn/status' --value '' apicall
Use the following commands to grant or revoke administrator privileges for users or groups.
Grant administrator privileges
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "admin": "true"}]' apicallRevoke administrator privileges
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "admin": "false"}]' apicallRestore inherited behavior
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "admin": null}]' apicallApply the changes
Perform a warm restart if required.
Use the following commands to grant or revoke auto-login privileges.
Enable auto-login
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "autologin": "true"}]' apicallDisable auto-login
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "autologin": "false"}]' apicallRestore inherited behavior
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "autologin": null}]' apicallApply the changes
Perform a warm restart if required.
Use the following commands to assign authentication methods to users or groups.
Assign an authentication method
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "auth_method": "<MODE>"}]' apicallSupported values for <MODE>:
localpamradiusldapsaml
Apply the changes
Perform a warm restart if required.
Tip
The default <configurationProfile> value is Default. If you're using a different configuration profile, replace it with the appropriate value.
Configure a global dynamic subnet
When users who aren't assigned to a group connect to the VPN, Access Server assigns addresses dynamically from this subnet.
sacli --method POST --url 'api/config-items/<configurationProfile>' --value '{"vpn.daemon.0.client.network": "172.27.224.0", "vpn.daemon.0.client.netmask_bits": "20"}' apicallThe default is 172.27.224.0/20.
Configure a global group subnet
When users belong to a group without a specific group subnet configured, Access Server assigns addresses dynamically from this subnet.
sacli --method POST --url 'api/config-items/<configurationProfile>' --value '{"vpn.server.group_pool.0": "172.27.240.0/20"}' apicallThe default is 172.27.240.0/20.
Configure a specific group subnet
Assign a dedicated subnet to a group:
sacli --method POST --url 'api/userprop/set' --value '[{"name":"<GROUP_NAME>","subnets":[{"netip":"192.0.2.0","prefix_length":24}]}]' apicallAssign a static IP address from that subnet to a user:
sacli --method POST --url 'api/userprop/set' --value '[{"name":"<USER_NAME>","static_ipv4":"192.0.2.55"}]' apicallConfigure a specific group subnet and dynamic range
sacli --method POST --url 'api/userprop/set' --value '[{"name":"<GROUP_NAME>","subnets":[{"netip":"192.0.2.0","prefix_length":24}],"dynamic_ranges":[{"first_ip":"192.0.2.10","last_ip":"192.0.2.20"}]}]' apicallConfigure a global static subnet
sacli --method POST --url 'api/config-items/<configurationProfile>' --value '{"vpn.server.static.0.network": "198.51.100.0", "vpn.server.static.0.netmask_bits": "24"}' apicallAssign a static IP address from the subnet:
sacli --method POST --url 'api/userprop/set' --value '[{"name":"<USER_NAME>","static_ipv4":"198.51.100.55"}]' apicallApply the changes
Perform a warm restart if required.
Use the following examples to grant access to resources using NAT or routing.
Grant access to a single IP using NAT
sacli --method POST --url 'api/userprop/access/set' --value '{"items_append":[{"type":"access_to_ipv4","username":"<USER_OR_GROUP>","access_route":{"accept":true,"type":"nat","subnet":{"netip":"198.51.100.5","prefix_length":32,"ipv6":false}}}]}' apicallGrant access to a single IP using routing
sacli --method POST --url 'api/userprop/access/set' --value '{"items_append":[{"type":"access_to_ipv4","username":"<USER_OR_GROUP>","access_route":{"accept":true,"type":"route","subnet":{"netip":"198.51.100.5","prefix_length":32,"ipv6":false}}}]}' apicallGrant access to a subnet (range of IP addresses) using NAT
sacli --method POST --url 'api/userprop/access/set' --value '{"items_append":[{"type":"access_to_ipv4","username":"<USER_OR_GROUP>","access_route":{"accept":true,"type":"nat","subnet":{"netip":"198.51.100.0","prefix_length":24,"ipv6":false}}}]}' apicallGrant access to a subnet (range of IP addresses) using routing
sacli --method POST --url 'api/userprop/access/set' --value '{"items_append":[{"type":"access_to_ipv4","username":"<USER_OR_GROUP>","access_route":{"accept":true,"type":"route","subnet":{"netip":"198.51.100.0","prefix_length":24,"ipv6":false}}}]}' apicallGrant access to TCP port 443 on a specific IP using NAT
sacli --method POST --url 'api/userprop/access/set' --value '{"items_append":[{"type":"access_to_ipv4","username":"<USER_OR_GROUP>","access_route":{"accept":true,"type":"nat","subnet":{"netip":"198.51.100.5","prefix_length":32,"ipv6":false,"service":[{"protocol":"tcp","start_port":"443"}]}}}]}' apicallApply the changes
Perform a warm restart if required.
Grant multiple access control rules in a single request
You can add multiple access control rules for the same user or group in a single API request by including multiple entries in the items_append array. This reduces the number of requests required when assigning several resources to the same user or group.
The following grants user brandonqa access to two individual IP addresses using NAT:
sacli --method POST --url 'api/userprop/access/set' --value '{"items_append":[{"type":"access_to_ipv4","username":"brandonqa","access_route":{"accept":true,"type":"nat","subnet":{"netip":"198.51.100.15","prefix_length":32,"ipv6":false}}},{"type":"access_to_ipv4","username":"brandonqa","access_route":{"accept":true,"type":"nat","subnet":{"netip":"198.51.100.20","prefix_length":32,"ipv6":false}}}]}' apicallResult
The user brandonqa can access both 198.51.100.15 and 198.51.100.20 through the VPN using NAT-based access rules.
Tip
Use these settings to configure split-tunnel behavior for specific users or groups when the full tunnel is enabled globally.
Disable internet traffic redirection and DNS server assignment
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "reroute_gw": "disable"}]' apicallDisable internet traffic redirection, but continue assigning DNS servers
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "reroute_gw": "dns_only"}]' apicallUse the global internet access and DNS settings
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "reroute_gw": "global"}]' apicallRestore inherited behavior
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_OR_GROUP>", "reroute_gw": null}]' apicallUse bypass routes to exclude specific networks from the VPN tunnel.
Create a bypass route
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_NAME>", "bypass_subnets": [{"ipv6": false, "netip": "198.51.100.0", "prefix_length": 24}]}]' apicallApply the changes
Perform a warm restart if required.
By default, users can generate client profiles.
Allow profile generation
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_NAME>", "allow_generate_profiles": "true"}]' apicallPrevent profile generation
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_NAME>", "allow_generate_profiles": "false"}]' apicallRestore inherited behavior
sacli --method POST --url 'api/userprop/set' --value '[{"name": "<USER_NAME>", "allow_generate_profiles": null}]' apicall