feat(firewall): complete operational reliability phase

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-07-30 23:39:37 -04:00
parent 90d847ffae
commit 4ee91a7918
15 changed files with 574 additions and 22 deletions
+52 -3
View File
@@ -394,7 +394,7 @@ class FirewallServiceTest extends TestCase
->willReturn(5);
$this->store->expects($this->once())
->method('claimBruteForce')
->with('tenant-event', '203.0.113.10', 3600)
->with('tenant-event', '203.0.113.10', 300)
->willReturn(true);
$this->store->expects($this->once())
->method('findExactIpRule')
@@ -407,9 +407,14 @@ class FirewallServiceTest extends TestCase
$this->store->expects($this->once())
->method('depositRule')
->with(self::callback(static function (FirewallRuleObject $rule): bool {
$metadata = $rule->getMetadata();
return $rule->getScope() === FirewallRuleObject::SCOPE_TENANT
&& $rule->getTenantId() === 'tenant-event'
&& $rule->getExpiresAt() !== null;
&& $rule->getExpiresAt() !== null
&& $metadata['failureThreshold'] === 5
&& $metadata['failureWindowSeconds'] === 300
&& $metadata['lastFailureCount'] === 5
&& $metadata['blockDurationSeconds'] === 3600;
}))
->willReturnArgument(0);
@@ -445,7 +450,7 @@ class FirewallServiceTest extends TestCase
->willReturn(5);
$this->store->expects($this->once())
->method('claimBruteForce')
->with('tenant-a', '203.0.113.10', 3600)
->with('tenant-a', '203.0.113.10', 300)
->willReturn(false);
$this->store->expects($this->never())->method('depositRule');
$this->events->expects($this->never())->method('dispatch');
@@ -500,6 +505,50 @@ class FirewallServiceTest extends TestCase
self::assertSame($eventId, $event->getEventId());
}
#[TestDox('Cleanup records successful maintenance counts')]
public function testCleanupStatus(): void
{
$this->store->method('cleanupExpiredRules')->willReturn(2);
$this->store->method('cleanupOldLogs')->with(30)->willReturn(3);
$this->store->method('cleanupExpiredBruteForceClaims')->willReturn(4);
$this->store->expects(self::once())
->method('recordMaintenanceStatus')
->with(
self::isInstanceOf(\DateTimeImmutable::class),
self::isInstanceOf(\DateTimeImmutable::class),
'success',
[
'expiredRules' => 2,
'oldLogs' => 3,
'expiredBruteForceClaims' => 4,
]
);
self::assertSame([
'expiredRules' => 2,
'oldLogs' => 3,
'expiredBruteForceClaims' => 4,
], $this->service->cleanup());
}
#[TestDox('Cleanup failures are recorded and rethrown')]
public function testCleanupFailureStatus(): void
{
$this->store->method('cleanupExpiredRules')->willThrowException(new \RuntimeException('cleanup failed'));
$this->store->expects(self::once())
->method('recordMaintenanceStatus')
->with(
self::isInstanceOf(\DateTimeImmutable::class),
self::isInstanceOf(\DateTimeImmutable::class),
'failed',
[],
'cleanup failed'
);
$this->expectExceptionMessage('cleanup failed');
$this->service->cleanup();
}
private function rule(
string $id,
string $scope,