Skip to content

ANTA catalog for SNMP tests

Tests

Module related to the EOS various SNMP tests.

VerifySnmpContact

Verifies the SNMP contact of a device.

Expected Results
  • Success: The test will pass if the SNMP contact matches the provided input.
  • Failure: The test will fail if the SNMP contact does not match the provided input.
Examples
anta.tests.snmp:
  - VerifySnmpContact:
      contact: Jon@example.com

Inputs

Name Type Description Default
contact str
Expected SNMP contact details of the device.
-
Source code in anta/tests/snmp.py
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
class VerifySnmpContact(AntaTest):
    """Verifies the SNMP contact of a device.

    Expected Results
    ----------------
    * Success: The test will pass if the SNMP contact matches the provided input.
    * Failure: The test will fail if the SNMP contact does not match the provided input.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpContact:
          contact: Jon@example.com
    ```
    """

    categories: ClassVar[list[str]] = ["snmp"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifySnmpContact test."""

        contact: str
        """Expected SNMP contact details of the device."""

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpContact."""
        self.result.is_success()
        # Verifies the SNMP contact is configured.
        if not (contact := get_value(self.instance_commands[0].json_output, "contact.contact")):
            self.result.is_failure("SNMP contact is not configured")
            return

        # Verifies the expected SNMP contact.
        if contact != self.inputs.contact:
            self.result.is_failure(f"Incorrect SNMP contact - Expected: {self.inputs.contact} Actual: {contact}")

VerifySnmpErrorCounters

Verifies the SNMP error counters.

By default, all error counters will be checked for any non-zero values. An optional list of specific error counters can be provided for granular testing.

Expected Results
  • Success: The test will pass if the SNMP error counter(s) are zero/None.
  • Failure: The test will fail if the SNMP error counter(s) are non-zero/not None/Not Found or is not configured.
Examples

```yaml anta.tests.snmp: - VerifySnmpErrorCounters: error_counters: - inVersionErrs - inBadCommunityNames

Inputs

Name Type Description Default
error_counters list[SnmpErrorCounter] | None
Optional list of SNMP error counters to be verified. If not provided, test will verifies all error counters.
None
Source code in anta/tests/snmp.py
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
class VerifySnmpErrorCounters(AntaTest):
    """Verifies the SNMP error counters.

    By default, all  error counters will be checked for any non-zero values.
    An optional list of specific error counters can be provided for granular testing.

    Expected Results
    ----------------
    * Success: The test will pass if the SNMP error counter(s) are zero/None.
    * Failure: The test will fail if the SNMP error counter(s) are non-zero/not None/Not Found or is not configured.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpErrorCounters:
          error_counters:
            - inVersionErrs
            - inBadCommunityNames
    """

    categories: ClassVar[list[str]] = ["snmp"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifySnmpErrorCounters test."""

        error_counters: list[SnmpErrorCounter] | None = None
        """Optional list of SNMP error counters to be verified. If not provided, test will verifies all error counters."""

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpErrorCounters."""
        self.result.is_success()
        error_counters = self.inputs.error_counters
        command_output = self.instance_commands[0].json_output

        # Verify SNMP PDU counters.
        if not (snmp_counters := get_value(command_output, "counters")):
            self.result.is_failure("SNMP counters not found.")
            return

        # In case SNMP error counters not provided, It will check all the error counters.
        if not error_counters:
            error_counters = list(get_args(SnmpErrorCounter))

        error_counters_not_ok = {counter for counter in error_counters if snmp_counters.get(counter)}

        # Check if any failures
        if error_counters_not_ok:
            self.result.is_failure(f"The following SNMP error counters are not found or have non-zero error counters: {', '.join(sorted(error_counters_not_ok))}")

VerifySnmpGroup

Verifies the SNMP group configurations for specified version(s).

This test performs the following checks:

  1. Verifies that the SNMP group is configured for the specified version.
  2. For SNMP version 3, verify that the security model matches the expected value.
  3. Ensures that SNMP group configurations, including read, write, and notify views, align with version-specific requirements.
Expected Results
  • Success: The test will pass if the provided SNMP group and all specified parameters are correctly configured.
  • Failure: The test will fail if the provided SNMP group is not configured or if any specified parameter is not correctly configured.
Examples
anta.tests.snmp:
  - VerifySnmpGroup:
      snmp_groups:
        - group_name: Group1
          version: v1
          read_view: group_read_1
          write_view: group_write_1
          notify_view: group_notify_1
        - group_name: Group2
          version: v3
          read_view: group_read_2
          write_view: group_write_2
          notify_view: group_notify_2
          authentication: priv

Inputs

Name Type Description Default
snmp_groups list[SnmpGroup]
List of SNMP groups.
-
Source code in anta/tests/snmp.py
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
class VerifySnmpGroup(AntaTest):
    """Verifies the SNMP group configurations for specified version(s).

    This test performs the following checks:

      1. Verifies that the SNMP group is configured for the specified version.
      2. For SNMP version 3, verify that the security model matches the expected value.
      3. Ensures that SNMP group configurations, including read, write, and notify views, align with version-specific requirements.

    Expected Results
    ----------------
    * Success: The test will pass if the provided SNMP group and all specified parameters are correctly configured.
    * Failure: The test will fail if the provided SNMP group is not configured or if any specified parameter is not correctly configured.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpGroup:
          snmp_groups:
            - group_name: Group1
              version: v1
              read_view: group_read_1
              write_view: group_write_1
              notify_view: group_notify_1
            - group_name: Group2
              version: v3
              read_view: group_read_2
              write_view: group_write_2
              notify_view: group_notify_2
              authentication: priv
    ```
    """

    categories: ClassVar[list[str]] = ["snmp"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp group", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifySnmpGroup test."""

        snmp_groups: list[SnmpGroup]
        """List of SNMP groups."""

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpGroup."""
        self.result.is_success()
        for group in self.inputs.snmp_groups:
            # Verify SNMP group details.
            if not (group_details := get_value(self.instance_commands[0].json_output, f"groups.{group.group_name}.versions.{group.version}")):
                self.result.is_failure(f"{group} - Not configured")
                continue

            view_types = [view_type for view_type in ["read", "write", "notify"] if getattr(group, f"{view_type}_view")]
            # Verify SNMP views, the read, write and notify settings aligning with version-specific requirements.
            for view_type in view_types:
                expected_view = getattr(group, f"{view_type}_view")
                # Verify actual view is configured.
                if group_details.get(f"{view_type}View") == "":
                    self.result.is_failure(f"{group} View: {view_type} - Not configured")
                elif (act_view := group_details.get(f"{view_type}View")) != expected_view:
                    self.result.is_failure(f"{group} - Incorrect {view_type.title()} view - Expected: {expected_view} Actual: {act_view}")
                elif not group_details.get(f"{view_type}ViewConfig"):
                    self.result.is_failure(f"{group} {view_type.title()} View: {expected_view} - Not configured")

            # For version v3, verify that the security model aligns with the expected value.
            if group.version == "v3" and (actual_auth := group_details.get("secModel")) != group.authentication:
                self.result.is_failure(f"{group} - Incorrect security model - Expected: {group.authentication} Actual: {actual_auth}")

VerifySnmpHostLogging

Verifies SNMP logging configurations.

This test performs the following checks:

  1. SNMP logging is enabled globally.
  2. For each specified SNMP host:
    • Host exists in configuration.
    • Host’s VRF assignment matches expected value.
Expected Results
  • Success: The test will pass if all of the following conditions are met:
    • SNMP logging is enabled on the device.
    • All specified hosts are configured with correct VRF assignments.
  • Failure: The test will fail if any of the following conditions is met:
    • SNMP logging is disabled on the device.
    • SNMP host not found in configuration.
    • Host’s VRF assignment doesn’t match expected value.
Examples
anta.tests.snmp:
  - VerifySnmpHostLogging:
      hosts:
        - hostname: 192.168.1.100
          vrf: default
        - hostname: 192.168.1.103
          vrf: MGMT

Inputs

Name Type Description Default
hosts list[SnmpHost]
List of SNMP hosts.
-
Source code in anta/tests/snmp.py
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
class VerifySnmpHostLogging(AntaTest):
    """Verifies SNMP logging configurations.

    This test performs the following checks:

     1. SNMP logging is enabled globally.
     2. For each specified SNMP host:
         - Host exists in configuration.
         - Host's VRF assignment matches expected value.

    Expected Results
    ----------------
    * Success: The test will pass if all of the following conditions are met:
        - SNMP logging is enabled on the device.
        - All specified hosts are configured with correct VRF assignments.
    * Failure: The test will fail if any of the following conditions is met:
        - SNMP logging is disabled on the device.
        - SNMP host not found in configuration.
        - Host's VRF assignment doesn't match expected value.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpHostLogging:
          hosts:
            - hostname: 192.168.1.100
              vrf: default
            - hostname: 192.168.1.103
              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 VerifySnmpHostLogging test."""

        hosts: list[SnmpHost]
        """List of SNMP hosts."""

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpHostLogging."""
        self.result.is_success()

        command_output = self.instance_commands[0].json_output.get("logging", {})
        # If SNMP logging is disabled, test fails.
        if not command_output.get("loggingEnabled"):
            self.result.is_failure("SNMP logging is disabled")
            return

        host_details = command_output.get("hosts", {})

        for host in self.inputs.hosts:
            hostname = str(host.hostname)
            vrf = host.vrf
            actual_snmp_host = host_details.get(hostname, {})

            # If SNMP host is not configured on the device, test fails.
            if not actual_snmp_host:
                self.result.is_failure(f"{host} - Not configured")
                continue

            # If VRF is not matches the expected value, test fails.
            actual_vrf = "default" if (vrf_name := actual_snmp_host.get("vrf")) == "" else vrf_name
            if actual_vrf != vrf:
                self.result.is_failure(f"{host} - Incorrect VRF - Actual: {actual_vrf}")

VerifySnmpIPv4Acl

Verifies if the SNMP agent has IPv4 ACL(s) configured.

Expected Results
  • Success: The test will pass if the SNMP agent has the provided number of IPv4 ACL(s) in the specified VRF.
  • Failure: The test will fail if the SNMP agent has not the right number of IPv4 ACL(s) in the specified VRF.
Examples
anta.tests.snmp:
  - VerifySnmpIPv4Acl:
      number: 3
      vrf: default

Inputs

Name Type Description Default
number PositiveInteger
The number of expected IPv4 ACL(s).
-
vrf str
The name of the VRF in which to check for the SNMP agent. Defaults to `default` VRF.
'default'
Source code in anta/tests/snmp.py
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
class VerifySnmpIPv4Acl(AntaTest):
    """Verifies if the SNMP agent has IPv4 ACL(s) configured.

    Expected Results
    ----------------
    * Success: The test will pass if the SNMP agent has the provided number of IPv4 ACL(s) in the specified VRF.
    * Failure: The test will fail if the SNMP agent has not the right number of IPv4 ACL(s) in the specified VRF.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpIPv4Acl:
          number: 3
          vrf: default
    ```
    """

    categories: ClassVar[list[str]] = ["snmp"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp ipv4 access-list summary", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifySnmpIPv4Acl test."""

        number: PositiveInteger
        """The number of expected IPv4 ACL(s)."""
        vrf: str = "default"
        """The name of the VRF in which to check for the SNMP agent. Defaults to `default` VRF."""

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpIPv4Acl."""
        self.result.is_success()
        command_output = self.instance_commands[0].json_output
        ipv4_acl_list = command_output["ipAclList"]["aclList"]
        ipv4_acl_number = len(ipv4_acl_list)
        if ipv4_acl_number != self.inputs.number:
            self.result.is_failure(f"VRF: {self.inputs.vrf} - Incorrect SNMP IPv4 ACL(s) - Expected: {self.inputs.number} Actual: {ipv4_acl_number}")
            return

        not_configured_acl = [acl["name"] for acl in ipv4_acl_list if self.inputs.vrf not in acl["configuredVrfs"] or self.inputs.vrf not in acl["activeVrfs"]]

        if not_configured_acl:
            self.result.is_failure(f"VRF: {self.inputs.vrf} - Following SNMP IPv4 ACL(s) not configured or active: {', '.join(not_configured_acl)}")

VerifySnmpIPv6Acl

Verifies if the SNMP agent has IPv6 ACL(s) configured.

Expected Results
  • Success: The test will pass if the SNMP agent has the provided number of IPv6 ACL(s) in the specified VRF.
  • Failure: The test will fail if the SNMP agent has not the right number of IPv6 ACL(s) in the specified VRF.
Examples
anta.tests.snmp:
  - VerifySnmpIPv6Acl:
      number: 3
      vrf: default

Inputs

Name Type Description Default
number PositiveInteger
The number of expected IPv6 ACL(s).
-
vrf str
The name of the VRF in which to check for the SNMP agent. Defaults to `default` VRF.
'default'
Source code in anta/tests/snmp.py
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
class VerifySnmpIPv6Acl(AntaTest):
    """Verifies if the SNMP agent has IPv6 ACL(s) configured.

    Expected Results
    ----------------
    * Success: The test will pass if the SNMP agent has the provided number of IPv6 ACL(s) in the specified VRF.
    * Failure: The test will fail if the SNMP agent has not the right number of IPv6 ACL(s) in the specified VRF.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpIPv6Acl:
          number: 3
          vrf: default
    ```
    """

    categories: ClassVar[list[str]] = ["snmp"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp ipv6 access-list summary", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifySnmpIPv6Acl test."""

        number: PositiveInteger
        """The number of expected IPv6 ACL(s)."""
        vrf: str = "default"
        """The name of the VRF in which to check for the SNMP agent. Defaults to `default` VRF."""

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpIPv6Acl."""
        command_output = self.instance_commands[0].json_output
        self.result.is_success()
        ipv6_acl_list = command_output["ipv6AclList"]["aclList"]
        ipv6_acl_number = len(ipv6_acl_list)
        if ipv6_acl_number != self.inputs.number:
            self.result.is_failure(f"VRF: {self.inputs.vrf} - Incorrect SNMP IPv6 ACL(s) - Expected: {self.inputs.number} Actual: {ipv6_acl_number}")
            return

        acl_not_configured = [acl["name"] for acl in ipv6_acl_list if self.inputs.vrf not in acl["configuredVrfs"] or self.inputs.vrf not in acl["activeVrfs"]]

        if acl_not_configured:
            self.result.is_failure(f"VRF: {self.inputs.vrf} - Following SNMP IPv6 ACL(s) not configured or active: {', '.join(acl_not_configured)}")

VerifySnmpLocation

Verifies the SNMP location of a device.

Expected Results
  • Success: The test will pass if the SNMP location matches the provided input.
  • Failure: The test will fail if the SNMP location does not match the provided input.
Examples
anta.tests.snmp:
  - VerifySnmpLocation:
      location: New York

Inputs

Name Type Description Default
location str
Expected SNMP location of the device.
-
Source code in anta/tests/snmp.py
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
class VerifySnmpLocation(AntaTest):
    """Verifies the SNMP location of a device.

    Expected Results
    ----------------
    * Success: The test will pass if the SNMP location matches the provided input.
    * Failure: The test will fail if the SNMP location does not match the provided input.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpLocation:
          location: New York
    ```
    """

    categories: ClassVar[list[str]] = ["snmp"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifySnmpLocation test."""

        location: str
        """Expected SNMP location of the device."""

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpLocation."""
        self.result.is_success()
        # Verifies the SNMP location is configured.
        if not (location := get_value(self.instance_commands[0].json_output, "location.location")):
            self.result.is_failure("SNMP location is not configured")
            return

        # Verifies the expected SNMP location.
        if location != self.inputs.location:
            self.result.is_failure(f"Incorrect SNMP location - Expected: {self.inputs.location} Actual: {location}")

VerifySnmpNotificationHost

Verifies the SNMP notification host(s) (SNMP manager) configurations.

This test performs the following checks for each specified host:

  1. Verifies that the SNMP host(s) is configured on the device.
  2. Verifies that the notification type (“trap” or “inform”) matches the expected value.
  3. Ensures that UDP port provided matches the expected value.
  4. Ensures the following depending on SNMP version:
    • For SNMP version v1/v2c, a valid community string is set and matches the expected value.
    • For SNMP version v3, a valid user field is set and matches the expected value.
Expected Results
  • Success: The test will pass if all of the following conditions are met:
    • The SNMP host(s) is configured on the device.
    • The notification type (“trap” or “inform”) and UDP port match the expected value.
    • Ensures the following depending on SNMP version:
      • For SNMP version v1/v2c, a community string is set and it matches the expected value.
      • For SNMP version v3, a valid user field is set and matches the expected value.
  • Failure: The test will fail if any of the following conditions is met:
    • The SNMP host(s) is not configured on the device.
    • The notification type (“trap” or “inform”) or UDP port do not matches the expected value.
    • Ensures the following depending on SNMP version:
      • For SNMP version v1/v2c, a community string is not matches the expected value.
      • For SNMP version v3, an user field is not matches the expected value.
Examples
anta.tests.snmp:
  - VerifySnmpNotificationHost:
      notification_hosts:
        - hostname: spine
          vrf: default
          notification_type: trap
          version: v1
          udp_port: 162
          community_string: public
        - hostname: 192.168.1.100
          vrf: default
          notification_type: trap
          version: v3
          udp_port: 162
          user: public

Inputs

Name Type Description Default
notification_hosts list[SnmpHost]
List of SNMP host(s).
-
Source code in anta/tests/snmp.py
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
class VerifySnmpNotificationHost(AntaTest):
    """Verifies the SNMP notification host(s) (SNMP manager) configurations.

    This test performs the following checks for each specified host:

     1. Verifies that the SNMP host(s) is configured on the device.
     2. Verifies that the notification type ("trap" or "inform") matches the expected value.
     3. Ensures that UDP port provided matches the expected value.
     4. Ensures the following depending on SNMP version:
        - For SNMP version v1/v2c, a valid community string is set and matches the expected value.
        - For SNMP version v3, a valid user field is set and matches the expected value.

    Expected Results
    ----------------
    * Success: The test will pass if all of the following conditions are met:
        - The SNMP host(s) is configured on the device.
        - The notification type ("trap" or "inform") and UDP port match the expected value.
        - Ensures the following depending on SNMP version:
            - For SNMP version v1/v2c, a community string is set and it matches the expected value.
            - For SNMP version v3, a valid user field is set and matches the expected value.
    * Failure: The test will fail if any of the following conditions is met:
        - The SNMP host(s) is not configured on the device.
        - The notification type ("trap" or "inform") or UDP port do not matches the expected value.
        - Ensures the following depending on SNMP version:
            - For SNMP version v1/v2c, a community string is not matches the expected value.
            - For SNMP version v3, an user field is not matches the expected value.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpNotificationHost:
          notification_hosts:
            - hostname: spine
              vrf: default
              notification_type: trap
              version: v1
              udp_port: 162
              community_string: public
            - hostname: 192.168.1.100
              vrf: default
              notification_type: trap
              version: v3
              udp_port: 162
              user: public
    ```
    """

    categories: ClassVar[list[str]] = ["snmp"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp notification host", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifySnmpNotificationHost test."""

        notification_hosts: list[SnmpHost]
        """List of SNMP host(s)."""

        @field_validator("notification_hosts")
        @classmethod
        def validate_notification_hosts(cls, notification_hosts: list[SnmpHost]) -> list[SnmpHost]:
            """Validate that all required fields are provided in each SNMP Notification Host."""
            for host in notification_hosts:
                if host.version is None:
                    msg = f"{host}; 'version' field missing in the input"
                    raise ValueError(msg)
                if host.version in ["v1", "v2c"] and host.community_string is None:
                    msg = f"{host} Version: {host.version}; 'community_string' field missing in the input"
                    raise ValueError(msg)
                if host.version == "v3" and host.user is None:
                    msg = f"{host} Version: {host.version}; 'user' field missing in the input"
                    raise ValueError(msg)
            return notification_hosts

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpNotificationHost."""
        self.result.is_success()

        # If SNMP is not configured, test fails.
        if not (snmp_hosts := get_value(self.instance_commands[0].json_output, "hosts")):
            self.result.is_failure("No SNMP host is configured")
            return

        for host in self.inputs.notification_hosts:
            vrf = "" if host.vrf == "default" else host.vrf
            hostname = str(host.hostname)
            notification_type = host.notification_type
            version = host.version
            udp_port = host.udp_port
            community_string = host.community_string
            user = host.user
            default_value = "Not Found"

            host_details = next(
                (host for host in snmp_hosts if (host.get("hostname") == hostname and host.get("protocolVersion") == version and host.get("vrf") == vrf)), None
            )
            # If expected SNMP host is not configured with the specified protocol version, test fails.
            if not host_details:
                self.result.is_failure(f"{host} Version: {version} - Not configured")
                continue

            # If actual notification type does not match the expected value, test fails.
            if notification_type != (actual_notification_type := get_value(host_details, "notificationType", default_value)):
                self.result.is_failure(f"{host} - Incorrect notification type - Expected: {notification_type} Actual: {actual_notification_type}")

            # If actual UDP port does not match the expected value, test fails.
            if udp_port != (actual_udp_port := get_value(host_details, "port", default_value)):
                self.result.is_failure(f"{host} - Incorrect UDP port - Expected: {udp_port} Actual: {actual_udp_port}")

            user_found = user != (actual_user := get_value(host_details, "v3Params.user", default_value))
            version_user_check = (version == "v3", user_found)

            # If SNMP protocol version is v1 or v2c and actual community string does not match the expected value, test fails.
            if version in ["v1", "v2c"] and community_string != (actual_community_string := get_value(host_details, "v1v2cParams.communityString", default_value)):
                self.result.is_failure(f"{host} Version: {version} - Incorrect community string - Expected: {community_string} Actual: {actual_community_string}")

            # If SNMP protocol version is v3 and actual user does not match the expected value, test fails.
            elif all(version_user_check):
                self.result.is_failure(f"{host} Version: {version} - Incorrect user - Expected: {user} Actual: {actual_user}")

VerifySnmpPDUCounters

Verifies the SNMP PDU counters.

By default, all SNMP PDU counters will be checked for any non-zero values. An optional list of specific SNMP PDU(s) can be provided for granular testing.

Expected Results
  • Success: The test will pass if the SNMP PDU counter(s) are non-zero/greater than zero.
  • Failure: The test will fail if the SNMP PDU counter(s) are zero/None/Not Found.
Examples
anta.tests.snmp:
  - VerifySnmpPDUCounters:
      pdus:
        - outTrapPdus
        - inGetNextPdus

Inputs

Name Type Description Default
pdus list[SnmpPdu] | None
Optional list of SNMP PDU counters to be verified. If not provided, test will verifies all PDU counters.
None
Source code in anta/tests/snmp.py
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
class VerifySnmpPDUCounters(AntaTest):
    """Verifies the SNMP PDU counters.

    By default, all SNMP PDU counters will be checked for any non-zero values.
    An optional list of specific SNMP PDU(s) can be provided for granular testing.

    Expected Results
    ----------------
    * Success: The test will pass if the SNMP PDU counter(s) are non-zero/greater than zero.
    * Failure: The test will fail if the SNMP PDU counter(s) are zero/None/Not Found.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpPDUCounters:
          pdus:
            - outTrapPdus
            - inGetNextPdus
    ```
    """

    categories: ClassVar[list[str]] = ["snmp"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifySnmpPDUCounters test."""

        pdus: list[SnmpPdu] | None = None
        """Optional list of SNMP PDU counters to be verified. If not provided, test will verifies all PDU counters."""

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpPDUCounters."""
        self.result.is_success()
        snmp_pdus = self.inputs.pdus
        command_output = self.instance_commands[0].json_output

        # Verify SNMP PDU counters.
        if not (pdu_counters := get_value(command_output, "counters")):
            self.result.is_failure("SNMP counters not found")
            return

        # In case SNMP PDUs not provided, It will check all the update error counters.
        if not snmp_pdus:
            snmp_pdus = list(get_args(SnmpPdu))

        failures = {pdu for pdu in snmp_pdus if (value := pdu_counters.get(pdu, "Not Found")) == "Not Found" or value == 0}

        # Check if any failures
        if failures:
            self.result.is_failure(f"The following SNMP PDU counters are not found or have zero PDU counters: {', '.join(sorted(failures))}")

VerifySnmpSourceInterface

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
anta.tests.snmp:
  - VerifySnmpSourceInterface:
      interfaces:
        - interface: Ethernet1
          vrf: default
        - interface: Management0
          vrf: MGMT

Inputs

Name Type Description Default
interfaces list[SnmpSourceInterface]
List of source interfaces.
-
Source code in anta/tests/snmp.py
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
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}")

VerifySnmpStatus

Verifies if the SNMP agent is enabled.

Expected Results
  • Success: The test will pass if the SNMP agent is enabled in the specified VRF.
  • Failure: The test will fail if the SNMP agent is disabled in the specified VRF.
Examples
anta.tests.snmp:
  - VerifySnmpStatus:
      vrf: default

Inputs

Name Type Description Default
vrf str
The name of the VRF in which to check for the SNMP agent. Defaults to `default` VRF.
'default'
Source code in anta/tests/snmp.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class VerifySnmpStatus(AntaTest):
    """Verifies if the SNMP agent is enabled.

    Expected Results
    ----------------
    * Success: The test will pass if the SNMP agent is enabled in the specified VRF.
    * Failure: The test will fail if the SNMP agent is disabled in the specified VRF.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpStatus:
          vrf: default
    ```
    """

    categories: ClassVar[list[str]] = ["snmp"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifySnmpStatus test."""

        vrf: str = "default"
        """The name of the VRF in which to check for the SNMP agent. Defaults to `default` VRF."""

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpStatus."""
        self.result.is_success()
        command_output = self.instance_commands[0].json_output
        if not (command_output["enabled"] and self.inputs.vrf in command_output["vrfs"]["snmpVrfs"]):
            self.result.is_failure(f"VRF: {self.inputs.vrf} - SNMP agent disabled")

VerifySnmpUser

Verifies the SNMP user configurations.

This test performs the following checks for each specified user:

  1. User exists in SNMP configuration.
  2. Group assignment is correct.
  3. For SNMPv3 users only:
    • Authentication type matches (if specified)
    • Privacy type matches (if specified)
Expected Results
  • Success: If all of the following conditions are met:
    • All users exist with correct group assignments.
    • SNMPv3 authentication and privacy types match specified values.
  • Failure: If any of the following occur:
    • User not found in SNMP configuration.
    • Incorrect group assignment.
    • For SNMPv3: Mismatched authentication or privacy types.
Examples
anta.tests.snmp:
  - VerifySnmpUser:
      snmp_users:
        - username: test
          group_name: test_group
          version: v3
          auth_type: MD5
          priv_type: AES-128

Inputs

Name Type Description Default
snmp_users list[SnmpUser]
List of SNMP users.
-
Source code in anta/tests/snmp.py
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
class VerifySnmpUser(AntaTest):
    """Verifies the SNMP user configurations.

    This test performs the following checks for each specified user:

      1. User exists in SNMP configuration.
      2. Group assignment is correct.
      3. For SNMPv3 users only:
          - Authentication type matches (if specified)
          - Privacy type matches (if specified)

    Expected Results
    ----------------
    * Success: If all of the following conditions are met:
        - All users exist with correct group assignments.
        - SNMPv3 authentication and privacy types match specified values.
    * Failure: If any of the following occur:
        - User not found in SNMP configuration.
        - Incorrect group assignment.
        - For SNMPv3: Mismatched authentication or privacy types.

    Examples
    --------
    ```yaml
    anta.tests.snmp:
      - VerifySnmpUser:
          snmp_users:
            - username: test
              group_name: test_group
              version: v3
              auth_type: MD5
              priv_type: AES-128
    ```
    """

    categories: ClassVar[list[str]] = ["snmp"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp user", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifySnmpUser test."""

        snmp_users: list[SnmpUser]
        """List of SNMP users."""

        @field_validator("snmp_users")
        @classmethod
        def validate_snmp_users(cls, snmp_users: list[SnmpUser]) -> list[SnmpUser]:
            """Validate that 'auth_type' or 'priv_type' field is provided in each SNMPv3 user."""
            for user in snmp_users:
                if user.version == "v3" and not (user.auth_type or user.priv_type):
                    msg = f"{user} 'auth_type' or 'priv_type' field is required with 'version: v3'"
                    raise ValueError(msg)
            return snmp_users

    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifySnmpUser."""
        self.result.is_success()

        for user in self.inputs.snmp_users:
            # Verify SNMP user details.
            if not (user_details := get_value(self.instance_commands[0].json_output, f"usersByVersion.{user.version}.users.{user.username}")):
                self.result.is_failure(f"{user} - Not found")
                continue

            if user.group_name != (act_group := user_details.get("groupName", "Not Found")):
                self.result.is_failure(f"{user} - Incorrect user group - Actual: {act_group}")

            if user.version == "v3":
                if user.auth_type and (act_auth_type := get_value(user_details, "v3Params.authType", "Not Found")) != user.auth_type:
                    self.result.is_failure(f"{user} - Incorrect authentication type - Expected: {user.auth_type} Actual: {act_auth_type}")

                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}")

Input models

Module containing input models for SNMP tests.

SnmpGroup

Model for an SNMP group.

Name Type Description Default
group_name str
SNMP group name.
-
version SnmpVersion
SNMP protocol version.
-
read_view str | None
Optional field, View to restrict read access.
None
write_view str | None
Optional field, View to restrict write access.
None
notify_view str | None
Optional field, View to restrict notifications.
None
authentication SnmpVersionV3AuthType | None
SNMPv3 authentication settings. Required when version is v3. Can be provided in the `VerifySnmpGroup` test.
None

validate_inputs

validate_inputs() -> Self

Validate the inputs provided to the SnmpGroup class.

Source code in anta/input_models/snmp.py
112
113
114
115
116
117
118
@model_validator(mode="after")
def validate_inputs(self) -> Self:
    """Validate the inputs provided to the SnmpGroup class."""
    if self.version == "v3" and self.authentication is None:
        msg = f"{self!s}: `authentication` field is missing in the input"
        raise ValueError(msg)
    return self
Source code in anta/input_models/snmp.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
class SnmpGroup(BaseModel):
    """Model for an SNMP group."""

    group_name: str
    """SNMP group name."""
    version: SnmpVersion
    """SNMP protocol version."""
    read_view: str | None = None
    """Optional field, View to restrict read access."""
    write_view: str | None = None
    """Optional field, View to restrict write access."""
    notify_view: str | None = None
    """Optional field, View to restrict notifications."""
    authentication: SnmpVersionV3AuthType | None = None
    """SNMPv3 authentication settings. Required when version is v3. Can be provided in the `VerifySnmpGroup` test."""

    @model_validator(mode="after")
    def validate_inputs(self) -> Self:
        """Validate the inputs provided to the SnmpGroup class."""
        if self.version == "v3" and self.authentication is None:
            msg = f"{self!s}: `authentication` field is missing in the input"
            raise ValueError(msg)
        return self

    def __str__(self) -> str:
        """Return a human-readable string representation of the SnmpGroup for reporting.

        Examples
        --------
        - Group: Test_Group Version: v2c
        """
        return f"Group: {self.group_name} Version: {self.version}"

SnmpHost

Model for a SNMP host.

Name Type Description Default
hostname IPv4Address | Hostname
IPv4 address or Hostname of the SNMP notification host.
-
vrf str
Optional VRF for SNMP Hosts. If not provided, it defaults to `default`.
'default'
notification_type Literal['trap', 'inform']
Type of SNMP notification (trap or inform), it defaults to trap.
'trap'
version SnmpVersion | None
SNMP protocol version. Required field in the `VerifySnmpNotificationHost` test.
None
udp_port Port | int
UDP port for SNMP. If not provided then defaults to 162.
162
community_string str | None
Optional SNMP community string for authentication,required for SNMP version is v1 or v2c. Can be provided in the `VerifySnmpNotificationHost` test.
None
user str | None
Optional SNMP user for authentication, required for SNMP version v3. Can be provided in the `VerifySnmpNotificationHost` test.
None
Source code in anta/input_models/snmp.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class SnmpHost(BaseModel):
    """Model for a SNMP host."""

    model_config = ConfigDict(extra="forbid")
    hostname: IPv4Address | Hostname
    """IPv4 address or Hostname of the SNMP notification host."""
    vrf: str = "default"
    """Optional VRF for SNMP Hosts. If not provided, it defaults to `default`."""
    notification_type: Literal["trap", "inform"] = "trap"
    """Type of SNMP notification (trap or inform), it defaults to trap."""
    version: SnmpVersion | None = None
    """SNMP protocol version. Required field in the `VerifySnmpNotificationHost` test."""
    udp_port: Port | int = 162
    """UDP port for SNMP. If not provided then defaults to 162."""
    community_string: str | None = None
    """Optional SNMP community string for authentication,required for SNMP version is v1 or v2c. Can be provided in the `VerifySnmpNotificationHost` test."""
    user: str | None = None
    """Optional SNMP user for authentication, required for SNMP version v3. Can be provided in the `VerifySnmpNotificationHost` test."""

    def __str__(self) -> str:
        """Return a human-readable string representation of the SnmpHost for reporting.

        Examples
        --------
         - Host: 192.168.1.100  VRF: default
        """
        return f"Host: {self.hostname} VRF: {self.vrf}"

SnmpSourceInterface

Model for a SNMP source-interface.

Name Type Description Default
interface Interface
Interface to use as the source IP address of SNMP messages.
-
vrf str
VRF of the source interface.
'default'
Source code in anta/input_models/snmp.py
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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}"

SnmpUser

Model for a SNMP User.

Name Type Description Default
username str
SNMP user name.
-
group_name str
SNMP group for the user.
-
version SnmpVersion
SNMP protocol version.
-
auth_type SnmpHashingAlgorithm | None
User authentication algorithm. Can be provided in the `VerifySnmpUser` test.
None
priv_type SnmpEncryptionAlgorithm | None
User privacy algorithm. Can be provided in the `VerifySnmpUser` test.
None
Source code in anta/input_models/snmp.py
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class SnmpUser(BaseModel):
    """Model for a SNMP User."""

    model_config = ConfigDict(extra="forbid")
    username: str
    """SNMP user name."""
    group_name: str
    """SNMP group for the user."""
    version: SnmpVersion
    """SNMP protocol version."""
    auth_type: SnmpHashingAlgorithm | None = None
    """User authentication algorithm. Can be provided in the `VerifySnmpUser` test."""
    priv_type: SnmpEncryptionAlgorithm | None = None
    """User privacy algorithm. Can be provided in the `VerifySnmpUser` test."""

    def __str__(self) -> str:
        """Return a human-readable string representation of the SnmpUser for reporting.

        Examples
        --------
        - User: Test Group: Test_Group Version: v2c
        """
        return f"User: {self.username} Group: {self.group_name} Version: {self.version}"