from unittest import mock from prowler.providers.vercel.services.project.project_service import VercelProject from prowler.providers.vercel.services.security.security_service import Security from tests.providers.vercel.vercel_fixtures import PROJECT_ID, PROJECT_NAME, TEAM_ID class TestSecurityService: def test_fetch_firewall_config_reads_active_version_and_normalizes_response(self): project = VercelProject( id=PROJECT_ID, name=PROJECT_NAME, team_id=TEAM_ID, billing_plan="pro", ) service = Security.__new__(Security) service.firewall_configs = {} service._get = mock.MagicMock( return_value={ "active": { "firewallEnabled": True, "managedRules": { "owasp": {"active": True, "action": "deny"}, "ai_bots": {"active": False, "action": "deny"}, }, "rules": [ { "id": "rule-custom", "name": "Block admin access", "active": True, "conditionGroup": [ { "conditions": [ { "type": "path", "op": "pre", "value": "/admin", } ] } ], "action": { "mitigate": { "action": "deny", } }, }, { "id": "rule-rate-limit", "name": "Rate limit login", "active": True, "conditionGroup": [ { "conditions": [ { "type": "path", "op": "eq", "value": "/login", } ] } ], "action": { "mitigate": { "action": "deny", "rateLimit": { "algo": "fixed_window", "window": 60, "limit": 10, }, } }, }, ], "ips": [ { "id": "ip-rule", "ip": "203.0.113.7", "action": "deny", } ], }, "draft": None, "versions": [1], } ) service._fetch_firewall_config(project) service._get.assert_called_once_with( "/v1/security/firewall/config/active", params={"projectId": PROJECT_ID, "teamId": TEAM_ID}, ) config = service.firewall_configs[PROJECT_ID] assert config.billing_plan == "pro" assert config.firewall_enabled is True assert config.managed_rulesets == {"owasp": {"active": True, "action": "deny"}} assert [rule["id"] for rule in config.custom_rules] == ["rule-custom"] assert [rule["id"] for rule in config.rate_limiting_rules] == [ "rule-rate-limit" ] assert [rule["id"] for rule in config.ip_blocking_rules] == ["ip-rule"] def test_fetch_firewall_config_parses_crs_managed_rulesets(self): project = VercelProject( id=PROJECT_ID, name=PROJECT_NAME, team_id=TEAM_ID, firewall_config_version="1", ) service = Security.__new__(Security) service.firewall_configs = {} service._get = mock.MagicMock( return_value={ "id": "waf_test", "version": 1, "firewallEnabled": True, "crs": { "gen": {"active": True, "action": "log"}, "xss": {"active": True, "action": "deny"}, "php": {"active": False, "action": "log"}, }, "rules": [], "ips": [], } ) service._fetch_firewall_config(project) config = service.firewall_configs[PROJECT_ID] assert config.firewall_enabled is True assert config.managed_rulesets == { "gen": {"active": True, "action": "log"}, "xss": {"active": True, "action": "deny"}, } def test_fetch_firewall_config_falls_back_to_wrapper_when_active_missing(self): project = VercelProject(id=PROJECT_ID, name=PROJECT_NAME, team_id=TEAM_ID) service = Security.__new__(Security) service.firewall_configs = {} service._get = mock.MagicMock( side_effect=[ Exception("404 active config not found"), {"active": None, "draft": None, "versions": []}, ] ) service._fetch_firewall_config(project) assert service._get.call_args_list == [ mock.call( "/v1/security/firewall/config/active", params={"projectId": PROJECT_ID, "teamId": TEAM_ID}, ), mock.call( "/v1/security/firewall/config", params={"projectId": PROJECT_ID, "teamId": TEAM_ID}, ), ] config = service.firewall_configs[PROJECT_ID] assert config.firewall_enabled is False assert config.managed_rulesets == {} assert config.custom_rules == [] assert config.rate_limiting_rules == [] assert config.ip_blocking_rules == [] def test_fetch_firewall_config_uses_project_security_metadata_when_config_empty( self, ): project = VercelProject( id=PROJECT_ID, name=PROJECT_NAME, team_id=TEAM_ID, firewall_enabled=True, firewall_config_version="42", managed_rules={ "owasp": {"active": True, "action": "log"}, "ai_bots": {"active": False, "action": "deny"}, }, ) service = Security.__new__(Security) service.firewall_configs = {} service._get = mock.MagicMock( return_value={"active": None, "draft": None, "versions": []} ) service._fetch_firewall_config(project) service._get.assert_called_once_with( "/v1/security/firewall/config/42", params={"projectId": PROJECT_ID, "teamId": TEAM_ID}, ) config = service.firewall_configs[PROJECT_ID] assert config.firewall_enabled is True assert config.managed_rulesets == {"owasp": {"active": True, "action": "log"}} assert config.custom_rules == [] assert config.rate_limiting_rules == [] assert config.ip_blocking_rules == []