GCPOffendingFirewallRule

Determine potential offending firewall rules in GCP based on port, protocol and possibly target tags (network tags). Considerations: - At this time this automation only find potential offending rules and not necessarily the rule that is matching traffic.

python · GCP Enrichment and Remediation

Details

IDGCPOffendingFirewallRule
Languagepython
From Version6.8.0
Docker Imagedemisto/python3:3.12.13.10116658

README

Determine potential offending firewall rules in GCP based on port, protocol and possibly target tags (network tags).

Considerations:

  • At this time this automation only find potential offending rules and not necessarily the rule that is matching traffic.

Script Data


Name Description
Script Type python3
Cortex XSOAR Version 6.8.0

Used In


This script is used in the following playbooks and scripts.

  • GCP - Enrichment - EXPANDR-3608
  • GCP - Enrichment

Inputs


Argument Name Description
project_id The project to look up firewall rules in. The project ID instead of the project number. No need to supply `projects/` before the ID (i.e., use `project-name` instead of `projects/project-name` or `projects/111111111111`).
network_url The url of the network objects to lookup firewall rules in. This will be the url of the network and not just the name (i.e. https://www.googleapis.com/compute/v1/projects/<project_name>/global/networks/<network_name>).
port Port to match traffic on for firewall rules.
protocol Protocol to match traffic on for firewall rules.
network_tags Network tags on GCP VM instance to match rules based on target tag (optional).

Outputs


Path Description Type
GCPOffendingFirewallRule One or more potential offending firewall rules in GCP based on port, protocol and possibly target tags (network tags). Unknown
import demistomock as demisto  # noqa: F401
import pytest
from CommonServerPython import CommandResults
from pytest_mock import MockerFixture


def test_is_port_in_range_func():
    """Tests is_port_in_range helper function.

    Given:
        - Mocked arguments
    When:
        - Sending args to lookup helper function.
    Then:
        - Checks the output of the helpedfunction with the expected output.
    """
    from GCPOffendingFirewallRule import is_port_in_range

    assert is_port_in_range("20-25", "22")
    assert is_port_in_range("80-80", "80")
    assert not is_port_in_range("20-21", "22")
    assert not is_port_in_range("80-80", "81")


def test_is_there_traffic_match_func():
    """Tests is_there_traffic_match helper function.

    Given:
        - Mocked arguments
    When:
        - Sending args to lookup helper function.
    Then:
        - Checks the output of the helpedfunction with the expected output.
    """
    from GCPOffendingFirewallRule import is_there_traffic_match

    port = "22"
    protocol = "tcp"
    no_tags = []
    net_tags = ["test-tag"]
    # Matches on
    # all protocol and no target tags
    assert is_there_traffic_match(
        port,
        protocol,
        {
            "allowed": [{"IPProtocol": "all"}],
            "direction": "INGRESS",
            "disabled": False,
            "sourceRanges": ["0.0.0.0/0"],
        },
        no_tags,
    )
    # single port and target tags
    assert is_there_traffic_match(
        port,
        protocol,
        {
            "allowed": [{"IPProtocol": "tcp", "ports": ["22"]}],
            "direction": "INGRESS",
            "disabled": False,
            "sourceRanges": ["0.0.0.0/0"],
            "targetTags": ["test-tag"],
        },
        net_tags,
    )
    # port range and no target tags
    assert is_there_traffic_match(
        port,
        protocol,
        {
            "allowed": [{"IPProtocol": "tcp", "ports": ["20-25"]}],
            "direction": "INGRESS",
            "disabled": False,
            "sourceRanges": ["0.0.0.0/0"],
        },
        no_tags,
    )

    # Doesn't match on
    # wrong port/protocol
    assert not is_there_traffic_match(
        "50",
        "udp",
        {
            "allowed": [{"IPProtocol": "tcp", "ports": ["20-25"]}],
            "direction": "INGRESS",
            "disabled": False,
            "sourceRanges": ["0.0.0.0/0"],
        },
        no_tags,
    )
    # wrong target tag
    assert not is_there_traffic_match(
        port,
        protocol,
        {
            "allowed": [{"IPProtocol": "tcp", "ports": ["20-25"]}],
            "direction": "INGRESS",
            "disabled": False,
            "sourceRanges": ["0.0.0.0/0"],
            "targetTags": ["test-tag"],
        },
        ["bad_tag"],
    )
    # Disabled
    assert not is_there_traffic_match(
        port,
        protocol,
        {
            "allowed": [{"IPProtocol": "all"}],
            "direction": "INGRESS",
            "disabled": True,
            "sourceRanges": ["0.0.0.0/0"],
        },
        no_tags,
    )


@pytest.mark.parametrize(
    "scenario, command_return, command_result",
    [
        (
            "Firewall rule match",
            [
                {
                    "Type": 1,
                    "Contents": {
                        "id": "example-id",
                        "items": [
                            {
                                "allowed": [{"IPProtocol": "tcp", "ports": ["22"]}],
                                "direction": "INGRESS",
                                "disabled": False,
                                "name": "rule1",
                                "sourceRanges": ["0.0.0.0/0"],
                            }
                        ],
                    },
                }
            ],
            "Potential Offending GCP Firewall Rule(s) Found: ['rule1']",
        ),
    ],
)
def test_gcp_offending_firewall_rule_command(mocker: MockerFixture, scenario: str, command_return: list, command_result: str):
    """Tests gcp_offending_firewall_rule function.

    Given:
        - Mocked arguments
    When:
        - Sending args to gcp_offending_firewall_rule function.
    Then:
        - Checks the output of the function with the expected output.
    """
    from GCPOffendingFirewallRule import gcp_offending_firewall_rule

    mocker.patch.object(demisto, "executeCommand", return_value=command_return)

    args = {
        "project_id": "gcp-project",
        "network_url": "https://gcp-network",
        "port": "22",
        "protocol": "tcp",
        "network_tags": ["test-tag"],
    }
    result = gcp_offending_firewall_rule(args)
    expected_result = CommandResults(readable_output=f"{command_result}")

    assert result.readable_output == expected_result.readable_output