add admin stuff

This commit is contained in:
2026-08-20 10:43:19 +02:00
parent 7108d446d8
commit 91758a2701
19 changed files with 2514 additions and 85 deletions

393
templates/admin.html Normal file
View File

@ -0,0 +1,393 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Jumphost Admin</title>
<link rel="stylesheet" href="/static/css/app.css">
</head>
<body>
<div class="topbar">
<div class="brand">Jumphost &middot; Admin</div>
<div>
<span class="hint" id="whoami"></span>
<a href="/dashboard">Zum Dashboard</a>
<a href="/docs" target="_blank" rel="noopener">API-Dokumentation</a>
<button id="logout-btn">Abmelden</button>
</div>
</div>
<div class="container wide">
<div id="banner-box"></div>
<div class="tabs" id="tabs">
<button type="button" class="tab-btn active" data-tab="users">Benutzer</button>
<button type="button" class="tab-btn" data-tab="groups">Benutzergruppen</button>
<button type="button" class="tab-btn" data-tab="hosts">Hosts &amp; Verbindungen</button>
<button type="button" class="tab-btn" data-tab="roles">Rollen</button>
<button type="button" class="tab-btn" data-tab="tokens">API-Tokens</button>
<button type="button" class="tab-btn" data-tab="audit">Audit-Log</button>
</div>
<!-- ================= Benutzer ================= -->
<div class="tab-panel" id="tab-users">
<div class="panel">
<h2>Neuen Benutzer anlegen</h2>
<form id="user-create-form" class="form-grid">
<div>
<label for="uc-username">Benutzername</label>
<input type="text" id="uc-username" required minlength="3" maxlength="64">
</div>
<div>
<label for="uc-password">Initiales Passwort (min. 12 Zeichen)</label>
<input type="text" id="uc-password" required minlength="12" maxlength="256">
</div>
<div class="checkbox-row">
<input type="checkbox" id="uc-is-admin">
<label for="uc-is-admin">Globaler Admin</label>
</div>
<button type="submit">Anlegen</button>
</form>
</div>
<div class="panel">
<h2>Benutzer</h2>
<div class="table-wrap">
<table class="data-table" id="users-table">
<thead>
<tr>
<th>ID</th><th>Benutzername</th><th>Admin</th><th>Aktiv</th>
<th>TOTP</th><th>Erstellt</th><th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<!-- ================= Benutzergruppen ================= -->
<div class="tab-panel hidden" id="tab-groups">
<div class="panel">
<h2>Neue Benutzergruppe anlegen</h2>
<form id="group-create-form" class="form-grid">
<div>
<label for="gc-name">Name</label>
<input type="text" id="gc-name" required maxlength="128">
</div>
<div>
<label for="gc-description">Beschreibung (optional)</label>
<input type="text" id="gc-description" maxlength="1024">
</div>
<button type="submit">Anlegen</button>
</form>
</div>
<div class="panel">
<h2>Benutzergruppen</h2>
<p class="hint">Rollen fuer eine Gruppe (= Verbindungen mit der ganzen Gruppe teilen) werden im Tab "Rollen" vergeben.</p>
<div class="table-wrap">
<table class="data-table" id="groups-table">
<thead><tr><th>ID</th><th>Name</th><th>Beschreibung</th><th>Mitglieder</th><th></th></tr></thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="panel hidden" id="group-members-panel">
<h2>Mitglieder von <span id="group-members-name"></span></h2>
<div class="table-wrap">
<table class="data-table" id="group-members-table">
<thead><tr><th>User-ID</th><th>Benutzername</th><th>Hinzugefuegt</th><th></th></tr></thead>
<tbody></tbody>
</table>
</div>
<h3>Mitglied hinzufuegen</h3>
<form id="group-member-add-form" class="form-grid">
<div>
<label for="gm-user-select">Benutzer</label>
<select id="gm-user-select" required></select>
</div>
<button type="submit">Hinzufuegen</button>
</form>
</div>
</div>
<!-- ================= Hosts & Verbindungen ================= -->
<div class="tab-panel hidden" id="tab-hosts">
<div class="panel">
<h2>Neue Hostgruppe anlegen</h2>
<form id="hostgroup-create-form" class="form-grid">
<div>
<label for="hgc-name">Name</label>
<input type="text" id="hgc-name" required maxlength="128">
</div>
<div>
<label for="hgc-description">Beschreibung (optional)</label>
<input type="text" id="hgc-description" maxlength="1024">
</div>
<button type="submit">Anlegen</button>
</form>
<h3>Hostgruppen</h3>
<div class="table-wrap">
<table class="data-table" id="hostgroups-table">
<thead><tr><th>ID</th><th>Name</th><th>Beschreibung</th></tr></thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="panel">
<h2>Neue Verbindung (Host) anlegen</h2>
<form id="host-create-form" class="form-grid">
<div>
<label for="hc-hostgroup">Hostgruppe</label>
<select id="hc-hostgroup" required></select>
</div>
<div>
<label for="hc-hostname">Hostname (Label)</label>
<input type="text" id="hc-hostname" required maxlength="128" pattern="[a-zA-Z0-9][a-zA-Z0-9._-]*">
</div>
<div>
<label for="hc-address">Adresse (IP/DNS)</label>
<input type="text" id="hc-address" required maxlength="255">
</div>
<div>
<label for="hc-protocol">Protokoll</label>
<select id="hc-protocol">
<option value="ssh">SSH</option>
<option value="rdp">RDP</option>
</select>
</div>
<div>
<label for="hc-port">Port</label>
<input type="text" id="hc-port" inputmode="numeric" value="22" required maxlength="5">
</div>
<div>
<label for="hc-os-type">Betriebssystem</label>
<select id="hc-os-type">
<option value="linux">Linux</option>
<option value="windows">Windows</option>
</select>
</div>
<div id="hc-ssh-username-box">
<label for="hc-ssh-username">SSH-Benutzername</label>
<input type="text" id="hc-ssh-username" maxlength="128">
</div>
<div id="hc-rdp-username-box" class="hidden">
<label for="hc-rdp-username">RDP-Benutzername</label>
<input type="text" id="hc-rdp-username" maxlength="128">
</div>
<div id="hc-rdp-domain-box" class="hidden">
<label for="hc-rdp-domain">RDP-Domaene (optional)</label>
<input type="text" id="hc-rdp-domain" maxlength="128">
</div>
<div class="checkbox-row"><input type="checkbox" id="hc-clipboard" checked><label for="hc-clipboard">Zwischenablage erlaubt</label></div>
<div class="checkbox-row"><input type="checkbox" id="hc-filetransfer" checked><label for="hc-filetransfer">Dateitransfer erlaubt</label></div>
<div class="checkbox-row hidden" id="hc-nla-box"><input type="checkbox" id="hc-nla" checked><label for="hc-nla">RDP: NLA erforderlich</label></div>
<button type="submit">Verbindung anlegen</button>
</form>
</div>
<div class="panel">
<h2>Vorhandene Hosts</h2>
<div class="table-wrap">
<table class="data-table" id="hosts-table">
<thead>
<tr><th>ID</th><th>Hostname</th><th>Adresse</th><th>Protokoll</th><th>OS</th><th>Hostgruppe</th><th></th></tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="panel hidden" id="host-detail-panel">
<h2>Verbindung: <span id="host-detail-name"></span></h2>
<div id="host-detail-ssh">
<h3>SSH-Host-Key</h3>
<p class="hint">Ermittelt den Host-Key EINMALIG ohne Pruefung (bewusste Trust-Entscheidung) und speichert den Fingerprint fuer kuenftiges Pinning. Wird prominent im Audit-Log vermerkt.</p>
<button type="button" class="btn-secondary" id="host-discover-key-btn">Host-Key ermitteln</button>
<div id="host-key-result" class="reveal-box hidden"></div>
<h3>SSH-Key zuordnen</h3>
<form id="host-key-map-form" class="form-grid">
<div>
<label for="hkm-key-select">SSH-Key</label>
<select id="hkm-key-select" required></select>
</div>
<button type="submit">Zuordnen</button>
</form>
</div>
<div id="host-detail-rdp" class="hidden">
<h3>RDP-Zugangsdaten setzen</h3>
<form id="host-rdp-cred-form" class="form-grid">
<div class="full-width">
<label for="hrc-password">RDP-Passwort</label>
<input type="text" id="hrc-password" required maxlength="512">
</div>
<button type="submit">Speichern</button>
</form>
</div>
</div>
<div class="panel">
<h2>Neuen SSH-Key anlegen</h2>
<form id="ssh-key-create-form" class="form-grid">
<div>
<label for="skc-label">Label</label>
<input type="text" id="skc-label" required maxlength="128">
</div>
<div>
<label for="skc-owner">Besitzer (User-ID, optional)</label>
<input type="text" id="skc-owner" inputmode="numeric" maxlength="10">
</div>
<div>
<label for="skc-type">Key-Typ</label>
<select id="skc-type">
<option value="ed25519">ed25519</option>
<option value="rsa-3072">rsa-3072</option>
<option value="rsa-4096">rsa-4096</option>
<option value="ca-cert">ca-cert</option>
</select>
</div>
<div class="full-width">
<label for="skc-private">Privater Schluessel (PEM)</label>
<textarea id="skc-private" required></textarea>
</div>
<div class="full-width">
<label for="skc-public">Oeffentlicher Schluessel</label>
<textarea id="skc-public" required></textarea>
</div>
<button type="submit">Anlegen</button>
</form>
<h3>Vorhandene SSH-Keys</h3>
<div class="table-wrap">
<table class="data-table" id="ssh-keys-table">
<thead><tr><th>ID</th><th>Label</th><th>Typ</th><th>Besitzer</th><th>Erstellt</th></tr></thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<!-- ================= Rollen ================= -->
<div class="tab-panel hidden" id="tab-roles">
<div class="panel">
<h2>Rolle an Benutzer vergeben</h2>
<form id="role-grant-form" class="form-grid">
<div>
<label for="rg-user">Benutzer</label>
<select id="rg-user" required></select>
</div>
<div>
<label for="rg-hostgroup">Hostgruppe</label>
<select id="rg-hostgroup" required></select>
</div>
<div>
<label for="rg-role">Rolle</label>
<select id="rg-role"></select>
</div>
<div>
<label for="rg-expires">Ablaufdatum (optional, ISO)</label>
<input type="text" id="rg-expires" placeholder="2026-12-31T00:00:00.000Z" maxlength="40">
</div>
<button type="submit">Vergeben</button>
</form>
<div class="table-wrap">
<table class="data-table" id="role-grants-table">
<thead><tr><th>Benutzer</th><th>Hostgruppe</th><th>Rolle</th><th>Ablauf</th><th></th></tr></thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="panel">
<h2>Rolle an Benutzergruppe vergeben (Verbindung mit Gruppe teilen)</h2>
<p class="hint">Volle Rollen-Vererbung: jedes aktuelle und zukuenftige Mitglied der Gruppe erhaelt diese Rolle automatisch.</p>
<form id="group-role-grant-form" class="form-grid">
<div>
<label for="grg-group">Benutzergruppe</label>
<select id="grg-group" required></select>
</div>
<div>
<label for="grg-hostgroup">Hostgruppe</label>
<select id="grg-hostgroup" required></select>
</div>
<div>
<label for="grg-role">Rolle</label>
<select id="grg-role"></select>
</div>
<div>
<label for="grg-expires">Ablaufdatum (optional, ISO)</label>
<input type="text" id="grg-expires" placeholder="2026-12-31T00:00:00.000Z" maxlength="40">
</div>
<button type="submit">Vergeben</button>
</form>
<div class="table-wrap">
<table class="data-table" id="group-role-grants-table">
<thead><tr><th>Gruppe</th><th>Hostgruppe</th><th>Rolle</th><th>Ablauf</th><th></th></tr></thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<!-- ================= API-Tokens ================= -->
<div class="tab-panel hidden" id="tab-tokens">
<div class="panel">
<h2>Neues API-Token erstellen</h2>
<p class="hint">Tokens wirken NUR auf die Verwaltungs-API (Benutzer/Hosts/Rollen/...), nie auf SSH-/RDP-Sitzungen selbst. "rw" schliesst "ro" auf derselben Ressource automatisch mit ein.</p>
<form id="token-create-form" class="form-grid">
<div>
<label for="tc-label">Bezeichnung</label>
<input type="text" id="tc-label" required maxlength="128">
</div>
<div>
<label for="tc-user">Fuer Benutzer</label>
<select id="tc-user" required></select>
</div>
<div>
<label for="tc-expires">Ablaufdatum (optional, ISO)</label>
<input type="text" id="tc-expires" placeholder="2026-12-31T00:00:00.000Z" maxlength="40">
</div>
<div class="full-width">
<label>Scopes</label>
<div class="scope-grid" id="tc-scope-grid"></div>
</div>
<button type="submit">Token erstellen</button>
</form>
<div id="token-reveal-box" class="reveal-box hidden"></div>
</div>
<div class="panel">
<h2>Vorhandene Tokens</h2>
<div class="table-wrap">
<table class="data-table" id="tokens-table">
<thead>
<tr><th>ID</th><th>Bezeichnung</th><th>Benutzer</th><th>Praefix</th><th>Scopes</th><th>Zuletzt genutzt</th><th>Status</th><th></th></tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<!-- ================= Audit-Log ================= -->
<div class="tab-panel hidden" id="tab-audit">
<div class="panel">
<h2>Audit-Log</h2>
<button type="button" class="btn-secondary" id="audit-verify-btn">Ketten-Integritaet pruefen</button>
<div id="audit-verify-result" class="hidden"></div>
<div class="table-wrap">
<table class="data-table" id="audit-table">
<thead><tr><th>ID</th><th>Zeit</th><th>User-ID</th><th>IP</th><th>Ereignis</th><th>Details</th></tr></thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
<script src="/static/js/admin.js"></script>
</body>
</html>