Files
michaelschiemer/src/Framework/Logging/ValueObjects/SecurityContext.php

245 lines
7.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\Logging\ValueObjects;
use App\Framework\Exception\SecurityLogLevel;
/**
* Security Context Value Object für strukturiertes Security-Event-Logging
*
* Kapselt alle Security-relevanten Informationen für OWASP-konforme Logs.
* Nutzt Framework's SecurityLogLevel aus Exception-Modul.
*
* OWASP Logging Cheat Sheet:
* https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html
*/
final readonly class SecurityContext
{
/**
* @param string $eventId OWASP Event Identifier (z.B. "AUTHN_login_failure")
* @param SecurityLogLevel $level Security-spezifisches Log Level
* @param string $description Human-readable Event-Beschreibung
* @param string|null $category Event-Kategorie (z.B. "authentication", "authorization")
* @param bool $requiresAlert Ob Event ein Security-Alert triggern soll
* @param string|null $userId Betroffene User-ID (falls zutreffend)
* @param string|null $username Betroffener Username (falls zutreffend)
* @param string|null $sourceIp Source IP-Adresse
* @param string|null $userAgent User-Agent String
* @param array<string, mixed> $eventData Zusätzliche Event-spezifische Daten
*/
public function __construct(
public string $eventId,
public SecurityLogLevel $level,
public string $description,
public ?string $category = null,
public bool $requiresAlert = false,
public ?string $userId = null,
public ?string $username = null,
public ?string $sourceIp = null,
public ?string $userAgent = null,
public array $eventData = []
) {
}
/**
* Factory: Erstellt SecurityContext für Authentication-Events
*/
public static function forAuthentication(
string $eventId,
string $description,
SecurityLogLevel $level = SecurityLogLevel::WARN,
bool $requiresAlert = false,
array $eventData = []
): self {
return new self(
eventId: $eventId,
level: $level,
description: $description,
category: 'authentication',
requiresAlert: $requiresAlert,
eventData: $eventData
);
}
/**
* Factory: Erstellt SecurityContext für Authorization-Events
*/
public static function forAuthorization(
string $eventId,
string $description,
SecurityLogLevel $level = SecurityLogLevel::WARN,
bool $requiresAlert = false,
array $eventData = []
): self {
return new self(
eventId: $eventId,
level: $level,
description: $description,
category: 'authorization',
requiresAlert: $requiresAlert,
eventData: $eventData
);
}
/**
* Factory: Erstellt SecurityContext für Input-Validation-Events
*/
public static function forInputValidation(
string $eventId,
string $description,
SecurityLogLevel $level = SecurityLogLevel::WARN,
bool $requiresAlert = false,
array $eventData = []
): self {
return new self(
eventId: $eventId,
level: $level,
description: $description,
category: 'input_validation',
requiresAlert: $requiresAlert,
eventData: $eventData
);
}
/**
* Factory: Erstellt SecurityContext für Session-Events
*/
public static function forSession(
string $eventId,
string $description,
SecurityLogLevel $level = SecurityLogLevel::INFO,
bool $requiresAlert = false,
array $eventData = []
): self {
return new self(
eventId: $eventId,
level: $level,
description: $description,
category: 'session',
requiresAlert: $requiresAlert,
eventData: $eventData
);
}
/**
* Factory: Erstellt SecurityContext für Intrusion-Detection-Events
*/
public static function forIntrusion(
string $eventId,
string $description,
SecurityLogLevel $level = SecurityLogLevel::FATAL,
bool $requiresAlert = true,
array $eventData = []
): self {
return new self(
eventId: $eventId,
level: $level,
description: $description,
category: 'intrusion_detection',
requiresAlert: $requiresAlert,
eventData: $eventData
);
}
/**
* Setzt User-Informationen
*/
public function withUser(?string $userId, ?string $username = null): self
{
return new self(
eventId: $this->eventId,
level: $this->level,
description: $this->description,
category: $this->category,
requiresAlert: $this->requiresAlert,
userId: $userId,
username: $username,
sourceIp: $this->sourceIp,
userAgent: $this->userAgent,
eventData: $this->eventData
);
}
/**
* Setzt Request-Informationen
*/
public function withRequestInfo(?string $sourceIp, ?string $userAgent = null): self
{
return new self(
eventId: $this->eventId,
level: $this->level,
description: $this->description,
category: $this->category,
requiresAlert: $this->requiresAlert,
userId: $this->userId,
username: $this->username,
sourceIp: $sourceIp,
userAgent: $userAgent,
eventData: $this->eventData
);
}
/**
* Fügt Event-Daten hinzu
*/
public function withEventData(array $eventData): self
{
return new self(
eventId: $this->eventId,
level: $this->level,
description: $this->description,
category: $this->category,
requiresAlert: $this->requiresAlert,
userId: $this->userId,
username: $this->username,
sourceIp: $this->sourceIp,
userAgent: $this->userAgent,
eventData: array_merge($this->eventData, $eventData)
);
}
/**
* Konvertiert zu Array für Serialisierung
*/
public function toArray(): array
{
$result = [
'event_id' => $this->eventId,
'level' => $this->level->value,
'description' => $this->description,
];
if ($this->category !== null) {
$result['category'] = $this->category;
}
if ($this->requiresAlert) {
$result['requires_alert'] = true;
}
if ($this->userId !== null) {
$result['user_id'] = $this->userId;
}
if ($this->username !== null) {
$result['username'] = $this->username;
}
if ($this->sourceIp !== null) {
$result['source_ip'] = $this->sourceIp;
}
if ($this->userAgent !== null) {
$result['user_agent'] = $this->userAgent;
}
if (!empty($this->eventData)) {
$result['event_data'] = $this->eventData;
}
return $result;
}
}