Admin API#
WORK IN PROGRESS
We provide an API that can be used by administrators to create and destroy VPN configurations for users. This can be useful when organizations want to provision managed devices with a VPN configuration, without having their users manually configure the VPN.
The API can be used to obtain WireGuard or OpenVPN configuration files that are ready to use with the official OpenVPN and WireGuard VPN clients. There would be no need to use the eduVPN or Let’s Connect! applications in this scenario.
NOTE: this is a Preview Feature!
Configuration#
The API is disabled by default, but it is easy to enable.
$ sudo /usr/libexec/vpn-user-portal/generate-secrets --admin-api
By default, the API is only accessible from localhost
in order to avoid
anyone accessing the API from the network.
You can modify /etc/httpd/conf.d/vpn-user-portal.conf
on Fedora/EL, or
/etc/apache2/conf-available/vpn-user-portal.conf
on Debian/Ubuntu. Set the
Require ip
option under <Files admin-api.php>
to the IP address(es) from
which you want to access the API. If your vpn-user-portal.conf
does not
contain anything related to the “Admin API”, make sure the following parts are
added:
Alias ${VPN_APP_ROOT}/admin/api /usr/share/vpn-user-portal/web/admin-api.php
<Directory /usr/share/vpn-user-portal/web>
...
<Files admin-api.php>
<RequireAny>
Require local
# Add the IP address(es) of your system(s) that need to access the
# Admin API here
#Require ip 192.0.2.0/24
#Require ip 2001:db::/32
</RequireAny>
</Files>
...
</Directory>
NOTE: if you modify vpn-user-portal.conf
file, on Debian/Ubuntu, you MAY
be notified during upgrades of vpn-user-portal
about a changed configuration
file. In that case choose to KEEP your current configuration file, or manually
merge your changes!
Do NOT forget to restart Apache after modifying the files.
In order to use the API, the secret you need can be found in
/etc/vpn-user-portal/keys/admin-api.key
after generating it which was done
above. Use this value in the Authorization
(Bearer) header. See the examples
below.
API Calls#
See the table below for supported API calls.
Method | URL | Description | Since |
---|---|---|---|
GET |
/connected_users |
Show a list of connected users for each profile | 3.5.1 |
GET |
/connection_list |
Show a list of all connections per profile | 3.5.3 |
GET |
/users |
List all users | 3.5.2 |
GET |
/disabled_users |
List all disabled users | 3.5.2 |
GET |
/user_configuration_list |
Get list of all configurations of user | 3.5.4 |
POST |
/create |
Create a VPN profile configuration for user | 3.0.6 |
POST |
/destroy |
Delete user account and all configurations | 3.0.6 |
POST |
/disable_user |
Disable user account (and disconnect user) | 3.5.1 |
POST |
/enable_user |
Enable user account | 3.5.1 |
POST |
/delete_connection |
Delete a connection | 3.5.3 |
POST |
/delete_user_authorizations |
Delete all OAuth authorizations of user | 3.5.4 |
Connected Users#
Get a list of users currently connected to the VPN (per profile).
Request#
$ curl \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/connected_users"
Response#
NOTE: in vpn-user-portal >= 3.5.2 the response is now wrapped in the object
connected_users
, in 3.5.1 it was not!
The following example output shows two profiles, students
and employees
.
The students
profile has three connected users. The employees
profile has
no connected users. If the same user is connected multiple times to the same
profile that user is only listed once.
{
"connected_users": {
"employees": [],
"students": [
"ellis",
"remi",
"charlie"
]
}
}
Connection List#
Get a list of all connections to a server (per profile).
Request#
$ curl \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/connection_list"
Response#
{
"connection_list": {
"default": [
{
"auth_key": null,
"connection_id": "z/2CtDHH/tJBosty+bjF7JhCZ8K8ulqqi3/ODAfzDRI=",
"display_name": "iPhone",
"ip_list": [
"10.146.176.4",
"fdee:1ead:29e8:22a2::4"
],
"user_id": "ellis",
"vpn_proto": "wireguard"
},
{
"auth_key": "hVYT4GwEXlhOqH0jLq8pIzTT-D2D-cr3UzllM9BG4Gg",
"connection_id": "T4q3RbSw9uDPciZeUEBlVPoS4ubKRj6E/T7AqKR5MQ8=",
"display_name": "org.eduvpn.app.ios",
"ip_list": [
"10.146.176.2",
"fdee:1ead:29e8:22a2::2"
],
"user_id": "remi",
"vpn_proto": "wireguard"
}
]
}
}
The above shows that there are two users connected to the default
profile,
ellis
and remi
.
The connection_id
field indicates the “Common Name” of the certificate
(for OpenVPN) or the public key (for WireGuard).
If you want to filter the result list, e.g. only show connections for user foo
to profile bar
, you can use jq
:
$ curl ... | jq '.connection_list.bar[]|select(.user_id == "foo")
If you want to see all connections for a particular user:
$ curl ... | jq '.connection_list.[][]|select(.user_id == "foo")
If you want to extract the connection_id
for all connections of a particular
user to any profile:
$ curl ... | jq -r '.connection_list.[][]|select(.user_id == "foo").connection_id
The -r
flag returns the “raw” response, so the connection_id
values are not
quoted anymore.
List All Users#
Get a list of all users known to the VPN server.
Request#
$ curl \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/users"
Response#
{
"users": [
"ellis",
"remi",
"charlie"
]
}
List Disabled Users#
Get a list of all disabled users known to the VPN server.
Request#
$ curl \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/disabled_users"
Response#
{
"disabled_users": [
"charlie"
]
}
List Configurations of User#
Parameter | Required | Value(s) |
---|---|---|
user_id |
Yes | The user account for which to list configurations |
Request#
$ curl \
--url-query "user_id=foo" \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/user_configuration_list"
Response#
{
"user_configuration_list": [
{
"connection_id": "eoJu5pqw3Kcz/5ezTJZfw75/mEE4jawY+lcF4XtRAzg=",
"profile_id": "default",
"display_name": "Foo Bar",
"auth_key": null,
"expires_at": "2026-12-14T11:48:06+00:00",
"vpn_proto": "wireguard"
}
]
}
Create#
Create a VPN configuration for a particular user (and profile). The /create
call will transparently create the user if necessary
Parameter | Required | Value(s) |
---|---|---|
user_id |
Yes | The user for which to create the configuration |
display_name |
No | How to list the created configuration in the portal (default: Admin API ) |
profile_id |
Yes | The profile_id of the VPN profile to create a configuration for |
prefer_tcp |
No | Prefer connecting over TCP to the server. Either yes or no . Defaults to no |
Request#
Obtain a configuration file for the “Employees” profile (employees
) for the
user foo
:
$ curl \
--data-urlencode "user_id=foo" \
--data-urlencode "profile_id=employees" \
--data-urlencode "display_name=Admin API Example Config" \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/create"
Destroy#
Remove the VPN configurations of a particular user and delete their account.
Parameter | Required | Value(s) |
---|---|---|
user_id |
Yes | The user for which to delete the configuration(s) and delete their account |
TODO: should we also require profile_id
to only delete config of certain
profile?
TODO: should we also allow for not deleting the user account? if the answer to the above question is YES then we should probably not (always) delete the user account
Request#
$ curl \
--data-urlencode "user_id=foo" \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/destroy"
Disable User#
Disable a user account and disconnect all active connections.
Parameter | Required | Value(s) |
---|---|---|
user_id |
Yes | The user account to disable |
Request#
$ curl \
--data-urlencode "user_id=foo" \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/disable_user"
Enable User#
Enable a user account.
Parameter | Required | Value(s) |
---|---|---|
user_id |
Yes | The user account to enable |
Request#
$ curl \
--data-urlencode "user_id=foo" \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/enable_user"
Delete Connection#
Delete a connection.
Parameter | Required | Value(s) |
---|---|---|
user_id |
Yes | The user account to which the connection belongs |
connection_id |
Yes | The connection identifier |
The connection_id
field references the Common Name (CN) for OpenVPN and the
public key for WireGuard.
Request#
$ curl \
--data-urlencode "user_id=foo" \
--data-urlencode "connection_id=z/2CtDHH/tJBosty+bjF7JhCZ8K8ulqqi3/ODAfzDRI=" \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/delete_connection"
Delete OAuth Authorizations#
This call will delete all OAuth authorizations for the specified user. It will NOT do anything else, i.e. not delete configurations or disconnect VPN users. Use the other API calls for this.
Parameter | Required | Value(s) |
---|---|---|
user_id |
Yes | The user account for which to delete the OAuth Authorizations |
Request#
$ curl \
--data-urlencode "user_id=foo" \
-H "Authorization: Bearer abcdefgh" \
"https://vpn.example.org/vpn-user-portal/admin/api/v1/delete_user_authorizations"
VPN Client#
We’ll describe how to configure VPN clients with these configuration files.
Windows#
Complete documentation on how to setup Windows with WireGuard to have VPN enabled before user authentication can be found here.
You can deploy the configuration file and MSI through AD/GPO and enable the service as documented.
macOS#
Probably using this.