Add authentication: admin/agent bearer tokens for the API, login for the dashboard
control-api: every route now carries a mandatory access level (admin / agent / open) in a route table. All /api/v1/admin/* require the admin token; the write calls of validator-agent and prober (self-check, events, results, complete) require a separate static agent token; register, heartbeat and fetching the assignment stay open. Tokens come from env vars, are compared in constant time and never logged. An empty token leaves that level open with a startup warning (backward compatible). validator-agent / prober: apiclient sends the agent token only to control-api. admin-dashboard: login/password (from env) with a stateless HMAC session cookie, Origin-based CSRF check, per-IP brute-force throttle, HX-Redirect for htmx polls, logout in the sidebar; the dashboard calls control-api with the admin token. Login page layout fixed after review. Also: env plumbing in docker-compose/rxprod-compose/systemd/config examples, e2e script with token assertions, tests, docs (API, SETUP, USAGE, DASHBOARD, README), plan and review under docs/changes/, bin/ rebuilt with new SHA256SUMS. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
972ad47d0c
commit
debf2afed2
67 files changed
+2050
-105
No files matched your search
@@ -78,6 +78,13 @@
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
{{if .AuthEnabled}}
|
||||
<form class="sidebar-user" method="post" action="/logout">
|
||||
<span class="sidebar-user-name" title="{{.User}}">{{.User}}</span>
|
||||
<button type="submit" class="btn btn-ghost btn-sm">Выйти</button>
|
||||
</form>
|
||||
{{end}}
|
||||
|
||||
<div class="sidebar-foot">
|
||||
<span class="sidebar-foot-status"><span class="pulse-dot"></span>control-api</span>
|
||||
<button type="button" class="theme-toggle" id="themeToggle" aria-label="Переключить тему" title="Переключить тему">
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
{{define "login_page"}}
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>{{template "html_head" .}}</head>
|
||||
<body>
|
||||
<div class="bg-grid"></div>
|
||||
<main class="login-shell">
|
||||
<div class="login-card">
|
||||
<form class="panel" method="post" action="/login" autocomplete="on">
|
||||
<div class="panel-head"><h2>Cloud IP Validator — вход</h2></div>
|
||||
<div class="panel-body">
|
||||
{{if .Error}}<div class="alert alert-warning" role="alert">{{.Error}}</div>{{end}}
|
||||
<input type="hidden" name="next" value="{{.Next}}">
|
||||
<div class="field">
|
||||
<label for="login-username">Логин</label>
|
||||
<input type="text" id="login-username" name="username" autocomplete="username" autofocus required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="login-password">Пароль</label>
|
||||
<input type="password" id="login-password" name="password" autocomplete="current-password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block">Войти</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
Reference in new issue
Block a user