|
|
|
@@ -8,6 +8,8 @@ Pages:
|
|
|
|
|
/ the status for people: plain text for curl and wget, a styled page
|
|
|
|
|
(Tailwind CSS from a CDN) for a browser
|
|
|
|
|
/status the status as JSON
|
|
|
|
|
/status/full
|
|
|
|
|
the whole status as JSON, whatever web.status_content says, for the Router Manager
|
|
|
|
|
/config the configuration without its secrets, and what the router resolved and
|
|
|
|
|
runs, with the installed Caddy and where it comes from, as JSON
|
|
|
|
|
/users the users in the router's directory, whether or not a P2S system is enabled: list,
|
|
|
|
@@ -40,7 +42,7 @@ Pages:
|
|
|
|
|
the databases of each PostgreSQL cluster on the router with their sizes, as JSON (see
|
|
|
|
|
postgresql_databases()); /config has the clusters' settings
|
|
|
|
|
|
|
|
|
|
/config, /metrics/history, /postgresql, /users, /service-accounts, /groups, /site-to-site, /backup, /ca and /account need an HS256 JWT in an Authorization: Bearer header signed
|
|
|
|
|
/status/full, /config, /metrics/history, /postgresql, /users, /service-accounts, /groups, /site-to-site, /backup, /ca and /account need an HS256 JWT in an Authorization: Bearer header signed
|
|
|
|
|
with vpnrouter_auth.WEB_KEY (see vpnrouter_auth.verify). A token of /auth names a user in sub;
|
|
|
|
|
/account serves that user, and the other paths need a member of vpnrouter_users.ADMIN_GROUP. A
|
|
|
|
|
token of vpn-router-token has the admin claim and names no user; it may call every path but
|
|
|
|
@@ -1042,7 +1044,7 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
|
|
directory = next((name for name in ('users', 'service-accounts', 'groups', 'account', 'site-to-site', 'backup',
|
|
|
|
|
'ca')
|
|
|
|
|
if path == f'/{name}' or path.startswith(f'/{name}/')), None)
|
|
|
|
|
protected = path in ('/config', '/metrics/history', '/postgresql') or directory is not None
|
|
|
|
|
protected = path in ('/status/full', '/config', '/metrics/history', '/postgresql') or directory is not None
|
|
|
|
|
signing = path in ('/auth', '/auth/refresh', '/auth/logout')
|
|
|
|
|
state = current() if protected or signing else {}
|
|
|
|
|
claims = self.claims(state['key']) if protected and state['key'] else None
|
|
|
|
@@ -1067,6 +1069,9 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
|
|
elif protected and (refused := self.refusal(claims, path, payload)):
|
|
|
|
|
code, kind = refused[0], 'application/json'
|
|
|
|
|
body = json.dumps({'error': refused[1]}, indent=2).encode() + b'\n'
|
|
|
|
|
elif path == '/status/full' and self.command in ('GET', 'HEAD'):
|
|
|
|
|
document = shown(self.status(), 'full', self.client())
|
|
|
|
|
body, kind, code = json.dumps(document, indent=2).encode() + b'\n', 'application/json', 200
|
|
|
|
|
elif path == '/config' and self.command in ('GET', 'HEAD'):
|
|
|
|
|
body, kind, code = json.dumps(details(state), indent=2).encode() + b'\n', 'application/json', 200
|
|
|
|
|
elif path == '/postgresql' and self.command in ('GET', 'HEAD'):
|
|
|
|
|