Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(eos_validate_state): Added the validation for STUN client configurations #3898

Merged
merged 12 commits into from
Jun 7, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -544,3 +544,13 @@ virtual_source_nat_vrfs:
metadata:
platform: vEOS-lab
dns_domain: dc1.local
router_path_selection:
path_groups:
- name: Test_local_interface
id: 110
dynamic_peers:
enabled: true
- name: Test_stun_server_profile
id: 210
local_interfaces:
- name: Ethernet3
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,18 @@ anta.tests.software:
- v1.13.6
- v1.8.0
anta.tests.stun:
- VerifyStunClient:
result_overwrite:
custom_field: 'Source IPv4 Address: 172.18.3.2 Source Port: 4500'
stun_clients:
- source_address: 172.18.3.2
source_port: 4500
- VerifyStunClient:
result_overwrite:
custom_field: 'Source IPv4 Address: 100.64.3.2 Source Port: 4500'
stun_clients:
- source_address: 100.64.3.2
source_port: 4500
- VerifyStunClient:
stun_clients:
- public_address: 172.18.3.21
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,18 @@ anta.tests.software:
- v1.13.6
- v1.8.0
anta.tests.stun:
- VerifyStunClient:
result_overwrite:
custom_field: 'Source IPv4 Address: 172.18.4.2 Source Port: 4500'
stun_clients:
- source_address: 172.18.4.2
source_port: 4500
- VerifyStunClient:
result_overwrite:
custom_field: 'Source IPv4 Address: 100.64.4.2 Source Port: 4500'
stun_clients:
- source_address: 100.64.4.2
source_port: 4500
- VerifyStunClient:
stun_clients:
- public_address: 172.18.3.21
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,14 @@ custom_structured_configuration_router_bgp:
- ip_address: 10.1.1.1
description: External peer
peer_group: EVPN-OVERLAY-PEERS
# Custom router path selection structured_config to test negative case for STUN client testcase
custom_structured_configuration_router_path_selection:
path_groups:
- name: Test_local_interface
id: 110
dynamic_peers:
enabled: true
- name: Test_stun_server_profile
id: 210
local_interfaces:
- name: Ethernet3
2,808 changes: 1,406 additions & 1,402 deletions ansible_collections/arista/avd/molecule/eos_validate_state/reports/FABRIC-state.csv

Large diffs are not rendered by default.

