diff --git a/prowler/changelog.d/gcp-firewall-multiport.fixed.md b/prowler/changelog.d/gcp-firewall-multiport.fixed.md new file mode 100644 index 0000000000..d9902a56f5 --- /dev/null +++ b/prowler/changelog.d/gcp-firewall-multiport.fixed.md @@ -0,0 +1 @@ +GCP firewall SSH and RDP checks now detect exposed target ports in any position within multi-port rules diff --git a/prowler/providers/gcp/services/compute/compute_firewall_rdp_access_from_the_internet_allowed/compute_firewall_rdp_access_from_the_internet_allowed.py b/prowler/providers/gcp/services/compute/compute_firewall_rdp_access_from_the_internet_allowed/compute_firewall_rdp_access_from_the_internet_allowed.py index af99daeec5..be860ea155 100644 --- a/prowler/providers/gcp/services/compute/compute_firewall_rdp_access_from_the_internet_allowed/compute_firewall_rdp_access_from_the_internet_allowed.py +++ b/prowler/providers/gcp/services/compute/compute_firewall_rdp_access_from_the_internet_allowed/compute_firewall_rdp_access_from_the_internet_allowed.py @@ -31,7 +31,7 @@ class compute_firewall_rdp_access_from_the_internet_allowed(Check): break elif int(port) == 3389: opened_port = True - break + break if ( "0.0.0.0/0" in firewall.source_ranges and firewall.direction == "INGRESS" diff --git a/prowler/providers/gcp/services/compute/compute_firewall_ssh_access_from_the_internet_allowed/compute_firewall_ssh_access_from_the_internet_allowed.py b/prowler/providers/gcp/services/compute/compute_firewall_ssh_access_from_the_internet_allowed/compute_firewall_ssh_access_from_the_internet_allowed.py index e4881568cf..a00158cd1d 100644 --- a/prowler/providers/gcp/services/compute/compute_firewall_ssh_access_from_the_internet_allowed/compute_firewall_ssh_access_from_the_internet_allowed.py +++ b/prowler/providers/gcp/services/compute/compute_firewall_ssh_access_from_the_internet_allowed/compute_firewall_ssh_access_from_the_internet_allowed.py @@ -31,7 +31,7 @@ class compute_firewall_ssh_access_from_the_internet_allowed(Check): break elif int(port) == 22: opened_port = True - break + break if ( "0.0.0.0/0" in firewall.source_ranges and firewall.direction == "INGRESS" diff --git a/tests/providers/gcp/services/compute/compute_firewall_rdp_access_from_the_internet_allowed/compute_firewall_rdp_access_from_the_internet_allowed_test.py b/tests/providers/gcp/services/compute/compute_firewall_rdp_access_from_the_internet_allowed/compute_firewall_rdp_access_from_the_internet_allowed_test.py index 930ee14605..71e44fb702 100644 --- a/tests/providers/gcp/services/compute/compute_firewall_rdp_access_from_the_internet_allowed/compute_firewall_rdp_access_from_the_internet_allowed_test.py +++ b/tests/providers/gcp/services/compute/compute_firewall_rdp_access_from_the_internet_allowed/compute_firewall_rdp_access_from_the_internet_allowed_test.py @@ -279,6 +279,48 @@ class Test_compute_firewall_rdp_access_from_the_internet_allowed: ) assert result[0].resource_id == firewall.id + def test_one_non_compliant_rule_with_multiple_ports(self): + from prowler.providers.gcp.services.compute.compute_service import Firewall + + firewall = Firewall( + name="test", + id="1234567890", + source_ranges=["0.0.0.0/0"], + direction="INGRESS", + allowed_rules=[{"IPProtocol": "tcp", "ports": ["80", "3389"]}], + project_id=GCP_PROJECT_ID, + ) + + compute_client = mock.MagicMock() + compute_client.project_ids = [GCP_PROJECT_ID] + compute_client.firewalls = [firewall] + compute_client.region = "global" + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.compute.compute_firewall_rdp_access_from_the_internet_allowed.compute_firewall_rdp_access_from_the_internet_allowed.compute_client", + new=compute_client, + ), + ): + from prowler.providers.gcp.services.compute.compute_firewall_rdp_access_from_the_internet_allowed.compute_firewall_rdp_access_from_the_internet_allowed import ( + compute_firewall_rdp_access_from_the_internet_allowed, + ) + + check = compute_firewall_rdp_access_from_the_internet_allowed() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert search( + f"Firewall {firewall.name} does exposes port 3389", + result[0].status_extended, + ) + assert result[0].resource_id == firewall.id + def test_one_non_compliant_rule_with_port_range(self): from prowler.providers.gcp.services.compute.compute_service import Firewall diff --git a/tests/providers/gcp/services/compute/compute_firewall_ssh_access_from_the_internet_allowed/compute_firewall_ssh_access_from_the_internet_allowed_test.py b/tests/providers/gcp/services/compute/compute_firewall_ssh_access_from_the_internet_allowed/compute_firewall_ssh_access_from_the_internet_allowed_test.py index 9939415ab7..315a899768 100644 --- a/tests/providers/gcp/services/compute/compute_firewall_ssh_access_from_the_internet_allowed/compute_firewall_ssh_access_from_the_internet_allowed_test.py +++ b/tests/providers/gcp/services/compute/compute_firewall_ssh_access_from_the_internet_allowed/compute_firewall_ssh_access_from_the_internet_allowed_test.py @@ -279,6 +279,48 @@ class Test_compute_firewall_ssh_access_from_the_internet_allowed: ) assert result[0].resource_id == firewall.id + def test_one_non_compliant_rule_with_multiple_ports(self): + from prowler.providers.gcp.services.compute.compute_service import Firewall + + firewall = Firewall( + name="test", + id="1234567890", + source_ranges=["0.0.0.0/0"], + direction="INGRESS", + allowed_rules=[{"IPProtocol": "tcp", "ports": ["80", "22"]}], + project_id=GCP_PROJECT_ID, + ) + + compute_client = mock.MagicMock() + compute_client.project_ids = [GCP_PROJECT_ID] + compute_client.firewalls = [firewall] + compute_client.region = "global" + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.compute.compute_firewall_ssh_access_from_the_internet_allowed.compute_firewall_ssh_access_from_the_internet_allowed.compute_client", + new=compute_client, + ), + ): + from prowler.providers.gcp.services.compute.compute_firewall_ssh_access_from_the_internet_allowed.compute_firewall_ssh_access_from_the_internet_allowed import ( + compute_firewall_ssh_access_from_the_internet_allowed, + ) + + check = compute_firewall_ssh_access_from_the_internet_allowed() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert search( + f"Firewall {firewall.name} does exposes port 22", + result[0].status_extended, + ) + assert result[0].resource_id == firewall.id + def test_one_non_compliant_rule_with_port_range(self): from prowler.providers.gcp.services.compute.compute_service import Firewall