OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

detail.php

10 KB
<?php
$this->layout('layouts/main', [
    'page_title'    => $page_title,
    'current_route' => 'xdr',
    'full_width'    => true,
]);

$alert         = $alert ?? [];
$mitre         = $mitre ?? [];
$raw           = $raw ?? [];
$assets        = $assets ?? [];
$canManage     = $can_manage ?? false;
$ticketEnabled = $ticket_enabled ?? false;
$view          = $this;

$sev = (string)($alert['severity'] ?? 'medium');
$st  = (string)($alert['local_status'] ?? 'new');

$sevPill = ['critical'=>'status-pill--danger','high'=>'status-pill--orange','medium'=>'status-pill--warning','low'=>'status-pill--info','info'=>'status-pill--neutral'];
$sevLabel = ['critical'=>'Kritisch','high'=>'Hoch','medium'=>'Mittel','low'=>'Niedrig','info'=>'Info'];
$statusLabel = ['new'=>'Neu','investigating'=>'In Bearbeitung','acknowledged'=>'Quittiert','resolved'=>'Erledigt','dismissed'=>'Verworfen'];
$providerLabel = ['trendmicro' => 'Trend Vision One', 'defender' => 'Microsoft Defender XDR'];
$typeLabel     = ['oat' => 'Observed Attack Technique', 'alert' => 'Alarm', 'workbench' => 'Workbench Alert'];
$actionLabel   = ['suppress' => 'verworfen', 'assign' => 'einer Person zugewiesen', 'ticket' => 'für ein Ticket vorgemerkt'];
?>

<div class="content-header">
    <div>
        <h1><?= $this->te('XDR-Warnung') ?></h1>
        <ol class="breadcrumb">
            <li class="breadcrumb-item"><a href="/"><?= $this->te('Home') ?></a></li>
            <li class="breadcrumb-item"><a href="/xdr">XDR</a></li>
            <li class="breadcrumb-item active">#<?= (int)($alert['id'] ?? 0) ?></li>
        </ol>
    </div>
    <div class="content-header-actions">
        <a href="/xdr" class="btn btn-default btn-sm"><?= $this->te('&laquo; Zur Übersicht') ?></a>
    </div>
</div>