2,816 changes: 1,410 additions & 1,406 deletions ansible_collections/arista/avd/molecule/eos_validate_state/reports/FABRIC-state.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,24 @@
],
"description": "Verifies the STUN client is configured with the specified IPv4 source address and port. Validate the public IP and port if provided."
},
{
"name": "dc1-wan1",
"test": "VerifyStunClient",
"categories": [
"stun"
],
"description": "Verifies the STUN client is configured with the specified IPv4 source address and port. Validate the public IP and port if provided.",
"custom_field": "Source IPv4 Address: 100.64.3.2 Source Port: 4500"
},
{
"name": "dc1-wan1",
"test": "VerifyStunClient",
"categories": [
"stun"
],
"description": "Verifies the STUN client is configured with the specified IPv4 source address and port. Validate the public IP and port if provided.",
"custom_field": "Source IPv4 Address: 172.18.3.2 Source Port: 4500"
},
{
"name": "dc1-wan1",
"test": "VerifyAgentLogs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,24 @@
],
"description": "Verifies the STUN client is configured with the specified IPv4 source address and port. Validate the public IP and port if provided."
},
{
"name": "dc1-wan2",
"test": "VerifyStunClient",
"categories": [
"stun"
],
"description": "Verifies the STUN client is configured with the specified IPv4 source address and port. Validate the public IP and port if provided.",
"custom_field": "Source IPv4 Address: 100.64.4.2 Source Port: 4500"
},
{
"name": "dc1-wan2",
"test": "VerifyStunClient",
"categories": [
"stun"
],
"description": "Verifies the STUN client is configured with the specified IPv4 source address and port. Validate the public IP and port if provided.",
"custom_field": "Source IPv4 Address: 172.18.4.2 Source Port: 4500"
},
{
"name": "dc1-wan2",
"test": "VerifyAgentLogs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ title: Ansible Collection Role eos_validate_state - Preview Integration with ANT
- (New) AvdTestIPSecurity (No Ansible tags, use the new `skipped_tests` variable instead)
- VerifySpecificIPSecConn: Validates the establishment of IP security connections for a peer within the default VRF. In its current state, the test validates only IPsec connections defined as static peers under the `router path-selection` section of the configuration.

- (New) AvdTestStun (No Ansible tags, use the new `skipped_tests` variable instead)
- VerifyStunClient: Validates the presence of a STUN client translation for a given source IPv4 address and port for WAN scenarios. The list of expected translations for each device is built by searching local interfaces in each path-group.

## Input variables

```yaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
AvdTestP2PIPReachability,
AvdTestReloadCause,
AvdTestRoutingTable,
AvdTestStun,
)

ACRONYM_CATEGORIES: set[str] = {"aaa", "mlag", "snmp", "bgp", "ospf", "vxlan", "stp", "igmp", "ip", "lldp", "ntp", "bfd", "ptp", "lanz", "stun", "vlan"}
Expand All @@ -38,6 +39,7 @@
AvdTestLoopback0Reachability: {"legacy_ansible_tags": ["loopback_reachability", "loopback0_reachability"]},
AvdTestAPIHttpsSSL: {},
AvdTestIPSecurity: {},
AvdTestStun: {},
}
"""
A dict of all AVD eos_validate_state test classes with their equivalent legacy Ansible tags.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .avdtestmlag import AvdTestMLAG
from .avdtestrouting import AvdTestBGP, AvdTestRoutingTable
from .avdtestsecurity import AvdTestAPIHttpsSSL, AvdTestIPSecurity
from .avdteststun import AvdTestStun
from .avdtestsystem import AvdTestNTP, AvdTestReloadCause

__all__ = [
Expand All @@ -22,5 +23,6 @@
"AvdTestRoutingTable",
"AvdTestBGP",
"AvdTestAPIHttpsSSL",
"AvdTestStun",
"AvdTestIPSecurity",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Copyright (c) 2023-2024 Arista Networks, Inc.
# Use of this source code is governed by the Apache License 2.0
# that can be found in the LICENSE file.
from __future__ import annotations

import logging
from functools import cached_property
from ipaddress import ip_interface

from ansible_collections.arista.avd.plugins.plugin_utils.eos_validate_state_utils.avdtestbase import AvdTestBase
from ansible_collections.arista.avd.plugins.plugin_utils.utils import get

LOGGER = logging.getLogger(__name__)


class AvdTestStun(AvdTestBase):
"""
AvdTestStun class for STUN tests.
Validates the presence of a STUN client translation for a given source IPv4 address and port for WAN scenarios.
The list of expected translations for each device is built by searching through router_path_selection.path_groups.local_interfaces.
"""

anta_module = "anta.tests.stun"

@cached_property
def test_definition(self) -> dict | None:
"""
Generates the proper ANTA test definition for all STUN tests.

Returns:
test_definition (dict): ANTA test definition.
"""
anta_tests = []

# Check if there are any path groups with STUN configuration
if (path_groups := get(self.structured_config, "router_path_selection.path_groups")) is None:
LOGGER.info("Path groups are not configured to collect STUN interfaces information. %s is skipped.", self.__class__.__name__)
return None

# Get the interfaces with STUN configuration
stun_interfaces = [
local_interfaces["name"]
for group_idx, path_group in enumerate(path_groups)
if self.validate_data(data=path_group, data_path=f"router_path_selection.path_groups.[{group_idx}]", required_keys="local_interfaces")
for interface_idx, local_interfaces in enumerate(path_group["local_interfaces"])
if self.validate_data(
data=local_interfaces,
data_path=f"router_path_selection.path_groups.[{group_idx}].local_interfaces.[{interface_idx}]",
required_keys="stun.server_profiles",
)
]
if not stun_interfaces:
LOGGER.info("No local interface found with STUN configuration. %s is skipped.", self.__class__.__name__)
return None

# Generate the ANTA tests for each identified local interface.
for source_interface in stun_interfaces:
if (ip_address := self.get_interface_ip("ethernet_interfaces", source_interface)) is None:
continue
source_address = str(ip_interface(ip_address).ip)
source_port = 4500
anta_tests.append(
{
"VerifyStunClient": {
"stun_clients": [{"source_address": source_address, "source_port": source_port}],
"result_overwrite": {"custom_field": f"Source IPv4 Address: {source_address} Source Port: {source_port}"},
}
}
)

# Return the ANTA tests as a dictionary
return {self.anta_module: anta_tests} if anta_tests else None
Loading