diff --git a/Makefile b/Makefile index 66b565c..14b6587 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,28 @@ +.phony: lint lint: flake8 panos_upgrade_assurance tests +.phony: security security: bandit -c pyproject.toml -r . +.phony: format_check format_check: black --diff --check panos_upgrade_assurance tests +.phony: format format: black panos_upgrade_assurance tests +.phony: test_coverage test_coverage: pytest --cov panos_upgrade_assurance --cov-report=term-missing --cov-report=xml:coverage.xml +.phony: documentation documentation: pydoc-markdown +.phony: check_line_length check_line_length: @for FILE in $$(find . -type f -name '*.py'); do \ echo $$FILE; \ @@ -29,4 +36,8 @@ check_line_length: done < "$$FILE"; \ done +.phony: all all: lint format security test_coverage documentation + +.phony: sca +sca: format lint security \ No newline at end of file diff --git a/docs/panos-upgrade-assurance/api/exceptions.md b/docs/panos-upgrade-assurance/api/exceptions.md index 20b80ba..ec5ff8d 100644 --- a/docs/panos-upgrade-assurance/api/exceptions.md +++ b/docs/panos-upgrade-assurance/api/exceptions.md @@ -28,6 +28,11 @@ module. Parent class for all exceptions coming from [Utils](/panos/docs/panos-upgrade-assurance/api/utils) module. +## class `WrongNumberOfArgumentsException` + +Thrown when [FirewallProxy](/panos/docs/panos-upgrade-assurance/api/firewall_proxy) constructor is given wrong number or +set of arguments. + ## class `CommandRunFailedException` Used when a command run on a device does not return the `success` status. diff --git a/docs/panos-upgrade-assurance/api/firewall_proxy.md b/docs/panos-upgrade-assurance/api/firewall_proxy.md index bcf54a4..ef5cb26 100644 --- a/docs/panos-upgrade-assurance/api/firewall_proxy.md +++ b/docs/panos-upgrade-assurance/api/firewall_proxy.md @@ -7,21 +7,73 @@ custom_edit_url: null --- ## class `FirewallProxy` -Class representing a Firewall. +A proxy to the [Firewall][fw] class. -Proxy in this class means that it is between the *high level* -[`CheckFirewall`](/panos/docs/panos-upgrade-assurance/api/check_firewall#class-checkfirewall) class and a device itself. -Inherits the [Firewall][fw] class but adds methods to interpret XML API commands. The class constructor is also inherited -from the [Firewall][fw] class. +Proxy in this case means that this class is between the *high level* +[`CheckFirewall`](/panos/docs/panos-upgrade-assurance/api/check_firewall#class-checkfirewall) class and the +[`Firewall`][fw] class representing the device itself. +There is no inheritance between the [`Firewall`][fw] and [`FirewallProxy`][fwp] classes, but an object of the latter one +has access to all attributes of the former. All interaction with a device are read-only. Therefore, a less privileged user can be used. -All methods starting with `is_` check the state, they do not present any data besides simple `boolean`values. +All methods starting with `is_` check the state, they do not present any data besides simple `boolean` values. All methods starting with `get_` fetch data from a device by running a command and parsing the output. The return data type can be different depending on what kind of information is returned from a device. [fw]: https://pan-os-python.readthedocs.io/en/latest/module-firewall.html#module-panos.firewall +[fwp]: /panos/docs/panos-upgrade-assurance/api/firewall_proxy + +__Attributes__ + + +- `_fw (Firewall)`: an object of the [`Firewall`][fw] class. + +### `FirewallProxy.__init__` + +```python +def __init__(firewall: Optional[Firewall] = None, **kwargs) +``` + +Constructor of the [`FirewallProxy`][fwp] class. + +Main purpose of this constructor is to store an object of the [`Firewall`][fw] class. This can be done in two ways: + +1. by passing an existing object +1. by passing credentials and address of a device (all parameters used byt the [`Firewall`][fw] class constructor + are supported). + +:::tip +Please note that positional arguments are not supported. +::: + +__Parameters__ + + +- __firewall__ (`Firewall`): An existing object of the [`Firewall`][fw] class. +- __**kwargs__: Used to pass keyword arguments that will be used directly in the [`Firewall`][fw] class constructor. + +__Raises__ + + +- `WrongNumberOfArgumentsException`: Raised when a mixture of arguments is passed (for example a [`Firewall`][fw] + object and firewall credentials). + +### `FirewallProxy.__getattr__` + +```python +def __getattr__(attr) +``` + +An overload of the default `__getattr__()` method. + +Its main purpose is to provide backwards compatibility to the old [`FirewallProxy`][fwp] class structure. It's called +when a requested attribute does not exist in the [`FirewallProxy`][fwp] class object, and it tries to fetch it +from the [`Firewall`][fw] object stored within the [`FirewallProxy`][fwp] object. + +From the [`FirewallProxy`][fwp] object's interface perspective, this provides the same behaviour as if the +[`FirewallProxy`][fwp] would still inherit from the [`Firewall`][fw] class. ### `FirewallProxy.op_parser` diff --git a/docs/panos-upgrade-assurance/configuration_details.mdx b/docs/panos-upgrade-assurance/configuration_details.mdx index 0408b92..2f37841 100644 --- a/docs/panos-upgrade-assurance/configuration_details.mdx +++ b/docs/panos-upgrade-assurance/configuration_details.mdx @@ -71,7 +71,7 @@ Elements of this list can be either of the `str` or `dict` type: ```mdx-code-block - + ``` ```yaml @@ -106,7 +106,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml @@ -151,7 +151,7 @@ The [`CheckFirewall.run_readiness_checks()`](/panos/docs/panos-upgrade-assurance ```mdx-code-block - + ``` ```yaml @@ -187,7 +187,7 @@ The [`CheckFirewall.run_readiness_checks()`](/panos/docs/panos-upgrade-assurance ```mdx-code-block - + ``` ```yaml @@ -223,7 +223,7 @@ The [`CheckFirewall.run_readiness_checks()`](/panos/docs/panos-upgrade-assurance ```mdx-code-block - + ``` ```yaml @@ -290,7 +290,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml @@ -382,7 +382,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml showLineNumbers title="Lookup limited to a single interface" @@ -457,7 +457,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -510,7 +510,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -561,7 +561,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -607,7 +607,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -652,7 +652,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -700,7 +700,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -746,7 +746,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -816,7 +816,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -865,7 +865,7 @@ checks_configuration = [ ```mdx-code-block - + ``` ```yaml @@ -971,7 +971,7 @@ snapshots_config = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -1076,7 +1076,7 @@ reports = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -1154,7 +1154,7 @@ reports = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -1214,7 +1214,7 @@ reports = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -1267,7 +1267,7 @@ reports = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -1319,7 +1319,7 @@ reports = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -1377,7 +1377,7 @@ reports = [ ```mdx-code-block - + ``` ```yaml showLineNumbers @@ -1433,7 +1433,7 @@ reports = [ ```mdx-code-block - + ``` ```yaml showLineNumbers diff --git a/panos_upgrade_assurance/__init__.py b/panos_upgrade_assurance/__init__.py index e69de29..59ab523 100644 --- a/panos_upgrade_assurance/__init__.py +++ b/panos_upgrade_assurance/__init__.py @@ -0,0 +1,3 @@ +from importlib import metadata + +__version__ = metadata.version(__package__) diff --git a/panos_upgrade_assurance/exceptions.py b/panos_upgrade_assurance/exceptions.py index 29b7741..893e3ac 100644 --- a/panos_upgrade_assurance/exceptions.py +++ b/panos_upgrade_assurance/exceptions.py @@ -31,6 +31,14 @@ class UtilsException(Exception): pass +class WrongNumberOfArgumentsException(FirewallProxyException): + """Thrown when [FirewallProxy](/panos/docs/panos-upgrade-assurance/api/firewall_proxy) constructor is given wrong number or + set of arguments. + """ + + pass + + class CommandRunFailedException(FirewallProxyException): """Used when a command run on a device does not return the `success` status.""" diff --git a/panos_upgrade_assurance/firewall_proxy.py b/panos_upgrade_assurance/firewall_proxy.py index 1859f9a..ed71b19 100644 --- a/panos_upgrade_assurance/firewall_proxy.py +++ b/panos_upgrade_assurance/firewall_proxy.py @@ -9,24 +9,75 @@ from datetime import datetime -class FirewallProxy(Firewall): - """Class representing a Firewall. +class FirewallProxy: + """A proxy to the [Firewall][fw] class. - Proxy in this class means that it is between the *high level* - [`CheckFirewall`](/panos/docs/panos-upgrade-assurance/api/check_firewall#class-checkfirewall) class and a device itself. - Inherits the [Firewall][fw] class but adds methods to interpret XML API commands. The class constructor is also inherited - from the [Firewall][fw] class. + Proxy in this case means that this class is between the *high level* + [`CheckFirewall`](/panos/docs/panos-upgrade-assurance/api/check_firewall#class-checkfirewall) class and the + [`Firewall`][fw] class representing the device itself. + There is no inheritance between the [`Firewall`][fw] and [`FirewallProxy`][fwp] classes, but an object of the latter one + has access to all attributes of the former. All interaction with a device are read-only. Therefore, a less privileged user can be used. - All methods starting with `is_` check the state, they do not present any data besides simple `boolean`values. + All methods starting with `is_` check the state, they do not present any data besides simple `boolean` values. All methods starting with `get_` fetch data from a device by running a command and parsing the output. The return data type can be different depending on what kind of information is returned from a device. [fw]: https://pan-os-python.readthedocs.io/en/latest/module-firewall.html#module-panos.firewall + [fwp]: /panos/docs/panos-upgrade-assurance/api/firewall_proxy + + # Attributes + + _fw (Firewall): an object of the [`Firewall`][fw] class. + """ + def __init__(self, firewall: Optional[Firewall] = None, **kwargs): + """Constructor of the [`FirewallProxy`][fwp] class. + + Main purpose of this constructor is to store an object of the [`Firewall`][fw] class. This can be done in two ways: + + 1. by passing an existing object + 1. by passing credentials and address of a device (all parameters used byt the [`Firewall`][fw] class constructor + are supported). + + :::tip + Please note that positional arguments are not supported. + ::: + + # Parameters + + firewall (Firewall): An existing object of the [`Firewall`][fw] class. + **kwargs: Used to pass keyword arguments that will be used directly in the [`Firewall`][fw] class constructor. + + # Raises + + WrongNumberOfArgumentsException: Raised when a mixture of arguments is passed (for example a [`Firewall`][fw] + object and firewall credentials). + + """ + if firewall and len(kwargs) > 0: + raise exceptions.WrongNumberOfArgumentsException( + "You cannot pass the Firewall object and the credentials at the same time." + ) + + self._fw = firewall if firewall else Firewall(**kwargs) + + def __getattr__(self, attr): + """An overload of the default `__getattr__()` method. + + Its main purpose is to provide backwards compatibility to the old [`FirewallProxy`][fwp] class structure. It's called + when a requested attribute does not exist in the [`FirewallProxy`][fwp] class object, and it tries to fetch it + from the [`Firewall`][fw] object stored within the [`FirewallProxy`][fwp] object. + + From the [`FirewallProxy`][fwp] object's interface perspective, this provides the same behaviour as if the + [`FirewallProxy`][fwp] would still inherit from the [`Firewall`][fw] class. + + """ + return getattr(self._fw, attr) + def op_parser( self, cmd: str, diff --git a/pyproject.toml b/pyproject.toml index a294b9c..eafa2be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,15 +18,15 @@ classifiers = [ "Bug Tracker" = "https://github.com/PaloAltoNetworks/pan-os-upgrade-assurance/issues" [tool.poetry.dependencies] -python = "^3.8.1" +python = "^3.8" pan-os-python = "^1.8" pan-python = "^0.17" -xmltodict = "^0.13" +xmltodict = "^0.12" pyopenssl = "^23.2" [tool.poetry.group.dev.dependencies] pydoc-markdown = "^4.6" -flake8 = "^6.0" +flake8 = "^5" black = "^23.3" bandit = "^1.7" flake8-pyproject = "^1.2" diff --git a/tests/test_firewall_proxy.py b/tests/test_firewall_proxy.py index 402852f..7af9938 100644 --- a/tests/test_firewall_proxy.py +++ b/tests/test_firewall_proxy.py @@ -1,5 +1,6 @@ import pytest from unittest.mock import MagicMock +from panos.firewall import Firewall from panos_upgrade_assurance.firewall_proxy import FirewallProxy from xmltodict import parse as xml_parse import xml.etree.ElementTree as ET @@ -19,10 +20,10 @@ @pytest.fixture(scope="function") def fw_proxy_mock(): - fw_proxy_obj = FirewallProxy() - fw_proxy_obj.op = MagicMock() - fw_proxy_obj.generate_xapi = MagicMock() - fw_proxy_obj.xapi.get = MagicMock() + fw_proxy_obj = FirewallProxy(Firewall()) + fw_proxy_obj._fw.op = MagicMock() + fw_proxy_obj._fw.generate_xapi = MagicMock() + fw_proxy_obj._fw.xapi.get = MagicMock() yield fw_proxy_obj