Refine OCSentinel security dashboard
Some checks failed
OfficeCom Sentinel Client / validate-client (push) Successful in 24s
OfficeCom Sentinel Client / build-client-windows (push) Failing after 19s

This commit is contained in:
OfficeCom Codex
2026-07-26 03:39:57 +02:00
parent 2f2a553fc2
commit a45a811040
4 changed files with 28 additions and 19 deletions

View File

@@ -5,7 +5,9 @@ body { margin:0; color:var(--ink); background:radial-gradient(circle at 86% -10%
.brand { color:var(--ink); font:700 20px/1 Arial,sans-serif; text-decoration:none; letter-spacing:-.04em; }.brand span { display:inline-grid; place-items:center; margin-right:7px; width:28px; height:28px; background:var(--green); color:#fff; border-radius:50%; font-size:11px; letter-spacing:0; }.badge,.eyebrow { color:var(--muted); font:700 10px/1 Arial,sans-serif; text-transform:uppercase; letter-spacing:.12em; }.badge { border:1px solid var(--line); padding:6px 8px; border-radius:20px; }
main { max-width:1280px; margin:auto; padding:58px 6vw 80px; }.hero { max-width:650px; margin-bottom:32px; }.hero h1 { font-size:clamp(34px,5vw,64px); line-height:.98; letter-spacing:-.06em; margin:10px 0; }.hero p { color:var(--muted); font-size:18px; }.hero.compact h1 { font-size:48px; }
.metrics { display:grid; grid-template-columns:repeat(5,1fr); gap:1px; margin:25px 0 46px; border:1px solid var(--line); background:var(--line); }.metrics article { min-height:130px; padding:20px; background:var(--panel); }.metrics span { display:block; color:var(--muted); font:700 10px Arial,sans-serif; letter-spacing:.09em; text-transform:uppercase; }.metrics strong { display:block; margin-top:16px; font:700 31px Arial,sans-serif; letter-spacing:-.05em; }.metrics .timestamp { font-size:14px; line-height:1.25; letter-spacing:-.02em; }.warning { color:var(--amber); }.critical { color:var(--red); }
.situation { display:flex; align-items:center; justify-content:space-between; gap:22px; margin:0 0 24px; padding:20px 22px; border:1px solid #b9d8c2; background:#edf8f0; color:#195235; }.situation.warning { border-color:#f2cf99; background:#fff6e8; color:#80450d; }.situation.critical { border-color:#edb4aa; background:#fff0ed; color:#8a2a20; }.situation strong { display:block; margin-top:7px; font:700 19px/1.15 Arial,sans-serif; letter-spacing:-.025em; }.situation > span { padding:7px 9px; border:1px solid currentColor; border-radius:20px; font:700 10px Arial,sans-serif; letter-spacing:.1em; }
.panel { margin-top:26px; padding:26px; background:var(--panel); border:1px solid var(--line); }.panel-heading h2 { margin:8px 0 22px; font-size:28px; letter-spacing:-.04em; }.alert-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:12px; }.alert-card { padding:17px; border-left:5px solid var(--amber); background:#fff7e9; color:var(--ink); text-decoration:none; }.alert-card.critical { border-color:var(--red); background:#fff0ed; }.alert-card span,.alert-card small { display:block; font:700 10px Arial,sans-serif; letter-spacing:.08em; text-transform:uppercase; }.alert-card strong { display:block; margin:10px 0; font:700 22px Arial,sans-serif; letter-spacing:-.04em; }
table { width:100%; border-collapse:collapse; font-family:Arial,sans-serif; font-size:13px; } th { text-align:left; color:var(--muted); font-size:10px; letter-spacing:.1em; text-transform:uppercase; } th,td { padding:13px 8px; border-bottom:1px solid var(--line); } td a { color:var(--green); font-weight:700; text-decoration:none; }.state { display:inline-block; padding:4px 7px; border-radius:12px; background:#e2efe6; color:var(--green); font:700 10px Arial,sans-serif; text-transform:uppercase; }.state.warning { background:#fff0d7; color:var(--amber); }.state.critical { background:#ffe0db; color:var(--red); } pre { margin:0; padding:18px; overflow:auto; color:#dce7da; background:#13221b; border-radius:4px; font:12px/1.5 'Cascadia Code',Consolas,monospace; }.table-wrap { overflow:auto; }
.report-frame { background:#fff; border:1px solid var(--line); box-shadow:0 12px 40px rgba(20,35,27,.1); }
@media (max-width:850px) { .metrics { grid-template-columns:repeat(2,1fr); }.metrics article:last-child { grid-column:span 2; }.masthead { padding:0 5vw; }.badge { display:none; } main { padding:38px 5vw; } }
.panel-heading p:last-child { max-width:720px; margin:-13px 0 20px; color:var(--muted); font-size:14px; }.calm-panel { border-color:#b9d8c2; background:#f4fbf5; }
@media (max-width:850px) { .metrics { grid-template-columns:repeat(2,1fr); }.metrics article:last-child { grid-column:span 2; }.masthead { height:auto; min-height:70px; padding:14px 5vw; align-items:flex-start; }.header-links { justify-content:flex-end; flex-wrap:wrap; }.badge { display:none; } main { padding:38px 5vw; }.situation { align-items:flex-start; flex-direction:column; } }

View File

@@ -8,8 +8,8 @@
</head>
<body>
<header class="masthead">
<a href="/" class="brand"><span>OC</span> Sentinel Debug</a>
<div class="header-links"><a href="{{ url_for('reports') }}">Wochenberichte</a><div class="badge">read-only database console</div></div>
<a href="/" class="brand"><span>OC</span> Sentinel</a>
<div class="header-links"><a href="/">Sicherheitslage</a><a href="{{ url_for('reports') }}">Wochenberichte</a><div class="badge">interner Sicherheitsbereich</div></div>
</header>
<main>{% block content %}{% endblock %}</main>
</body>

View File

@@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block title %}{{ report[0] }} · OCSentinel Debug{% endblock %}
{% block title %}{{ report[0] }} - OCSentinel{% endblock %}
{% block content %}
<section class="hero compact"><p class="eyebrow">Gerätedetail</p><h1>{{ report[0] }}</h1><p><span class="state {{ report[6] }}">{{ report[6] }}</span> · Eingang {{ report[5] }}</p></section>
<section class="metrics compact-metrics"><article><span>Events</span><strong>{{ report[8] }}</strong></article><article><span>Quell-IPs</span><strong>{{ report[9] }}</strong></article><article><span>CVEs</span><strong>{{ report[10] }}</strong></article><article><span>Kritisch/High</span><strong class="critical">{{ report[11] }}</strong></article></section>
<section class="panel"><div class="panel-heading"><p class="eyebrow">Forensik</p><h2>Signierter Rohreport</h2></div><pre>{{ payload_pretty }}</pre></section>
<section class="hero compact"><p class="eyebrow">Geraetedetails</p><h1>{{ report[0] }}</h1><p><span class="state {{ report[6] }}">{{ report[6] }}</span> | Letzte Datenmeldung: {{ report[5] }}</p></section>
<section class="metrics compact-metrics"><article><span>Ereignisse</span><strong>{{ report[8] }}</strong></article><article><span>Quell-IPs</span><strong>{{ report[9] }}</strong></article><article><span>CVEs</span><strong>{{ report[10] }}</strong></article><article><span>Kritische CVEs</span><strong class="critical">{{ report[11] }}</strong></article></section>
<section class="panel"><div class="panel-heading"><p class="eyebrow">Technische Details</p><h2>Signierter Sicherheitsbericht</h2><p>Unveraenderte Rohdaten zur Nachvollziehbarkeit und Fehleranalyse.</p></div><pre>{{ payload_pretty }}</pre></section>
{% endblock %}

View File

@@ -1,35 +1,42 @@
{% extends "base.html" %}
{% block content %}
<section class="hero">
<p class="eyebrow">Central Ingest</p>
<h1>Endpoint Signals, ohne Rauschen.</h1>
<p>Letzte signierte OCSentinel-Berichte aus PostgreSQL.</p>
<p class="eyebrow">OCSentinel Sicherheitszentrale</p>
<h1>Sicherheitslage auf einen Blick.</h1>
<p>Aktuelle Auswertung aller signierten Sicherheitsberichte aus den betreuten Organisationen.</p>
</section>
<section class="situation {% if summary[2] %}critical{% elif summary[1] %}warning{% else %}ok{% endif %}">
<div><p class="eyebrow">Aktuelle Lage</p><strong>{% if summary[2] %}Kritische Ereignisse erfordern Aufmerksamkeit.{% elif summary[1] %}Hinweise vorhanden - bitte auffaellige Geraete pruefen.{% else %}Keine kritischen Auffaelligkeiten gemeldet.{% endif %}</strong></div>
<span>{% if summary[2] %}KRITISCH{% elif summary[1] %}PRUEFEN{% else %}STABIL{% endif %}</span>
</section>
<section class="metrics">
<article><span>Berichtende Geräte</span><strong>{{ summary[0] }}</strong></article>
<article><span>Geraete mit Bericht</span><strong>{{ summary[0] }}</strong></article>
<article><span>Warnungen</span><strong class="warning">{{ summary[1] }}</strong></article>
<article><span>Kritisch</span><strong class="critical">{{ summary[2] }}</strong></article>
<article><span>Events</span><strong>{{ summary[3] }}</strong></article>
<article><span>Letzter Eingang</span><strong class="timestamp">{{ summary[7] or 'noch keiner' }}</strong></article>
<article><span>Kritische Geraete</span><strong class="critical">{{ summary[2] }}</strong></article>
<article><span>Erkannte Ereignisse</span><strong>{{ summary[3] }}</strong></article>
<article><span>Letzte Datenmeldung</span><strong class="timestamp">{{ summary[7] or 'noch keine Daten' }}</strong></article>
</section>
{% if alerts %}
<section class="panel alert-panel">
<div class="panel-heading"><p class="eyebrow">Priorität</p><h2>Auffällige Geräte</h2></div>
<div class="panel-heading"><p class="eyebrow">Handlungsbedarf</p><h2>Auffaellige Geraete</h2><p>Diese Geraete haben zuletzt Warnungen oder kritische Sicherheitsereignisse gemeldet.</p></div>
<div class="alert-grid">
{% for alert in alerts %}
<a class="alert-card {{ alert[1] }}" href="{{ url_for('device', machine_name=alert[0]) }}">
<span>{{ alert[1] }}</span><strong>{{ alert[0] }}</strong><small>{{ alert[2] }} Events · {{ alert[3] }} IPs · {{ alert[4] }}</small>
<span>{{ alert[1] }}</span><strong>{{ alert[0] }}</strong><small>{{ alert[2] }} Ereignisse | {{ alert[3] }} Quell-IPs | {{ alert[4] }}</small>
</a>
{% endfor %}
</div>
</section>
{% else %}
<section class="panel calm-panel"><div class="panel-heading"><p class="eyebrow">Handlungsbedarf</p><h2>Keine auffaelligen Geraete</h2><p>Die zuletzt eingegangenen Berichte enthalten keine Warnungen oder kritischen Ereignisse.</p></div></section>
{% endif %}
<section class="panel">
<div class="panel-heading"><p class="eyebrow">Live-Bestand</p><h2>Letzte Geräteberichte</h2></div>
<div class="table-wrap"><table><thead><tr><th>Gerät</th><th>Organisation</th><th>Status</th><th>Events</th><th>IPs</th><th>Empfangen</th></tr></thead>
<tbody>{% for row in reports %}<tr><td><a href="{{ url_for('device', machine_name=row[0]) }}">{{ row[0] }}</a></td><td>{{ row[1] or '' }}</td><td><span class="state {{ row[3] }}">{{ row[3] }}</span></td><td>{{ row[4] }}</td><td>{{ row[5] }}</td><td>{{ row[2] or '' }}</td></tr>{% endfor %}</tbody></table></div>
<div class="panel-heading"><p class="eyebrow">Berichtsbestand</p><h2>Aktuelle Geraetestatus</h2><p>Jede Zeile zeigt den letzten erfolgreich uebermittelten OCSentinel-Bericht eines Geraets.</p></div>
<div class="table-wrap"><table><thead><tr><th>Geraet</th><th>Organisation</th><th>Status</th><th>Ereignisse</th><th>Quell-IPs</th><th>Empfangen</th></tr></thead>
<tbody>{% for row in reports %}<tr><td><a href="{{ url_for('device', machine_name=row[0]) }}">{{ row[0] }}</a></td><td>{{ row[1] or '-' }}</td><td><span class="state {{ row[3] }}">{{ row[3] }}</span></td><td>{{ row[4] }}</td><td>{{ row[5] }}</td><td>{{ row[2] or '-' }}</td></tr>{% else %}<tr><td colspan="6">Noch keine Geraeteberichte vorhanden.</td></tr>{% endfor %}</tbody></table></div>
</section>
{% endblock %}