Skip to content

Commit

Permalink
Make IPv4 and IPv6 parse errors raise an API error (#5282)
Browse files Browse the repository at this point in the history
* Make IPv4 and IPv6 parse errors raise an API error

Currently, IP address parsing errors lead to an execption which is not
handled by the `api_validate()` call. By using concrete IPv4 and IPv6
types and `vol.Coerce()` parsing errors are properly handled.

* ruff format

* ruff check
  • Loading branch information
agners authored Aug 30, 2024
1 parent c0e3537 commit 00d217b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 7 deletions.
23 changes: 16 additions & 7 deletions supervisor/api/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import asyncio
from collections.abc import Awaitable
from dataclasses import replace
from ipaddress import ip_address, ip_interface
from ipaddress import IPv4Address, IPv4Interface, IPv6Address, IPv6Interface
from typing import Any

from aiohttp import web
Expand Down Expand Up @@ -56,12 +56,21 @@
from ..host.const import AuthMethod, InterfaceType, WifiMode
from .utils import api_process, api_validate

_SCHEMA_IP_CONFIG = vol.Schema(
_SCHEMA_IPV4_CONFIG = vol.Schema(
{
vol.Optional(ATTR_ADDRESS): [vol.Coerce(ip_interface)],
vol.Optional(ATTR_ADDRESS): [vol.Coerce(IPv4Interface)],
vol.Optional(ATTR_METHOD): vol.Coerce(InterfaceMethod),
vol.Optional(ATTR_GATEWAY): vol.Coerce(ip_address),
vol.Optional(ATTR_NAMESERVERS): [vol.Coerce(ip_address)],
vol.Optional(ATTR_GATEWAY): vol.Coerce(IPv4Address),
vol.Optional(ATTR_NAMESERVERS): [vol.Coerce(IPv4Address)],
}
)

_SCHEMA_IPV6_CONFIG = vol.Schema(
{
vol.Optional(ATTR_ADDRESS): [vol.Coerce(IPv6Interface)],
vol.Optional(ATTR_METHOD): vol.Coerce(InterfaceMethod),
vol.Optional(ATTR_GATEWAY): vol.Coerce(IPv6Address),
vol.Optional(ATTR_NAMESERVERS): [vol.Coerce(IPv6Address)],
}
)

Expand All @@ -78,8 +87,8 @@
# pylint: disable=no-value-for-parameter
SCHEMA_UPDATE = vol.Schema(
{
vol.Optional(ATTR_IPV4): _SCHEMA_IP_CONFIG,
vol.Optional(ATTR_IPV6): _SCHEMA_IP_CONFIG,
vol.Optional(ATTR_IPV4): _SCHEMA_IPV4_CONFIG,
vol.Optional(ATTR_IPV6): _SCHEMA_IPV6_CONFIG,
vol.Optional(ATTR_WIFI): _SCHEMA_WIFI_CONFIG,
vol.Optional(ATTR_ENABLED): vol.Boolean(),
}
Expand Down
20 changes: 20 additions & 0 deletions tests/api/test_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,26 @@ async def test_api_network_interface_update_invalid(api_client: TestClient):
== "expected a list for dictionary value @ data['ipv4']['nameservers']. Got '1.1.1.1'"
)

resp = await api_client.post(
f"/network/interface/{TEST_INTERFACE_ETH_NAME}/update",
json={"ipv4": {"gateway": "invalid"}},
)
result = await resp.json()
assert (
result["message"]
== "expected IPv4Address for dictionary value @ data['ipv4']['gateway']. Got 'invalid'"
)

resp = await api_client.post(
f"/network/interface/{TEST_INTERFACE_ETH_NAME}/update",
json={"ipv6": {"gateway": "invalid"}},
)
result = await resp.json()
assert (
result["message"]
== "expected IPv6Address for dictionary value @ data['ipv6']['gateway']. Got 'invalid'"
)


async def test_api_network_wireless_scan(api_client: TestClient):
"""Test network manager api."""
Expand Down

0 comments on commit 00d217b

Please sign in to comment.