evebox 0.13.0

A web based Suricata event manager
Documentation
<loading-spinner [loading]="loading"></loading-spinner>

<div [@loadingState]="!rows || (!silentRefresh && loading) ? 'true' : 'false'">

  <!-- Fixes the button/search bar in place, and hides the page as it scrolls
       underneath. -->

  <div style="position: relative;">

    <div class="evebox-fixed">

      <br/>

      <div class="row" style="margin-right: 15px;">
        <div class="col-md">
          <button type="button" class="btn btn-secondary mr-2" (click)="refresh()">
            Refresh
          </button>
          <button *ngIf="rows && rows.length > 0 && !allSelected()"
                  type="button"
                  class="btn btn-secondary mr-2"
                  (click)="selectAllRows()">Select All
          </button>
          <button *ngIf="rows && rows.length > 0 && allSelected()" type="button"
                  class="btn btn-secondary mr-2"
                  (click)="deselectAllRows()">Deselect All
          </button>
          <button *ngIf="rows && rows.length > 0 && getSelectedCount() > 0"
                  type="button"
                  class="btn btn-secondary mr-2"
                  (click)="archiveSelected()">Archive
          </button>
          <button *ngIf="rows && rows.length > 0 && getSelectedCount() > 0"
                  type="button"
                  class="btn btn-secondary"
                  (click)="escalateSelected()">Escalate
          </button>
        </div>
        <div class="col-md">
          <form (submit)="submitFilter()">
            <div class="input-group">
              <input id="filter-input"
                     type="text"
                     class="form-control"
                     placeholder="Filter..."
                     [(ngModel)]="queryString"
                     name="queryString"/>
              <div class="input-group-append">
                <button class="btn btn-secondary" type="submit">Apply
                </button>
                <button type="button"
                        class="btn btn-secondary"
                        (click)="clearFilter()">Clear
                </button>
              </div>
            </div>
          </form>
        </div>
      </div>

      <br/>

    </div>

  </div>

</div>

<!-- This hidden div acts as a spacer as it should be the same height
     as the fixed row above. -->
<div style="visibility: hidden;">
  <div class="row">
    <div class="col-md">
      <button type="button" class="btn btn-secondary btn-block">Spacer</button>
    </div>
    <div class="col-md">
      <button type="button" class="btn btn-secondary btn-block">Spacer</button>
    </div>
  </div>
  <br>
</div>

<br/>

<div *ngIf="!loading && rows && rows.length == 0" style="text-align: center;">
  <hr/>
  No events found.
  <hr/>
</div>

<div *ngIf="(!rows || rows.length == 0) && loading" style="text-align: center;">
  <hr/>
  Loading.
  <hr/>
</div>

<div class="row align-items-center" *ngIf="rows && rows.length > 0">
  <div class="col-sm">
    Showing {{offset + 1}}-{{offset + rows.length}} of {{allRows.length}}.
  </div>
  <div class="col-sm">
    <div class="btn-group float-right" role="group">
      <button [disabled]="offset == 0"
              type="button"
              class="btn btn-secondary" (click)="newest()">Newest
      </button>
      <button [disabled]="offset == 0"
              type="button"
              class="btn btn-secondary" (click)="newer()">Newer
      </button>
      <button
          [disabled]="rows.length == allRows.length || offset + windowSize >= allRows.length"
          type="button"
          class="btn btn-secondary" (click)="older()">Older
      </button>
      <button
          [disabled]="rows.length == allRows.length || offset + windowSize >= allRows.length"
          type="button"
          class="btn btn-secondary" (click)="oldest()">Oldest
      </button>
      <button type="button"
              class="btn btn-secondary dropdown-toggle"
              data-toggle="dropdown"
              aria-haspopup="true"
              aria-expanded="false">
      </button>
      <div class="dropdown-menu dropdown-menu-right">
        <button class="dropdown-item" href="#" (click)="showAll()">View
          All
        </button>
      </div>
    </div>
  </div>
</div>

<br/>

