Enable Discovery debug logging for production troubleshooting

- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -0,0 +1,233 @@
<?php
declare(strict_types=1);
namespace Tests\Framework\Security;
use App\Framework\Auth\Auth;
use App\Framework\Http\MiddlewareContext;
use App\Framework\Http\Middlewares\AuthMiddleware;
use App\Framework\Http\Next;
use App\Framework\Http\Request;
use App\Framework\Http\RequestStateManager;
use App\Framework\Http\Session\SessionInterface;
use PHPUnit\Framework\TestCase;
/**
* Critical Security Tests for Authentication
* Tests gegen OWASP A07:2021 Identification and Authentication Failures
*/
final class AuthenticationSecurityTest extends TestCase
{
private SessionInterface $session;
private Auth $auth;
private AuthMiddleware $middleware;
private RequestStateManager $stateManager;
protected function setUp(): void
{
$this->session = $this->createMock(SessionInterface::class);
$this->auth = $this->createMock(Auth::class);
$this->middleware = new AuthMiddleware($this->auth);
$this->stateManager = $this->createMock(RequestStateManager::class);
}
/**
* Test: Nicht-authentifizierte Benutzer werden blockiert
* OWASP A07:2021 Identification and Authentication Failures
*/
public function test_blocks_unauthenticated_access(): void
{
// Arrange: Benutzer nicht authentifiziert
$this->auth->method('isAuthenticated')->willReturn(false);
$request = $this->createMock(Request::class);
$context = new MiddlewareContext($request);
$next = $this->createMock(Next::class);
$next->expects($this->never())->method('__invoke');
// Act & Assert: Exception erwartet
$this->expectException(\App\Framework\Http\Exception\HttpException::class);
$this->middleware->__invoke($context, $next, $this->stateManager);
}
/**
* Test: Authentifizierte Benutzer werden durchgelassen
*/
public function test_allows_authenticated_access(): void
{
// Arrange: Benutzer authentifiziert
$this->auth->method('isAuthenticated')->willReturn(true);
$request = $this->createMock(Request::class);
$context = new MiddlewareContext($request);
$next = $this->createMock(Next::class);
$next->expects($this->once())->method('__invoke')->willReturn($context);
// Act
$result = $this->middleware->__invoke($context, $next, $this->stateManager);
// Assert
$this->assertSame($context, $result);
}
/**
* Test: Session Hijacking Schutz
* Validiert Session-Fingerprinting
*/
public function test_session_fingerprint_validation(): void
{
// Arrange: Authentifiziert aber Session-Fingerprint geändert
$this->auth->method('isAuthenticated')->willReturn(true);
$this->auth->method('validateSessionFingerprint')->willReturn(false);
$request = $this->createMock(Request::class);
$context = new MiddlewareContext($request);
$next = $this->createMock(Next::class);
// Act & Assert: Session Hijacking erkannt
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Session fingerprint validation failed');
$this->middleware->__invoke($context, $next, $this->stateManager);
}
/**
* Test: Concurrent Login Detection
* Erkennt verdächtige gleichzeitige Logins
*/
public function test_concurrent_login_detection(): void
{
// Arrange: Benutzer von verschiedenen IPs eingeloggt
$this->auth->method('isAuthenticated')->willReturn(true);
$this->auth->method('validateSessionFingerprint')->willReturn(true);
$this->auth->method('detectConcurrentSessions')->willReturn(true);
$request = $this->createMock(Request::class);
$context = new MiddlewareContext($request);
$next = $this->createMock(Next::class);
// Act & Assert: Concurrent Session erkannt
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Concurrent session detected');
$this->middleware->__invoke($context, $next, $this->stateManager);
}
/**
* Test: Session Timeout Validierung
*/
public function test_session_timeout_validation(): void
{
// Arrange: Session abgelaufen
$this->auth->method('isAuthenticated')->willReturn(true);
$this->auth->method('isSessionExpired')->willReturn(true);
$request = $this->createMock(Request::class);
$context = new MiddlewareContext($request);
$next = $this->createMock(Next::class);
// Act & Assert: Session Timeout
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Session expired');
$this->middleware->__invoke($context, $next, $this->stateManager);
}
/**
* Test: Rate Limiting für Authentication Failures
* Verhindert Brute Force Attacks
*/
public function test_authentication_rate_limiting(): void
{
// Arrange: Zu viele fehlgeschlagene Login-Versuche
$this->auth->method('isAuthenticated')->willReturn(false);
$this->auth->method('isRateLimited')->willReturn(true);
$request = $this->createMock(Request::class);
$context = new MiddlewareContext($request);
$next = $this->createMock(Next::class);
// Act & Assert: Rate Limit erreicht
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Authentication rate limit exceeded');
$this->middleware->__invoke($context, $next, $this->stateManager);
}
/**
* Test: IP Whitelist Validation
* Admin-Bereiche nur von bestimmten IPs
*/
public function test_ip_whitelist_validation(): void
{
// Arrange: IP nicht in Whitelist
$this->auth->method('isAuthenticated')->willReturn(true);
$this->auth->method('isIpWhitelisted')->willReturn(false);
$request = $this->createRequestWithIp('192.168.1.100');
$context = new MiddlewareContext($request);
$next = $this->createMock(Next::class);
// Act & Assert: IP nicht erlaubt
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Access from this IP address is not allowed');
$this->middleware->__invoke($context, $next, $this->stateManager);
}
/**
* Test: Account Lockout nach fehlgeschlagenen Versuchen
*/
public function test_account_lockout_after_failed_attempts(): void
{
// Arrange: Account gesperrt nach zu vielen Versuchen
$this->auth->method('isAuthenticated')->willReturn(false);
$this->auth->method('isAccountLocked')->willReturn(true);
$request = $this->createMock(Request::class);
$context = new MiddlewareContext($request);
$next = $this->createMock(Next::class);
// Act & Assert: Account gesperrt
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Account is locked due to too many failed attempts');
$this->middleware->__invoke($context, $next, $this->stateManager);
}
/**
* Test: Two-Factor Authentication Validation
*/
public function test_two_factor_authentication_required(): void
{
// Arrange: 2FA erforderlich aber nicht bereitgestellt
$this->auth->method('isAuthenticated')->willReturn(true);
$this->auth->method('requires2FA')->willReturn(true);
$this->auth->method('is2FAValid')->willReturn(false);
$request = $this->createMock(Request::class);
$context = new MiddlewareContext($request);
$next = $this->createMock(Next::class);
// Act & Assert: 2FA erforderlich
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Two-factor authentication required');
$this->middleware->__invoke($context, $next, $this->stateManager);
}
// Helper Methods
private function createRequestWithIp(string $ip): Request
{
$request = $this->createMock(Request::class);
$request->method('getClientIp')->willReturn($ip);
return $request;
}
}