<div class="page-body">
    <div class="detail-card">
        <div class="detail-card-header">
            <span class="detail-card-title">
                <span class="status-pill <?= $sevPill[$sev] ?? 'status-pill--neutral' ?>"><?= $sevLabel[$sev] ?? $view->e($sev) ?></span>
                <?= $view->e($alert['title'] ?? '') ?>
            </span>
        </div>
        <div class="detail-card-body">
            <table class="data-table">
                <tbody>
                    <tr><th scope="row" style="width:200px;"><?= $this->te('Anbieter') ?></th><td><?= $view->e($providerLabel[$alert['provider']] ?? ($alert['provider'] ?? '')) ?></td></tr>
                    <tr><th scope="row"><?= $this->te('Typ') ?></th><td><?= $view->e($typeLabel[$alert['alert_type'] ?? ''] ?? ($alert['alert_type'] ?? '–')) ?></td></tr>
                    <tr><th scope="row"><?= $this->te('Lokaler Status') ?></th><td><span class="status-pill"><?= $statusLabel[$st] ?? $view->e($st) ?></span></td></tr>
                    <tr><th scope="row"><?= $this->te('Status beim Anbieter') ?></th><td><?= $view->e($alert['provider_status'] ?? '–') ?></td></tr>
                    <tr><th scope="row"><?= $this->te('Gerät (Anbieter)') ?></th><td><?= $view->e($alert['endpoint_name'] ?? '–') ?></td></tr>
                    <tr>
                        <th scope="row"><?= $this->te('Zugeordnetes Asset') ?></th>
                        <td>
                            <?php if (!empty($alert['asset_id'])): ?>
                                <a href="/inventory/<?= (int)$alert['asset_id'] ?>" class="table-link"><?= $view->e($alert['asset_name'] ?? ('#' . $alert['asset_id'])) ?></a>
                            <?php else: ?>
                                <span class="status-pill status-pill--danger"><?= $this->te('Nicht zugeordnet') ?></span>
                            <?php endif; ?>
                        </td>
                    </tr>
                    <tr><th scope="row"><?= $this->te('IP-Adresse') ?></th><td><?= $view->e($alert['ip_address'] ?? '–') ?></td></tr>
                    <tr><th scope="row"><?= $this->te('MAC-Adresse') ?></th><td><?= $view->e($alert['mac_address'] ?? '–') ?></td></tr>
                    <tr><th scope="row"><?= $this->te('Agent-GUID') ?></th><td><code><?= $view->e($alert['agent_guid'] ?? '–') ?></code></td></tr>
                    <tr><th scope="row"><?= $this->te('Erkannt am') ?></th><td><?= $alert['detected_at'] ? $view->e(date('d.m.Y H:i', strtotime((string)$alert['detected_at']))) : '–' ?></td></tr>
                    <tr>
                        <th scope="row"><?= $this->t('MITRE ATT&CK') ?></th>
                        <td>
                            <?php if (empty($mitre)): ?>–<?php else: foreach ($mitre as $t): ?>
                                <span class="badge"><?= $view->e($t) ?></span>
                            <?php endforeach; endif; ?>
                        </td>
                    </tr>
                    <?php if (!empty($alert['assigned_to'])): ?>
                    <tr><th scope="row"><?= $this->te('Zuständig') ?></th><td><?= $view->e($alert['assigned_to_name'] ?? ('#' . (int)$alert['assigned_to'])) ?></td></tr>
                    <?php endif; ?>
                    <?php if (!empty($alert['auto_action'])): ?>
                    <tr>
                        <th scope="row"><?= $this->te('Automatisch behandelt') ?></th>
                        <td>
                            <?= $view->e($actionLabel[$alert['auto_action']] ?? (string)$alert['auto_action']) ?>
                            <?php if (!empty($alert['applied_rule_name'])): ?>
                                <?= $view->t('durch die Regel „{name}"', ['name' => $view->e((string)$alert['applied_rule_name'])]) ?>
                            <?php else: ?>
                                <?= $view->te('durch eine inzwischen gelöschte Regel') ?>
                            <?php endif; ?>
                        </td>
                    </tr>
                    <?php endif; ?>
                    <?php if (!empty($alert['ticket_id'])): ?>
                    <tr><th scope="row"><?= $this->te('Verknüpftes Ticket') ?></th><td><a href="/tickets/<?= (int)$alert['ticket_id'] ?>" class="table-link"><?= $this->te('Ticket #{nummer}', ['nummer' => (int)$alert['ticket_id']]) ?></a></td></tr>
                    <?php endif; ?>
                </tbody>
            </table>

            <?php if (!empty($alert['description'])): ?>
                <h4 style="margin-top:1rem;"><?= $this->te('Beschreibung') ?></h4>
                <p><?= nl2br($view->e($alert['description'])) ?></p>
            <?php endif; ?>
        </div>
    </div>

    <?php if ($canManage): ?>
    <div class="detail-card">
        <div class="detail-card-header"><span class="detail-card-title"><?= $this->te('Bearbeitung') ?></span></div>
        <div class="detail-card-body">
            <div style="display:flex; flex-wrap:wrap; gap:2rem;">

                <!-- Status -->
                <form method="post" action="/xdr/<?= (int)$alert['id'] ?>/status" style="min-width:240px;">
                    <input type="hidden" name="_csrf" value="<?= $view->e($view->csrf()) ?>">
                    <div class="form-group">
                        <label for="f-8f10-local_status"><?= $this->te('Status setzen') ?></label>
                        <select id="f-8f10-local_status" name="local_status" class="form-control form-control-sm">
                            <?php foreach ($statusLabel as $k => $lbl): ?>
                                <option value="<?= $k ?>" <?= $st === $k ? 'selected' : '' ?>><?= $lbl ?></option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <button type="submit" class="btn btn-primary btn-sm"><?= $this->te('Speichern') ?></button>
                </form>

                <!-- Asset-Zuordnung -->
                <form method="post" action="/xdr/<?= (int)$alert['id'] ?>/assign" style="min-width:320px;">
                    <input type="hidden" name="_csrf" value="<?= $view->e($view->csrf()) ?>">
                    <div class="form-group">
                        <label for="f-8f10-asset_id"><?= $this->te('Asset zuordnen') ?></label>
                        <select id="f-8f10-asset_id" name="asset_id" class="form-control form-control-sm">
                            <option value="0"><?= $this->te('— nicht zugeordnet —') ?></option>
                            <?php foreach ($assets as $opt): ?>
                                <option value="<?= (int)$opt['id'] ?>" <?= (int)($alert['asset_id'] ?? 0) === (int)$opt['id'] ? 'selected' : '' ?>>
                                    <?= $view->e($opt['label']) ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                        <small class="form-hint"><?= $this->te('Über die Agent-GUID gilt die Zuordnung für alle Warnungen dieses Geräts.') ?></small>
                    </div>
                    <button type="submit" class="btn btn-primary btn-sm"><?= $this->te('Zuordnen') ?></button>
                </form>

                <!-- Ticket -->
                <?php if ($ticketEnabled && empty($alert['ticket_id'])): ?>
                <form method="post" action="/xdr/<?= (int)$alert['id'] ?>/ticket" style="min-width:200px;">
                    <input type="hidden" name="_csrf" value="<?= $view->e($view->csrf()) ?>">
                    <div class="form-group">
                        <label><?= $this->te('Incident-Handling') ?></label>
                        <div><button type="submit" class="btn btn-default btn-sm"><i class="fas fa-ticket-alt"></i> <?= $this->te('Ticket erstellen') ?></button></div>
                    </div>
                </form>
                <?php endif; ?>

            </div>
        </div>
    </div>
    <?php endif; ?>

    <div class="detail-card">
        <div class="detail-card-header"><span class="detail-card-title"><?= $this->te('Rohdaten') ?></span></div>
        <div class="detail-card-body">
            <pre style="max-height:480px; overflow:auto; background:var(--color-bg-alt); border:1px solid var(--color-border); border-radius:.4rem; padding:1rem; font-size:.78rem;"><?= $view->e(json_encode($raw, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) ?></pre>
        </div>
    </div>
</div>