PAN-OS-AnalyzeRuleHitCounts

Processes the context output from !pan-os-get-rulehitcounts and returns data about unused local rules, unused rules from Panorama, and rules from Panorama that have hits on some firewalls but not all.

python · PAN-OS by Palo Alto Networks

Details

IDPAN-OS-AnalyzeRuleHitCounts
Languagepython
From Version6.10.0
Docker Imagedemisto/python3:3.12.13.10116658

README

Processes the context output from !pan-os-get-rulehitcounts and returns data about unused local rules, unused rules from Panorama, and rules from Panorama that have hits on some firewalls but not all.

Script Data


Name Description
Script Type python3
Cortex XSOAR Version 6.10.0

Inputs


There are no inputs for this script.

Outputs


Path Description Type
PANOS.UnusedRules.TotalLocalRulesAnalyzed The total number of local rules analyzed. Number
PANOS.UnusedRules.TotalPanoramaRulesAnalyzed The total number of rules pushed from Panorama analyzed. Number
PANOS.UnusedRules.UsedPanoramaRules.from_dg_name Name of the device group the rule is inherited from. String
PANOS.UnusedRules.UsedPanoramaRules.hostids_with_hits Host IDs of firewalls where this rule has hits. String
PANOS.UnusedRules.UsedPanoramaRules.hostnames_with_hits Hostnames of firewalls where this rule has hits. String
PANOS.UnusedRules.UsedPanoramaRules.hostids_with_zero_hits Host IDs of firewalls where this rule has zero hits. Unknown
PANOS.UnusedRules.UsedPanoramaRules.hostnames_with_zero_hits Hostnames of firewalls where this rule has zero hits. Unknown
PANOS.UnusedRules.UsedPanoramaRules.instanceName Name of the PAN-OS Integration Instance used to collect rule hitcount data. String
PANOS.UnusedRules.UsedPanoramaRules.name The name of the rule. String
PANOS.UnusedRules.UsedPanoramaRules.position The position of the rule within the Panorama device-group rulebase (pre-rulebase or post-rulebase). String
PANOS.UnusedRules.UsedPanoramaRules.rulebase The rulebase where the rule is configured (e.g. “Security”, “NAT”, etc). String
PANOS.UnusedRules.UnusedLocalRules.activeHAPeer If the firewall where this rule data comes from is in an HA pair, contains the hostid of the active device in the pair. Unknown
PANOS.UnusedRules.UnusedLocalRules.hostid Host ID of the firewall where the rule is configured. String
PANOS.UnusedRules.UnusedLocalRules.hostname Hostname of the firewall where this rule is configured. String
PANOS.UnusedRules.UnusedLocalRules.vsys The virtual system (vsys) where the rule is configured. String
PANOS.UnusedRules.UnusedLocalRules.instanceName Name of the PAN-OS Integration Instance used to collect rule hitcount data. String
PANOS.UnusedRules.UnusedLocalRules.name The name of the rule. String
PANOS.UnusedRules.UnusedLocalRules.position The position of the rule within the Panorama device-group rulebase (pre-rulebase or post-rulebase). String
PANOS.UnusedRules.UnusedLocalRules.rulebase The rulebase where the rule is configured (e.g. “Security”, “NAT”, etc). String
PANOS.UnusedRules.UnusedPanoramaRules.from_dg_name The rulebase where the rule is configured (e.g. “Security”, “NAT”, etc). String
PANOS.UnusedRules.UnusedPanoramaRules.instanceName Name of the PAN-OS Integration Instance used to collect rule hitcount data. String
PANOS.UnusedRules.UnusedPanoramaRules.name The name of the rule. String
PANOS.UnusedRules.UnusedPanoramaRules.position The position of the rule within the Panorama device-group rulebase (pre-rulebase or post-rulebase). String
PANOS.UnusedRules.UnusedPanoramaRules.rulebase The rulebase where the rule is configured (e.g. “Security”, “NAT”, etc). String
PANOS.UnusedRules.ignore_auto_extract Instructs the system not to perform indicator extraction on returned data. Boolean
import json


def load_json(path):
    with open(path, encoding="utf-8") as f:
        return json.loads(f.read())


sample_context = load_json("test_data/context_data.json")
sample_rule_hitcount_data = sample_context.get("PANOS", {}).get("RuleHitCount", [])
sample_ha_state_data = sample_context.get("PANOS", {}).get("HAState", [])
sample_system_info = sample_context.get("PANOS", {}).get("ShowSystemInfo", {}).get("Result")


def test_get_local_rules(mocker):
    """
    Test the function with a set of sample context data and verify it returns the correct unused local rules.
    """
    from PanOSAnalyzeRuleHitCounts import get_local_rules

    total_local_rules, summaries = get_local_rules(sample_rule_hitcount_data, sample_ha_state_data, sample_system_info)

    assert total_local_rules == 4
    assert len(summaries) == 2
    assert summaries[0]["name"] == "Rule1"
    assert summaries[1]["name"] == "Rule5"


def test_analyze_panorama_rules(mocker):
    """
    Test the function with a set of sample context data and verify it returns the correct unused Panorama rules.
    """
    from PanOSAnalyzeRuleHitCounts import analyze_panorama_rules

    total_panorama_rules, unused_panorama_rules, used_panorama_rules = analyze_panorama_rules(
        sample_rule_hitcount_data, sample_ha_state_data, sample_system_info
    )

    assert total_panorama_rules == 2
    assert len(unused_panorama_rules) == 1
    assert unused_panorama_rules[0]["name"] == "Rule6"
    assert used_panorama_rules[0]["name"] == "Rule4"
    assert used_panorama_rules[0]["hostnames_with_zero_hits"] == ["PAN-VM-01"]
    assert used_panorama_rules[0]["hostnames_with_hits"] == ["PAN-VM-02"]


def test_main(mocker):
    """
    Test the main function with some necessary data missing and verify it raises the appropriate exception.
    """
    from PanOSAnalyzeRuleHitCounts import main

    context_data = sample_context
    context_data["PANOS"].pop("HAState")
    mocker.patch("PanOSAnalyzeRuleHitCounts.demisto.context", return_value=sample_context)

    mock_return_error = mocker.patch("PanOSAnalyzeRuleHitCounts.return_error", return_value=True)

    main()

    assert (
        mock_return_error.call_args[0][0] == "Failed to execute PAN-OS-AnalyzeRuleHitCounts. Error: Missing data: HAState. "
        "Please run the 'pan-os-platform-get-ha-state' command to populate this data."
    )