feat(firewall): add tenant and system rule scopes

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-07-30 21:38:19 -04:00
parent b8afd75b77
commit 63d91ca7fa
5 changed files with 352 additions and 37 deletions
+69 -7
View File
@@ -29,14 +29,19 @@ class FirewallStore
*/
public function listRules(string $tenantId, bool $activeOnly = true): array
{
$filter = ['tenantId' => $tenantId];
$filter = [
'tenantId' => $tenantId,
'scope' => FirewallRuleObject::SCOPE_TENANT,
];
if ($activeOnly) {
$filter['enabled'] = true;
$filter['$or'] = [
$filter['$and'] = [[
'$or' => [
['expiresAt' => null],
['expiresAt' => ['$gt' => (new \DateTimeImmutable())->format(\DateTimeInterface::ATOM)]]
];
],
]];
}
$cursor = $this->dataStore->selectCollection(self::RULES_COLLECTION)->find($filter);
@@ -50,6 +55,43 @@ class FirewallStore
return $list;
}
/**
* List active system-wide rules and active rules owned by a tenant.
*/
public function listApplicableRules(string $tenantId): array
{
$now = (new \DateTimeImmutable())->format(\DateTimeInterface::ATOM);
$filter = [
'enabled' => true,
'$and' => [
[
'$or' => [
['scope' => FirewallRuleObject::SCOPE_SYSTEM],
[
'tenantId' => $tenantId,
'scope' => FirewallRuleObject::SCOPE_TENANT,
],
],
],
[
'$or' => [
['expiresAt' => null],
['expiresAt' => ['$gt' => $now]],
],
],
],
];
$cursor = $this->dataStore->selectCollection(self::RULES_COLLECTION)->find($filter);
$list = [];
foreach ($cursor as $entry) {
$list[] = (new FirewallRuleObject())->jsonDeserialize((array)$entry);
}
return $list;
}
/**
* Find rules by IP address
*/
@@ -118,15 +160,33 @@ class FirewallStore
/**
* Check if exact IP rule exists
*/
public function findExactIpRule(string $tenantId, string $ipAddress, string $action): ?FirewallRuleObject
public function findExactIpRule(
?string $tenantId,
string $ipAddress,
string $action,
string $scope = FirewallRuleObject::SCOPE_TENANT
): ?FirewallRuleObject
{
$entry = $this->dataStore->selectCollection(self::RULES_COLLECTION)->findOne([
'tenantId' => $tenantId,
$filter = [
'type' => FirewallRuleObject::TYPE_IP,
'value' => $ipAddress,
'action' => $action,
'enabled' => true,
]);
'$or' => [
['expiresAt' => null],
['expiresAt' => ['$gt' => (new \DateTimeImmutable())->format(\DateTimeInterface::ATOM)]],
],
];
if ($scope === FirewallRuleObject::SCOPE_SYSTEM) {
$filter['scope'] = FirewallRuleObject::SCOPE_SYSTEM;
$filter['tenantId'] = null;
} else {
$filter['tenantId'] = $tenantId;
$filter['scope'] = FirewallRuleObject::SCOPE_TENANT;
}
$entry = $this->dataStore->selectCollection(self::RULES_COLLECTION)->findOne($filter);
if (!$entry) {
return null;
@@ -139,6 +199,8 @@ class FirewallStore
*/
public function depositRule(FirewallRuleObject $rule): ?FirewallRuleObject
{
$rule->assertValidScopeOwnership();
if ($rule->getId()) {
return $this->updateRule($rule);
} else {