feat(firewall): add audited rule lifecycle management

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-08-03 22:35:45 -04:00
parent b06c18d38e
commit d5ca89e160
13 changed files with 457 additions and 43 deletions
@@ -220,6 +220,48 @@ class FirewallStoreTest extends TestCase
self::assertSame(FirewallRuleManager::ORIGIN_MANUAL, $logs[0]->getMetadata()['origin']);
}
#[TestDox('Manual rule lifecycle changes persist through disable, enable, extension, and deletion')]
public function testManualRuleLifecyclePersistence(): void
{
$manager = new FirewallRuleManager(
$this->store,
new FirewallRuleCache($this->store),
$this->createStub(EventDispatcherInterface::class)
);
$rule = $manager->createManualRule(
FirewallRuleScope::tenant('tenant-a'),
FirewallRuleObject::TYPE_IP,
FirewallRuleObject::ACTION_BLOCK,
'203.0.113.10',
'Repeated abuse',
'admin-a',
300
);
$manager->disableManual(
FirewallRuleScope::tenant('tenant-a'), $rule->getId(), 'Investigating', 'admin-a'
);
self::assertFalse($this->store->fetchRule($rule->getId())->isEnabled());
$manager->enableManual(
FirewallRuleScope::tenant('tenant-a'), $rule->getId(), 'Threat confirmed', 'admin-a'
);
self::assertTrue($this->store->fetchRule($rule->getId())->isEnabled());
$previousExpiry = $rule->getExpiresAt();
$manager->extendManual(
FirewallRuleScope::tenant('tenant-a'), $rule->getId(), 300, 'Continue monitoring', 'admin-a'
);
$stored = $this->store->fetchRule($rule->getId());
self::assertGreaterThan($previousExpiry, $stored->getExpiresAt());
self::assertSame('Continue monitoring', $stored->getMetadata()['extensions'][0]['reason']);
$manager->removeManual(
FirewallRuleScope::tenant('tenant-a'), $rule->getId(), 'Case closed', 'admin-a'
);
self::assertNull($this->store->fetchRule($rule->getId()));
}
#[TestDox('Event-backed firewall logs are inserted exactly once')]
public function testIdempotentLogPersistence(): void
{