fix(firewall): enforce system rules independently of tenant context
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
@@ -10,20 +10,30 @@ use KTXC\Stores\FirewallStore;
|
||||
final class FirewallRuleCache
|
||||
{
|
||||
/** @var array<string, FirewallRuleObject[]> */
|
||||
private array $rules = [];
|
||||
private array $tenantRules = [];
|
||||
|
||||
/** @var FirewallRuleObject[]|null */
|
||||
private ?array $systemRules = null;
|
||||
|
||||
public function __construct(private readonly FirewallStore $store)
|
||||
{
|
||||
}
|
||||
|
||||
/** @return FirewallRuleObject[] */
|
||||
public function applicable(string $tenantId): array
|
||||
public function tenant(string $tenantId): array
|
||||
{
|
||||
return $this->rules[$tenantId] ??= $this->store->listApplicableRules($tenantId);
|
||||
return $this->tenantRules[$tenantId] ??= $this->store->listRules($tenantId);
|
||||
}
|
||||
|
||||
/** @return FirewallRuleObject[] */
|
||||
public function system(): array
|
||||
{
|
||||
return $this->systemRules ??= $this->store->listSystemRules();
|
||||
}
|
||||
|
||||
public function invalidate(): void
|
||||
{
|
||||
$this->rules = [];
|
||||
$this->tenantRules = [];
|
||||
$this->systemRules = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,26 +73,22 @@ class FirewallService
|
||||
string $ipAddress,
|
||||
?string $deviceFingerprint = null
|
||||
): FirewallAnalyzeResult {
|
||||
// Check if firewall is enabled for this tenant
|
||||
if (!$this->isEnabled()) {
|
||||
return new FirewallAnalyzeResult(true);
|
||||
}
|
||||
|
||||
$tenantId = $this->tenantContext->identifier();
|
||||
if (!$tenantId) {
|
||||
return new FirewallAnalyzeResult(true);
|
||||
$ruleGroups = [
|
||||
[$this->ruleCache->system(), FirewallRuleObject::ACTION_BLOCK],
|
||||
];
|
||||
|
||||
if ($tenantId !== null && $this->isEnabled()) {
|
||||
$tenantRules = $this->ruleCache->tenant($tenantId);
|
||||
$ruleGroups[] = [$tenantRules, FirewallRuleObject::ACTION_ALLOW];
|
||||
$ruleGroups[] = [$tenantRules, FirewallRuleObject::ACTION_BLOCK];
|
||||
}
|
||||
|
||||
$rules = $this->getActiveRules();
|
||||
$ruleGroups[] = [$this->ruleCache->system(), FirewallRuleObject::ACTION_ALLOW];
|
||||
|
||||
foreach ([
|
||||
[FirewallRuleObject::SCOPE_SYSTEM, FirewallRuleObject::ACTION_BLOCK],
|
||||
[FirewallRuleObject::SCOPE_TENANT, FirewallRuleObject::ACTION_ALLOW],
|
||||
[FirewallRuleObject::SCOPE_TENANT, FirewallRuleObject::ACTION_BLOCK],
|
||||
[FirewallRuleObject::SCOPE_SYSTEM, FirewallRuleObject::ACTION_ALLOW],
|
||||
] as [$scope, $action]) {
|
||||
foreach ($ruleGroups as [$rules, $action]) {
|
||||
foreach ($rules as $rule) {
|
||||
if ($rule->getScope() !== $scope || $rule->getAction() !== $action) {
|
||||
if ($rule->getAction() !== $action) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -310,20 +306,6 @@ class FirewallService
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active rules (cached)
|
||||
* @return FirewallRuleObject[]
|
||||
*/
|
||||
private function getActiveRules(): array
|
||||
{
|
||||
$tenantId = $this->tenantContext->identifier();
|
||||
if (!$tenantId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->ruleCache->applicable($tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup maintenance tasks
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user