-
Notifications
You must be signed in to change notification settings - Fork 66
Description
Environment
- Python version: 3.11.11
- netutils version: 1.15.1
Expected Behavior
section_config() may normalize the PAN-OS login banner terminator (for example, replacing the closing quote " with ^C). However, the resulting section must remain parseable by PaloAltoNetworksConfigParser.
Specifically, the parser should recognize ^C as a valid banner terminator and should not include subsequent set commands as part of the banner content. Normalization should not lead to banner parsing errors or unintended expansion of the banner section.
Observed Behavior
When extracting a PAN-OS login banner using section_config(), the returned configuration:
- Removes the closing double quote (")
- Appends ^C to the banner content (banner end normalization)
This transformation causes the returned section to be syntactically different from the original configuration and not parseable by PaloAltoNetworksConfigParser.
As a result, downstream calls (e.g. via diff_network_config() / feature_compliance()) raise: ValueError: Unable to parse banner end..
Example outputs from section_config():
Example 1:
config:
set deviceconfig system login-banner "####################################################
WARNING TO UNAUTHORIZED USERS:
...
####################################################
"
section_config() returns:
set deviceconfig system login-banner "####################################################
WARNING TO UNAUTHORIZED USERS:
...
####################################################
^C
Result: The closing '"' is removed and a '^C' is added.
In this case if we run feature_compliace() for this configuration we get the following exception:
>>> compliance = feature_compliance(feature, backup_cfg, intended_cfg_2, network_os)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/opt/nautobot/lib/python3.10/site-packages/netutils/config/compliance.py", line 355, in feature_compliance
feature_data.update(_check_configs_differences(intended_cfg, backup_cfg, network_os))
File "/opt/nautobot/lib/python3.10/site-packages/netutils/config/compliance.py", line 81, in _check_configs_differences
missing = diff_network_config(intended_cfg, actual_cfg, network_os)
File "/opt/nautobot/lib/python3.10/site-packages/netutils/config/compliance.py", line 284, in diff_network_config
compare_parser = os_parser(compare_config)
File "/opt/nautobot/lib/python3.10/site-packages/netutils/config/parser.py", line 65, in __init__
super(BaseSpaceConfigParser, self).__init__(config)
File "/opt/nautobot/lib/python3.10/site-packages/netutils/config/parser.py", line 32, in __init__
self.build_config_relationship()
File "/opt/nautobot/lib/python3.10/site-packages/netutils/config/parser.py", line 1579, in build_config_relationship
line = self._build_banner(line) # type: ignore
File "/opt/nautobot/lib/python3.10/site-packages/netutils/config/parser.py", line 1538, in _build_banner
raise ValueError("Unable to parse banner end.")
ValueError: Unable to parse banner end.
Example 2:
config:
set deviceconfig system login-banner "####################################################
WARNING TO UNAUTHORIZED USERS:
...
####################################################
"
set deviceconfig system ntp-servers primary-ntp-server ntp-server-address ntp.chevron.net
set deviceconfig system ntp-servers primary-ntp-server authnetication-type none
section_config() returns:
set deviceconfig system login-banner "####################################################
WARNING TO UNAUTHORIZED USERS:
...
####################################################
^C
set deviceconfig system ntp-servers primary-ntp-server ntp-server-address ntp.chevron.net
set deviceconfig system ntp-servers primary-ntp-server authnetication-type none
Result: The closing '"' is removed and the set commands that follow the banner are included in the section.
Based on the above section_config() normalizes the PAN-OS login banner by replacing the closing quote (") with a ^C terminator. As a result, the section passed to diff_network_config() is no longer the original PAN-OS quoted banner but an IOS-style banner. However, PaloAltoNetworksConfigParser does not recognize ^C as a valid banner terminator, which leads to parsing errors.
Also, because line.startswith("set") is included in PaloAltoNetworksConfigParser.is_banner_end() checks, in Example 2 the subsequent set commands are incorrectly included in the banner section.
Steps to Reproduce
Example script to reproduce the issue:
from netutils.config.parser import PaloAltoNetworksConfigParser
from netutils.config.compliance import section_config, feature_compliance, diff_network_config, _check_configs_differences
import json
intended_1 = """\
set deviceconfig system login-banner "##
xxxxx
##
"
set deviceconfig system ntp-servers primary-ntp-server ntp-server-address ntp.chevron.net
set deviceconfig system ntp-servers primary-ntp-server authentication-type none
"""
intended_2 = """\
set deviceconfig system login-banner "##
xxxxx
##
"
"""
backup = """\
"""
network_os = "paloalto_panos"
feature = {"section":['set deviceconfig system login-banner'],"ordered":False}
backup_cfg = section_config(feature, backup, network_os)
intended_cfg_1 = section_config(feature, intended_1, network_os)
print(intended_cfg_1)
compliance = feature_compliance(feature, backup_cfg, intended_cfg_1, network_os)
print(json.dumps(compliance, indent=4))
intended_cfg_2 = section_config(feature, intended_2, network_os)
print(intended_cfg_2)
compliance = feature_compliance(feature, backup_cfg, intended_cfg_2, network_os)
print(json.dumps(compliance, indent=4))