Event Service - jastit00/IT-Sec-Projekt GitHub Wiki

Modul: Event Service

Author: Marcel Nicklaß

System Overview

The Event Service manages security events and provides the following core features:

  • Categorization by severity (Critical, Warning, Normal) with detailed descriptions
  • Filtering and searching through event data
  • Sorting by various criteria
  • IP address extraction and display

Architecture

System Architecture

Overview

The service follows a modern frontend-backend architecture:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    HTTP/REST    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Frontend      β”‚ ←───────────→   β”‚   Backend       β”‚
β”‚   (Angular)     β”‚                 β”‚   (Django)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Event Service β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Components    β”‚
β”‚   - All Events  β”‚
β”‚   - Critical    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Technology Stack

Frontend:

  • Angular & Angular Material Design
  • RxJS
  • TypeScript
  • CSS

Backend:

  • Django REST Framework
  • PostgreSQL
  • RESTful API Design

Communication:

  • HTTP/REST API
  • JSON data format

Event Service

Class Description

@Injectable({
  providedIn: 'root'
})
export class EventService {
  private defaultService = inject(DefaultService);
  private httpClient = inject(HttpClient);
  private updateService = inject(ChartUpdateService);
  
  events: SecurityEvent[] = [];
  loading = false;
}

Main Responsibilities

1. Data Management

  • Loading Events: loadEventsFromBackend()
  • Caching: In-memory event storage
  • State Management: Handling loading states and errors

2. Data Processing

Event Mapping:

private mapBackendEventsToSecurityEvents(backendEvents: Events[]): SecurityEvent[] {
  return backendEvents.map(backendEvent => ({
    id: backendEvent.id ?? Math.floor(Math.random() * 10000),
    date: this.formatDate(new Date(backendEvent.timestamp)),
    event: this.getDisplayEventType(backendEvent),
    status: this.mapSeverityToStatus(backendEvent.severity),
    ips: this.extractIPs(backendEvent),
    description: this.generateDescription(backendEvent)
  }));
}

IP Extraction:

private extractIPs(event: Events): string[] {
  const ips: string[] = [];
  
  if (event.source_ips && Array.isArray(event.source_ips)) {
    event.source_ips.forEach(ip => {
      if (ip && typeof ip === 'string' && ip.trim() !== '') {
        ips.push(ip.trim());
      }
    });
  }
  
  return ips;
}

3. Description Generation

private generateDescription(event: Events): string {
  const eventType = this.getDisplayEventType(event).toLowerCase();
  
  switch (eventType) {
    case 'network packet':
      const packetInfo = [];
      if (event.protocol) packetInfo.push(`Protocol: ${event.protocol}`);
      if (event.count) packetInfo.push(`Count: ${event.count}`);
      return packetInfo.join(' | ');
      
    case 'login':
      const loginInfo = [];
      if (event.username) loginInfo.push(`User: ${event.username}`);
      if (event.result) loginInfo.push(`Status: ${event.result}`);
      return loginInfo.join(' | ');
      
    // More event types...
  }
}

Public API

Main Methods

getAllEvents(): SecurityEvent[]

  • Returns all loaded events
  • Used in the All Events component

getCriticalEvents(): SecurityEvent[]

  • Filters only critical events
  • Used in the Critical Events component

refreshEvents(): Observable<SecurityEvent[]>

  • Reloads events from the backend
  • Triggered by chart updates

Frontend Components

All Events Component

Overview

Displays a full list of all security events with advanced filtering and search features.

Core Features

1. Search Function

private matchesSearchTerm(event: SecurityEvent): boolean {
  if (!this._searchTerm.trim()) return true;
  
  const search = this._searchTerm.toLowerCase();
  return event.date.toLowerCase().includes(search) ||
         event.event.toLowerCase().includes(search) ||
         event.status.toLowerCase().includes(search) ||
         event.description.toLowerCase().includes(search) ||
         event.ips?.some(ip => ip.toLowerCase().includes(search));
}

2. Advanced Filtering

<mat-form-field appearance="outline" class="sort-field">
  <mat-label>Sort by</mat-label>
  <mat-select [(ngModel)]="sortBy" (selectionChange)="sortEvents()">
    <mat-option value="">No sorting</mat-option>
    <mat-option value="normal">Normal Events</mat-option>
    <mat-option value="warning">Warning Events</mat-option>
    <mat-option value="critical">Critical Events</mat-option>
    <mat-option value="login">Login Events</mat-option>
    <mat-option value="logout">Logout Events</mat-option>
  </mat-select>
</mat-form-field>

3. Sorting