<div *ngIf="rows && rows.length > 0">
  <div class="table-responsive" style="overflow: inherit !important;">

    <table class="table table-sm evebox-event-table"
           style="margin-bottom: 0px;"
           eveboxKeyTable [rows]="rows" [(activeRow)]="activeRow">

      <thead>
      <tr>
        <th></th>
        <th></th>
        <th></th>
        <th style="white-space: nowrap;"><a (click)="onSort('count')">#
          <i *ngIf="sortBy == 'count' && sortOrder == 'desc'"
             class="fa fa-caret-up"></i>
          <i *ngIf="sortBy == 'count' && sortOrder == 'asc'"
             class="fa fa-caret-down"></i>
        </a></th>
        <th><a (click)="onSort('timestamp')">
          Timestamp
          <i *ngIf="sortBy == 'timestamp' && sortOrder == 'desc'"
             class="fa fa-caret-up"></i>
          <i *ngIf="sortBy == 'timestamp' && sortOrder == 'asc'"
             class="fa fa-caret-down"></i>
        </a></th>
        <th>
          <a (click)="onSort('source')">Source
            <span *ngIf="sortBy == 'source' && sortOrder == 'desc'"><i
                class="fa fa-caret-up"></i></span>
            <span *ngIf="sortBy == 'source' && sortOrder == 'asc'"><i
                class="fa fa-caret-down"></i></span>
          </a>/
          <a (click)="onSort('dest')">Dest
            <span *ngIf="sortBy == 'dest' && sortOrder == 'desc'"><i
                class="fa fa-caret-up"></i></span>
            <span *ngIf="sortBy == 'dest' && sortOrder == 'asc'"><i
                class="fa fa-caret-down"></i></span>
          </a>
        </th>
        <th width="50%"><a (click)="onSort('signature')">Signature <i
            *ngIf="sortBy == 'signature' && sortOrder == 'desc'"
            class="fa fa-caret-up"> </i>
          <i *ngIf="sortBy == 'signature' && sortOrder == 'asc'"
             class="fa fa-caret-down"> </i>
        </a></th>
      </tr>
      </thead>

      <tbody>
      <tr *ngFor="let row of rows; let i = index" id="row-{{i}}"
          [ngClass]="row.event.event | eventSeverityToBootstrapClass:'evebox-bg-'"
          (click)="rowClicked(row)" class="align-items-center">
        <td style="width: 1% !important;">
          <i *ngIf="i == activeRow" class="fa fa-chevron-right"
             aria-hidden="true"></i>
        </td>
        <td class="clearfix" style="width: 1% !important;">
          <input type="checkbox" [(ngModel)]="row.selected"
                 (click)="$event.stopPropagation()">
        </td>
        <td (click)="$event.stopPropagation(); toggleEscalatedState(row)"
            style="width: 1% !important;">
          <i *ngIf="row.event.escalatedCount == 0"
             class="fa fa-star-o"></i>
          <i *ngIf="row.event.escalatedCount == row.event.count"
             class="fa fa-star"></i>
          <i *ngIf="row.event.escalatedCount > 0 &&  row.event.escalatedCount != row.event.count"
             class="fa fa-star-half-o"></i>
        </td>
        <td style="width: 1% !important;">{{row.event.count}}</td>
        <td class="text-nowrap" style="width: 1%;">
          {{row.date | eveboxFormatTimestamp}}
          <br/>
          <evebox-duration style="color:gray"
                           [timestamp]="row.event.maxTs"></evebox-duration>
        </td>
        <td class="text-nowrap" style="width: 1% !important">
          <label>S:</label>
          {{row.event.event._source.src_ip | eveboxFormatIpAddress}}
          <br/>
          <label>D:</label>
          {{row.event.event._source.dest_ip | eveboxFormatIpAddress}}
        </td>
        <td>
          <div *ngIf="!isArchived(row)" class="btn-group float-right"
               (click)="$event.stopPropagation();">
            <button type="button"
                    class="btn btn-secondary"
                    (click)="archiveAlertGroup(row)">
              Archive
            </button>
            <button type="button" class="btn btn-secondary"
                    title="Escalate and Archive"
                    (click)="escalateAndArchiveEvent(row);">
              <!-- This is supposed to be a star with an archive box overlaid,
                 the idea behing to escalate and archive the event. -->
              <i class="fa fa-star-o fa-lg"></i>
              <i class="fa fa-archive"
                 style="position: absolute; left: 50%; top: 40%"></i>
            </button>
            <button type="button"
                    class="btn btn-secondary dropdown-toggle"
                    data-toggle="dropdown" aria-haspopup="true"
                    aria-expanded="false"></button>
            <div class="dropdown-menu dropdown-menu-right">
              <a class="dropdown-item" href="javascript:void(0);"
                 (click)="selectBySignatureId(row)">
                Select all with SID: {{row.event.event._source.alert.signature_id}}
              </a>
              <a class="dropdown-item" href="javascript:void(0);"
                 (click)="filterBySignatureId(row)">
                Filter on SID: {{row.event.event._source.alert.signature_id}}</a>
              <a class="dropdown-item"
                 [routerLink]="['/reports/ip', {ip: row.event.event._source.src_ip}]">
                Source IP report for {{row.event.event._source.src_ip}}
              </a>
              <a class="dropdown-item"
                 [routerLink]="['/reports/ip', {ip: row.event.event._source.dest_ip}]">
                Destination IP report for {{row.event.event._source.dest_ip}}
              </a>
            </div>
          </div>

          <span *ngIf="row.event.event._source.alert.action != 'allowed'"
                class="badge badge-warning">{{row.event.event._source.alert.action
          | uppercase}}</span>
          <span
              [innerHTML]="row.event.event | eveboxEventDescriptionPrinter"></span>
          <span class="badge badge-secondary mx-2"
                *ngIf="row.event.event._source.app_proto && row.event.event._source.app_proto != 'failed'">
            {{row.event.event._source.app_proto}}
          </span>
        </td>
      </tr>
      </tbody>

    </table>

  </div>

</div>

<br/>