feat(firewall): add safeguarded rule creation

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-08-03 22:27:20 -04:00
parent 6700ff145d
commit b06c18d38e
10 changed files with 374 additions and 0 deletions
@@ -7,6 +7,7 @@ namespace KTXT\Unit\Controllers;
use KTXC\Context\IdentityContextInterface;
use KTXC\Context\TenantContextInterface;
use KTXC\Controllers\FirewallController;
use KTXC\Http\Request\Request;
use KTXC\Service\FirewallRuleCache;
use KTXC\Service\FirewallRuleManager;
use KTXC\Service\FirewallStatusService;
@@ -89,6 +90,39 @@ final class FirewallControllerTest extends TestCase
self::assertSame(400, $this->controller->systemMetrics(since: 'not-a-date')->getStatusCode());
}
#[TestDox('Current-IP blocks return a structured confirmation conflict')]
public function testCurrentIpConflict(): void
{
$this->store->expects(self::never())->method('depositRule');
$response = $this->controller->createTenantRule(
new Request(server: ['REMOTE_ADDR' => '203.0.113.10']),
'ip',
'block',
'203.0.113.10',
'Suspected abuse'
);
$data = json_decode($response->getContent(), true, flags: JSON_THROW_ON_ERROR);
self::assertSame(409, $response->getStatusCode());
self::assertSame('current_ip_confirmation_required', $data['error']['code']);
}
#[TestDox('Invalid manual rules return a stable validation response')]
public function testMutationValidation(): void
{
$response = $this->controller->createSystemRule(
new Request(server: ['REMOTE_ADDR' => '203.0.113.10']),
'device',
'allow',
'device-123',
'Trusted device'
);
$data = json_decode($response->getContent(), true, flags: JSON_THROW_ON_ERROR);
self::assertSame(400, $response->getStatusCode());
self::assertSame('invalid_firewall_rule', $data['error']['code']);
}
#[TestDox('Every rule endpoint declares its scope-specific read permission')]
public function testRoutePermissions(): void
{
@@ -104,6 +138,8 @@ final class FirewallControllerTest extends TestCase
'tenantConfiguration' => TenantFirewallStatusService::PERMISSION_SETTINGS_READ,
'systemMetrics' => SystemFirewallLogService::PERMISSION_READ,
'maintenanceStatus' => SystemFirewallStatusService::PERMISSION_MAINTENANCE_READ,
'createTenantRule' => TenantFirewallRuleService::PERMISSION_MANAGE,
'createSystemRule' => SystemFirewallRuleService::PERMISSION_MANAGE,
];
foreach ($expected as $method => $permission) {