sortEvents() {
  this.filteredEvents.sort((a, b) => {
    let comparison = 0;
    
    const dateA = new Date(a.date);
    const dateB = new Date(b.date);
    comparison = dateA.getTime() - dateB.getTime();
    
    if (comparison === 0) {
      comparison = a.event.toLowerCase().localeCompare(b.event.toLowerCase());
    }
    
    return this.sortDirection === 'desc' ? -comparison : comparison;
  });
}

Critical Events Component

Overview

Focuses exclusively on critical security events.

Specialization

1. Critical Events Filter

constructor(private eventService: EventService) {
  this.events = this.eventService.getCriticalEvents();
  this.filteredEvents = [...this.events];
}

2. Simplified Sorting

sortEvents() {
  const criticalEvents = this.eventService.getCriticalEvents();
  
  if (!this.searchTerm.trim()) {
    this.filteredEvents = [...criticalEvents];
  } else {
    this.filteredEvents = criticalEvents.filter(event => 
      this.matchesSearchTerm(event)
    );
  }
  
  if (this.sortDirection && this.filteredEvents.length > 0) {
    this.filteredEvents.sort((a, b) => {
      let comparison = new Date(a.date).getTime() - new Date(b.date).getTime();
      if (comparison === 0) {
        comparison = a.event.toLowerCase().localeCompare(b.event.toLowerCase());
      }
      if (comparison === 0) {
        comparison = a.description.toLowerCase().localeCompare(b.description.toLowerCase());
      }
      return this.sortDirection === 'desc' ? -comparison : comparison;
    });
  }
}

API Integration

HTTP Client Configuration

Base URL Setup

export class EventService {
  private apiBaseUrl = 'http://localhost:8000/api';
  
  getUnifiedEvents(): Observable<Events[]> {
    return this.httpClient.get<Events[]>(`${this.apiBaseUrl}/logfiles/unified-event-log/`);
  }
}

Request-Response Cycle

1. Request

loadEventsFromBackend(): Observable<SecurityEvent[]> {
  this.loading = true;
  
  return this.getUnifiedEvents().pipe(
    map(backendEvents => this.mapBackendEventsToSecurityEvents(backendEvents)),
    tap(mappedEvents => this.events = mappedEvents),
    catchError(this.handleError),
    finalize(() => this.loading = false)
  );
}

2. Error Handling

private handleError = (error: any): Observable<SecurityEvent[]> => {
  console.error('API Error:', error);
  
  this.events = [];
  
  if (error.status === 404) {
    console.warn('Event endpoint not found');
  } else if (error.status === 500) {
    console.error('Server error occurred');
  }
  
  return of([]);
};

Data Model Mapping

Backend Model (Events)

interface Events {
  id?: number;
  timestamp: string;
  event_type: string;
  severity: string;
  source_ips?: string[];
  src_ip_address?: string;
  dst_ip_address?: string;
  protocol?: string;
  username?: string;
  result?: string;
  incident_type?: string;
  reason?: string;
  details?: any;
}

Frontend Model (SecurityEvent)

export interface SecurityEvent {
  id: number;
  date: string;
  event: string;
  status: 'Critical' | 'Warning' | 'Normal';
  ips: string[];
  description: string;
}

Auto Updates

constructor() {
  this.updateSubscription = this.updateService.updateChart$.subscribe(() => {
    this.refreshEvents().subscribe();
  });
}

refreshEvents(): Observable<SecurityEvent[]> {
  return this.loadEventsFromBackend();
}

Security

Security Measures

Input Validation

1. Character Filtering

export class AllEventsComponent {
  private readonly FORBIDDEN_CHARS = /[<>"';[\]{}()\\\/]/g;

  set searchTerm(value: string) {
    this._searchTerm = value ? value.replace(this.FORBIDDEN_CHARS, '').trim() : '';
  }
}

2. Keyboard Event Filtering

onKeyPress(event: KeyboardEvent) {
  const forbiddenChars = '<>"\;[]{}()/';
  if (forbiddenChars.includes(event.key)) {
    event.preventDefault();
    console.log("Blocked forbidden character:", event.key);
  }
}

3. Template Security

<!-- Angular auto-escapes input -->
<input matInput 
       [(ngModel)]="searchTerm"
       (keypress)="onKeyPress($event)"
       maxlength="100"
       autocomplete="off"
       spellcheck="false">

XSS Protection

1. Template Escaping

<!-- Safe - Angular auto escapes interpolated content -->
<td>{{ event.description }}</td>
<td>{{ event.event }}</td>

2. Input Sanitization

// Sanitization on user input
private sanitizeInput(input: string): string {
  return input
    .replace(this.FORBIDDEN_CHARS, '')
    .trim()
    .substring(0, 100); // Limit length
}
⚠️ **GitHub.com Fallback** ⚠️