API Reference¶
This section provides detailed documentation for all modules, classes, and functions in the Policy Inspector package.
Core Modules¶
CLI Interface¶
- policy_inspector.cli.run_scenario_with_panorama(scenario_cls: type[~policy_inspector.scenario.Scenario], panorama_hostname: str, panorama_username: str, panorama_password: str, panorama_api_version: str = 'v11.1', panorama_verify_ssl: bool = False, export: tuple[str, ...] = (), export_dir: str | None = '.', show: tuple[str, ...] = ('text',), panorama_cls: type[~policy_inspector.panorama.PanoramaConnector] = <class 'policy_inspector.panorama.PanoramaConnector'>, **kwargs) None[source]¶
Common scenario execution logic for Panorama-based scenarios.
- policy_inspector.cli.run_scenario_with_mock_data(scenario_cls: type[Scenario], data_dir: Path, device_group: str, device_groups: tuple[str] = (), show: tuple[str, ...] = (), export: tuple[str, ...] = (), export_dir: str | None = '.', **kwargs) None[source]¶
Run scenario using mock data from JSON files.
Configuration Management¶
- policy_inspector.config.configure_from_yaml(ctx, param, filename)[source]¶
Callback for –config option that reads YAML configuration file and sets ctx.default_map for Click to use as parameter defaults.
- Parameters:
ctx – Click context
param – The parameter object (not used)
filename – Path to the YAML configuration file
- policy_inspector.config.config_option(config_file_name: str = '--config', default: str = 'config.yaml')[source]¶
Decorator that adds a –config option to read defaults from a YAML file.
This uses Click’s ctx.default_map mechanism to set parameter defaults from the configuration file. The configuration file is processed eagerly before other options.
- Parameters:
config_file_name – The option name (default: “–config”)
default – Default config file name
help_text – Help text for the option
Returns:
- policy_inspector.config.show_options(f)[source]¶
Decorator that adds –show click options to a command.
- policy_inspector.config.export_options(f)[source]¶
Decorator that adds –export and –export-dir options to a command.
- policy_inspector.config.panorama_options(f)[source]¶
Decorator that adds panorama connection click options to a command.
These options are for connecting to Panorama: - panorama_hostname: str - Panorama hostname/IP - panorama_username: str - Username for authentication - panorama_password: str - Password for authentication (hidden input) - panorama_api_version: str - PAN-OS API version (default: v11.1) - panorama_verify_ssl: bool - Whether to verify SSL certificates (default: False)
- Parameters:
f – The function to decorate
- Returns:
The decorated function with panorama options added
Panorama Integration¶
- class policy_inspector.panorama.PanoramaConnector(hostname: str, username: str, password: str, port: int = 443, verify_ssl: bool = False, api_version: str = 'v1', timeout: int = 60)[source]¶
Bases:
objectConnect to Panorama and retrieve objects using REST API.
- Parameters:
hostname – Panorama hostname or IP address
username – API username
password – API password
port – API port (default: 443)
verify_ssl – Whether to verify SSL certificates
api_version – REST API version (default: v1)
timeout – Request timeout in seconds
- __init__(hostname: str, username: str, password: str, port: int = 443, verify_ssl: bool = False, api_version: str = 'v1', timeout: int = 60)[source]¶
- get_address_objects(device_group: str | None = None) list[AddressObject][source]¶
Retrieve address objects from Panorama using REST API.
- Parameters:
device_group – Name of the Device Group or shared if
None.- Returns:
List of
AddressObjectinstances.
- get_address_groups(device_group: str | None = None) list[AddressGroup][source]¶
Retrieve address groups from Panorama using REST API.
- Parameters:
device_group – Name of the Device Group of shared if
None.- Returns:
List of
AddressGroupinstances
- get_security_rules(device_group: str | None = None, rulebase: Literal['pre', 'post'] = 'post') list[SecurityRule][source]¶
Retrieve security rules from Panorama using REST API.
- Parameters:
device_group – Name of the Device Group of shared if
None.rulebase – Type of rulebase.
- Returns:
List of
SecurityRuleinstances.
Filters System¶
- policy_inspector.filters.apply_filters(filters: Iterable[Callable[[SecurityRule], bool]], policies: Iterable[SecurityRule]) Iterator[SecurityRule][source]¶
Apply a set of filter functions to security policies.
- Parameters:
filters – An iterable of filter functions that take a SecurityRule object and return a boolean indicating whether the rule should be included.
policies – An iterable of SecurityRule objects to be filtered.
- Returns:
An iterator over SecurityRule objects that pass all filter conditions.
Example
>>> filters = [exclude_disabled, exclude_deny] >>> filtered_policies = apply_filters(filters, policies) >>> for policy in filtered_policies: ... print(policy)
- policy_inspector.filters.exclude_disabled(policy: SecurityRule) bool[source]¶
Exclude security rules that are disabled.
- policy_inspector.filters.exclude_deny(policy: SecurityRule) bool[source]¶
Exclude security rules with a ‘deny’ action.
Scenario Framework¶
- class policy_inspector.scenario.Scenario(panorama: PanoramaConnector, **kwargs)[source]
Bases:
objectBase class for defining security scenarios and checks.
- name
Scenario display name.
- Type:
str | None
- panorama
PanoramaConnector instance for data retrieval.
- _scenarios
A set of all registered subclasses of Scenario.
- Type:
dict[str, type[Scenario]]
- name: str | None = None
- __init__(panorama: PanoramaConnector, **kwargs) None[source]
Initialize a Scenario instance.
- Parameters:
panorama – PanoramaConnector instance for data retrieval.
**kwargs – Additional keyword arguments for subclass customization.
- classmethod __init_subclass__(**kwargs) None[source]
Registers subclasses automatically in the scenarios set.
- classmethod get_available() dict[str, type[Scenario]][source]
Retrieve all registered
Scenariosubclasses.- Returns:
A set containing all subclasses of
Scenario.
- classmethod from_name(name: str) type[Scenario][source]
- show(formats, *args, **kwargs)[source]
Show scenario results in the given formats using registered show functions.
- export(formats, *args, output_dir: str | None = None, **kwargs)[source]
Export scenario results in the given formats using registered export functions. If exporting to HTML, save the file to output_dir or current directory.
- execute() ScenarioResults[source]
Execute the scenario logic.
Warning
This method must be implemented by subclasses.
- Returns:
The results of executing.
- analyze(results: ScenarioResults) AnalysisResult[source]
Analyze the results obtained from executing a scenario.
Warning
This method must be implemented by subclasses.
- Parameters:
results – The results to analyze.
- Returns:
The analysis outcome.
- execute_and_analyze() AnalysisResult[source]
Execute the scenario and analyze the results.
Address Resolution¶
- class policy_inspector.resolver.Resolver(address_objects: list[AddressObject], address_groups: list[AddressGroup])[source]¶
Bases:
objectProcess Address Groups into their Address Objects or IP Network object.
It expands Address Groups (AG) recursively.
- Parameters:
address_objects – A list of
AddressObject.address_groups – A list of
AddressGroup.
- __init__(address_objects: list[AddressObject], address_groups: list[AddressGroup])[source]¶
- resolve(names: Iterable[str]) list[AddressObject][source]¶
Resolve given names.
- Parameters:
names – Names of
Address GroupsorAddress Objects
Utilities¶
- policy_inspector.utils.load_json(path: Path) list[dict[str, Any]][source]¶
Load and parse a JSON file, returning its contents as a list of dictionaries.
- policy_inspector.utils.register_export(scenario_cls: type, fmt: str)[source]¶
Decorator to register an export function for a scenario and format.
- policy_inspector.utils.get_export_func(scenario, fmt: str)[source]¶
Get export function for scenario instance and format.
- policy_inspector.utils.register_show(scenario_cls: type, fmt: str)[source]¶
Decorator to register a show function for a scenario and format.
- policy_inspector.utils.get_show_func(scenario, fmt: str)[source]¶
Get show function for scenario instance and format.
- policy_inspector.utils.load_jinja_template(template_dir: Path, template_name: str)[source]¶
Load a Jinja2 template from the current directory.
- class policy_inspector.utils.VerboseGroup(name=None, commands=None, **attrs)[source]¶
Bases:
RichGroupClick Group that automatically adds verbose option to all commands.
- policy_inspector.utils.config_logger(logger_name: str = 'policy_inspector', default_level: str = 'INFO', log_format: str = '%(message)s', date_format: str = '[%X]') None[source]¶
Configure
loggerwithRichHandler- Parameters:
logger – Instance of a
logging.Loggerlevel – Default level of a
logger.log_format – Logs format.
date_format – Date format in logs.
- class policy_inspector.utils.Example(*, name: str, scenario: type, data_dir: str, device_group: str, show: tuple[str, ...] = ('text',), export: tuple[str, ...] = (), args: dict[str, Any] = {})[source]¶
Bases:
BaseModelRepresents an example that can be run.
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- name: str¶
- scenario: type¶
- data_dir: str¶
- device_group: str¶
- show: tuple[str, ...]¶
- export: tuple[str, ...]¶
- args: dict[str, Any]¶
Data Models¶
Base Models¶
- class policy_inspector.model.base.MainModel[source]¶
Bases:
BaseModelBase class for all models.
- singular: ClassVar[str | None] = None¶
Display name of a single model.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- plural: ClassVar[str | None] = None¶
Display name of a many models.
Security Rules¶
- class policy_inspector.model.security_rule.SecurityRule(*, index: int = 1, name: str, enabled: bool = True, action: ~typing.Literal['allow', 'deny', 'monitor'] = 'allow', source_zones: set[str] | set[~typing.Literal['any']] = {'any'}, destination_zones: set[str] | set[~typing.Literal['any']] = {'any'}, source_addresses: set[str] | set[~typing.Literal['any']] = {'any'}, destination_addresses: set[str] | set[~typing.Literal['any']] = {'any'}, applications: set[str] | set[~typing.Literal['any']] = {'any'}, services: set[str] | set[~typing.Literal['any']] | set[~typing.Literal['application-default']] = <factory>, category: set[str] | set[~typing.Literal['any']] = {'any'})[source]¶
Bases:
MainModel- singular: ClassVar[str] = 'Security Rule'¶
Display name of a single model.
- plural: ClassVar[str] = 'Security Rules'¶
Display name of a many models.
- index: int¶
- name: str¶
- enabled: bool¶
- action: Literal['allow', 'deny', 'monitor']¶
- source_zones: set[str] | set[Literal['any']]¶
- destination_zones: set[str] | set[Literal['any']]¶
- source_addresses: set[str] | set[Literal['any']]¶
- destination_addresses: set[str] | set[Literal['any']]¶
- applications: set[str] | set[Literal['any']]¶
- services: set[str] | set[Literal['any']] | set[Literal['application-default']]¶
- category: set[str] | set[Literal['any']]¶
- classmethod parse_json(elements: list[dict]) list[SecurityRule][source]¶
Map a JSON object to a SecurityRule.
- classmethod parse_csv(elements: list[dict]) list[SecurityRule][source]¶
Map a CSV row to a SecurityRule.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class policy_inspector.model.security_rule.AdvancedSecurityRule(*, index: int = 1, name: str, enabled: bool = True, action: ~typing.Literal['allow', 'deny', 'monitor'] = 'allow', source_zones: set[str] | set[~typing.Literal['any']] = {'any'}, destination_zones: set[str] | set[~typing.Literal['any']] = {'any'}, source_addresses: set[str] | set[~typing.Literal['any']] = {'any'}, destination_addresses: set[str] | set[~typing.Literal['any']] = {'any'}, applications: set[str] | set[~typing.Literal['any']] = {'any'}, services: set[str] | set[~typing.Literal['any']] | set[~typing.Literal['application-default']] = <factory>, category: set[str] | set[~typing.Literal['any']] = {'any'}, resolved_source_addresses: list[~policy_inspector.model.address_object.AddressObjectIPNetwork | ~policy_inspector.model.address_object.AddressObjectIPRange | ~policy_inspector.model.address_object.AddressObjectFQDN] | None = None, resolved_destination_addresses: list[~policy_inspector.model.address_object.AddressObjectIPNetwork | ~policy_inspector.model.address_object.AddressObjectIPRange | ~policy_inspector.model.address_object.AddressObjectFQDN] | None = None)[source]¶
Bases:
SecurityRule- resolved_source_addresses: list[AddressObjectIPNetwork | AddressObjectIPRange | AddressObjectFQDN] | None¶
- resolved_destination_addresses: list[AddressObjectIPNetwork | AddressObjectIPRange | AddressObjectFQDN] | None¶
- classmethod from_security_rule(rule: SecurityRule, **kwargs) AdvancedSecurityRule[source]¶
Convert a base
SecurityRuleto anAdvancedSecurityRule.- Parameters:
rule –
SecurityRuleinstance to convert- Returns:
New
AdvancedSecurityRuleinstance with same field values
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
Address Objects¶
- class policy_inspector.model.address_object.AddressObject(*, name: str, description: str = '', tags: set[str] = <factory>)[source]¶
Bases:
MainModelBase class representing a network address object.
- singular: ClassVar[str] = 'Address Object'¶
Display name of a single model.
- plural: ClassVar[str] = 'Address Objects'¶
Display name of a many models.
- name: str¶
- description: str¶
- tags: set[str]¶
- is_covered_by(other: AddressObject) bool[source]¶
- classmethod parse_json(elements: list[dict]) list[AddressObject][source]¶
Parse JSON data from PAN-OS API response
- classmethod parse_csv(elements: list[dict]) list[AddressObject][source]¶
Parse CSV row from spreadsheet import
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class policy_inspector.model.address_object.AddressObjectIPNetwork(*, name: str, description: str = '', tags: set[str] = <factory>, value: ~ipaddress.IPv4Network)[source]¶
Bases:
AddressObjectRepresents an IPv4 network range using CIDR notation.
- value: IPv4Network¶
- classmethod convert(v) IPv4Network[source]¶
Convert string to IPv4Network instance.
- Raises:
ValueError – For invalid network formats
- is_covered_by(other: AddressObject) bool[source]¶
Check if this network is fully contained within another object.
- Returns:
Contained within another IP network
Fully inside an IP range
- Return type:
True if either
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class policy_inspector.model.address_object.AddressObjectIPRange(*, name: str, description: str = '', tags: set[str] = <factory>, value: tuple[~ipaddress.IPv4Address, ~ipaddress.IPv4Address])[source]¶
Bases:
AddressObjectRepresents a contiguous range of IPv4 addresses.
- value: tuple[IPv4Address, IPv4Address]¶
- classmethod convert(v) tuple[IPv4Address, IPv4Address][source]¶
Convert string or list to IPv4Address tuple.
- classmethod validate(v)[source]¶
Ensure valid IP range ordering.
- Raises:
ValueError – If end address precedes start address
- is_covered_by(other: AddressObject) bool[source]¶
Check if this range is fully contained within another object.
- Returns:
Fully inside another IP network
Contained within another IP range
- Return type:
True if either
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class policy_inspector.model.address_object.AddressObjectFQDN(*, name: str, description: str = '', tags: set[str] = <factory>, value: str)[source]¶
Bases:
AddressObjectRepresents a fully qualified domain name.
- value: str¶
- is_covered_by(other: AddressObject) bool[source]¶
Check FQDN equivalence.
- Returns:
True if both FQDNs match exactly (case-insensitive)
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
Address Groups¶
- class policy_inspector.model.address_group.AddressGroup(*, name: str, description: str = '', tag: set[str] = <factory>, static: set[str] = <factory>)[source]¶
Bases:
MainModel- singular: ClassVar[str] = 'Address Group'¶
Display name of a single model.
- plural: ClassVar[str] = 'Address Groups'¶
Display name of a many models.
- name: str¶
- description: str¶
- tag: set[str]¶
- static: set[str]¶
- classmethod parse_json(elements: list[dict]) list[AddressGroup][source]¶
Map a JSON object to an AddressGroup.
- classmethod parse_csv(elements: list[dict]) list[AddressGroup][source]¶
Map a JSON object to an AddressObject.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].