From 3f761532d79717ad92f9704eb3e738192ce4ab92 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 20:29:06 +0100 Subject: [PATCH 1/2] ci: pre-commit autoupdate (#1014) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.1 → v0.9.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.1...v0.9.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Guillaume Mulocher --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 42b0ce1cb..b0bf3c72d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - '' - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.1 + rev: v0.9.2 hooks: - id: ruff name: Run Ruff linter From 995943a6b047b93da263bc2cf8c2c1c41d0ea63a Mon Sep 17 00:00:00 2001 From: vitthalmagadum <122079046+vitthalmagadum@users.noreply.github.com> Date: Tue, 21 Jan 2025 06:30:25 +0530 Subject: [PATCH 2/2] feat(anta): Added the test case to verify the SNMP source interface for specified VRF (#870) * Added TC for SNMP source interface * issue_854 handling review comments: updated failure msgs * Issue_854: Fixed pre-commit issues * Issue_854: Refactored snmp source interface verification test with latest input model changes * Issue_854: Fixed docstrings * Minor fixes --------- Co-authored-by: VitthalMagadum Co-authored-by: Geetanjali.mane Co-authored-by: Carl Baillargeon --- anta/input_models/snmp.py | 20 ++++++++++- anta/tests/snmp.py | 56 ++++++++++++++++++++++++++++- examples/tests.yaml | 7 ++++ tests/units/anta_tests/test_snmp.py | 44 +++++++++++++++++++++++ 4 files changed, 125 insertions(+), 2 deletions(-) diff --git a/anta/input_models/snmp.py b/anta/input_models/snmp.py index bd7350e45..d408d9311 100644 --- a/anta/input_models/snmp.py +++ b/anta/input_models/snmp.py @@ -9,7 +9,7 @@ from pydantic import BaseModel, ConfigDict -from anta.custom_types import Hostname, SnmpEncryptionAlgorithm, SnmpHashingAlgorithm, SnmpVersion +from anta.custom_types import Hostname, Interface, SnmpEncryptionAlgorithm, SnmpHashingAlgorithm, SnmpVersion class SnmpHost(BaseModel): @@ -54,3 +54,21 @@ def __str__(self) -> str: - User: Test Group: Test_Group Version: v2c """ return f"User: {self.username} Group: {self.group_name} Version: {self.version}" + + +class SnmpSourceInterface(BaseModel): + """Model for a SNMP source-interface.""" + + interface: Interface + """Interface to use as the source IP address of SNMP messages.""" + vrf: str = "default" + """VRF of the source interface.""" + + def __str__(self) -> str: + """Return a human-readable string representation of the SnmpSourceInterface for reporting. + + Examples + -------- + - Source Interface: Ethernet1 VRF: default + """ + return f"Source Interface: {self.interface} VRF: {self.vrf}" diff --git a/anta/tests/snmp.py b/anta/tests/snmp.py index 910d5929c..84c5470e6 100644 --- a/anta/tests/snmp.py +++ b/anta/tests/snmp.py @@ -12,7 +12,7 @@ from pydantic import field_validator from anta.custom_types import PositiveInteger, SnmpErrorCounter, SnmpPdu -from anta.input_models.snmp import SnmpHost, SnmpUser +from anta.input_models.snmp import SnmpHost, SnmpSourceInterface, SnmpUser from anta.models import AntaCommand, AntaTest from anta.tools import get_value @@ -489,3 +489,57 @@ def test(self) -> None: if user.priv_type and (act_encryption := get_value(user_details, "v3Params.privType", "Not Found")) != user.priv_type: self.result.is_failure(f"{user} - Incorrect privacy type - Expected: {user.priv_type} Actual: {act_encryption}") + + +class VerifySnmpSourceInterface(AntaTest): + """Verifies SNMP source interfaces. + + This test performs the following checks: + + 1. Verifies that source interface(s) are configured for SNMP. + 2. For each specified source interface: + - Interface is configured in the specified VRF. + + Expected Results + ---------------- + * Success: The test will pass if the provided SNMP source interface(s) are configured in their specified VRF. + * Failure: The test will fail if any of the provided SNMP source interface(s) are NOT configured in their specified VRF. + + Examples + -------- + ```yaml + anta.tests.snmp: + - VerifySnmpSourceInterface: + interfaces: + - interface: Ethernet1 + vrf: default + - interface: Management0 + vrf: MGMT + ``` + """ + + categories: ClassVar[list[str]] = ["snmp"] + commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp", revision=1)] + + class Input(AntaTest.Input): + """Input model for the VerifySnmpSourceInterface test.""" + + interfaces: list[SnmpSourceInterface] + """List of source interfaces.""" + + @AntaTest.anta_test + def test(self) -> None: + """Main test function for VerifySnmpSourceInterface.""" + self.result.is_success() + command_output = self.instance_commands[0].json_output.get("srcIntf", {}) + + if not (interface_output := command_output.get("sourceInterfaces")): + self.result.is_failure("SNMP source interface(s) not configured") + return + + for interface_details in self.inputs.interfaces: + # If the source interface is not configured, or if it does not match the expected value, the test fails. + if not (actual_interface := interface_output.get(interface_details.vrf)): + self.result.is_failure(f"{interface_details} - Not configured") + elif actual_interface != interface_details.interface: + self.result.is_failure(f"{interface_details} - Incorrect source interface - Actual: {actual_interface}") diff --git a/examples/tests.yaml b/examples/tests.yaml index f47285a13..6c64f5d9f 100644 --- a/examples/tests.yaml +++ b/examples/tests.yaml @@ -793,6 +793,13 @@ anta.tests.snmp: pdus: - outTrapPdus - inGetNextPdus + - VerifySnmpSourceInterface: + # Verifies SNMP source interfaces. + interfaces: + - interface: Ethernet1 + vrf: default + - interface: Management0 + vrf: MGMT - VerifySnmpStatus: # Verifies if the SNMP agent is enabled. vrf: default diff --git a/tests/units/anta_tests/test_snmp.py b/tests/units/anta_tests/test_snmp.py index ebbf94897..fc30ad6ce 100644 --- a/tests/units/anta_tests/test_snmp.py +++ b/tests/units/anta_tests/test_snmp.py @@ -15,6 +15,7 @@ VerifySnmpIPv6Acl, VerifySnmpLocation, VerifySnmpPDUCounters, + VerifySnmpSourceInterface, VerifySnmpStatus, VerifySnmpUser, ) @@ -536,4 +537,47 @@ ], }, }, + { + "name": "success", + "test": VerifySnmpSourceInterface, + "eos_data": [ + { + "srcIntf": {"sourceInterfaces": {"default": "Ethernet1", "MGMT": "Management0"}}, + } + ], + "inputs": {"interfaces": [{"interface": "Ethernet1", "vrf": "default"}, {"interface": "Management0", "vrf": "MGMT"}]}, + "expected": {"result": "success"}, + }, + { + "name": "failure-not-configured", + "test": VerifySnmpSourceInterface, + "eos_data": [ + { + "srcIntf": {}, + } + ], + "inputs": {"interfaces": [{"interface": "Ethernet1", "vrf": "default"}, {"interface": "Management0", "vrf": "MGMT"}]}, + "expected": {"result": "failure", "messages": ["SNMP source interface(s) not configured"]}, + }, + { + "name": "failure-incorrect-interfaces", + "test": VerifySnmpSourceInterface, + "eos_data": [ + { + "srcIntf": { + "sourceInterfaces": { + "default": "Management0", + } + }, + } + ], + "inputs": {"interfaces": [{"interface": "Ethernet1", "vrf": "default"}, {"interface": "Management0", "vrf": "MGMT"}]}, + "expected": { + "result": "failure", + "messages": [ + "Source Interface: Ethernet1 VRF: default - Incorrect source interface - Actual: Management0", + "Source Interface: Management0 VRF: MGMT - Not configured", + ], + }, + }, ]