fix: vpn-router-setup owns only the creation of the metrics service's account, which is marked internal, and administrators add service accounts with vpn-router-user add --service and /users.
Release / release (push) Successful in 32s

This commit is contained in:
slawek committed 2026-10-25 18:00:25 +01:00
1 parent bf651da5a6
commit d1970b77b7
6 files changed
+73 -26

No files matched your search

+10 -3
View File
@@ -441,9 +441,11 @@ def users(state, method, path, body):
GET /users the users
POST /users add a user: {"name", "password", "first_name", "last_name", "email"};
without the names a Manager-only account
without the names a Manager-only account, and with "service": true a
service account
PUT /users/<name> change any of {"first_name", "last_name", "email"}
PUT /users/<name>/password set the password: {"password": ...}
PUT /users/<name>/password set the password: {"password": ...}; refused for the internal service
account, whose password vpn-router-setup keeps
POST /users/<name>/disable lock the user out of OpenVPN
POST /users/<name>/enable let the user in again
POST /users/<name>/unlock end a lockout after failed logins
@@ -461,7 +463,8 @@ def users(state, method, path, body):
name = parts[1] if len(parts) > 1 else None
actions = {
('GET', 1, None): lambda connection: vpnrouter_users.list_users(connection),
('POST', 1, None): lambda connection: vpnrouter_users.add(connection, body.get('name'), body.get('password'), body),
('POST', 1, None): lambda connection: vpnrouter_users.add(connection, body.get('name'), body.get('password'), body,
service=body.get('service') is True),
('PUT', 2, None): lambda connection: vpnrouter_users.update(connection, name, body),
('PUT', 3, 'password'): lambda connection: vpnrouter_users.passwd(connection, name, body.get('password')),
('POST', 3, 'disable'): lambda connection: vpnrouter_users.disable(connection, name),
@@ -478,6 +481,10 @@ def users(state, method, path, body):
('DELETE', 2, None): 'remove'}
if route not in actions:
return 404, {'error': f'no route {method} {path}'}
if route == ('POST', 1, None) and not isinstance(body.get('service', False), bool):
return 400, {'error': 'service must be true or false'}
if route == ('PUT', 3, 'password') and name == vpnrouter_users.metrics_account():
return 400, {'error': f'{name} is the internal service account of the metrics service; vpn-router-setup keeps its password'}
try:
with vpnrouter_users.session() as connection:
document = actions[route](connection)