Redact sensitive info from debug logs (#1069)

Redacts sensitive data when debug logging device responses such as mac,
location and usernames
This commit is contained in:
Steven B.
2024-07-17 18:57:09 +01:00
committed by GitHub
parent c19389f236
commit c4f015a2fb
11 changed files with 300 additions and 39 deletions

View File

@@ -87,7 +87,8 @@ import ipaddress
import logging
import socket
from collections.abc import Awaitable
from typing import Callable, Dict, Optional, Type, cast
from pprint import pformat as pf
from typing import Any, Callable, Dict, Optional, Type, cast
# When support for cpython older than 3.11 is dropped
# async_timeout can be replaced with asyncio.timeout
@@ -112,8 +113,10 @@ from kasa.exceptions import (
UnsupportedDeviceError,
)
from kasa.iot.iotdevice import IotDevice
from kasa.iotprotocol import REDACTORS as IOT_REDACTORS
from kasa.json import dumps as json_dumps
from kasa.json import loads as json_loads
from kasa.protocol import mask_mac, redact_data
from kasa.xortransport import XorEncryption
_LOGGER = logging.getLogger(__name__)
@@ -123,6 +126,12 @@ OnDiscoveredCallable = Callable[[Device], Awaitable[None]]
OnUnsupportedCallable = Callable[[UnsupportedDeviceError], Awaitable[None]]
DeviceDict = Dict[str, Device]
NEW_DISCOVERY_REDACTORS: dict[str, Callable[[Any], Any] | None] = {
"device_id": lambda x: "REDACTED_" + x[9::],
"owner": lambda x: "REDACTED_" + x[9::],
"mac": mask_mac,
}
class _DiscoverProtocol(asyncio.DatagramProtocol):
"""Implementation of the discovery protocol handler.
@@ -293,6 +302,8 @@ class Discover:
DISCOVERY_PORT_2 = 20002
DISCOVERY_QUERY_2 = binascii.unhexlify("020000010000000000000000463cb5d3")
_redact_data = True
@staticmethod
async def discover(
*,
@@ -484,7 +495,9 @@ class Discover:
f"Unable to read response from device: {config.host}: {ex}"
) from ex
_LOGGER.debug("[DISCOVERY] %s << %s", config.host, info)
if _LOGGER.isEnabledFor(logging.DEBUG):
data = redact_data(info, IOT_REDACTORS) if Discover._redact_data else info
_LOGGER.debug("[DISCOVERY] %s << %s", config.host, pf(data))
device_class = cast(Type[IotDevice], Discover._get_device_class(info))
device = device_class(config.host, config=config)
@@ -504,6 +517,7 @@ class Discover:
config: DeviceConfig,
) -> Device:
"""Get SmartDevice from the new 20002 response."""
debug_enabled = _LOGGER.isEnabledFor(logging.DEBUG)
try:
info = json_loads(data[16:])
except Exception as ex:
@@ -514,9 +528,17 @@ class Discover:
try:
discovery_result = DiscoveryResult(**info["result"])
except ValidationError as ex:
_LOGGER.debug(
"Unable to parse discovery from device %s: %s", config.host, info
)
if debug_enabled:
data = (
redact_data(info, NEW_DISCOVERY_REDACTORS)
if Discover._redact_data
else info
)
_LOGGER.debug(
"Unable to parse discovery from device %s: %s",
config.host,
pf(data),
)
raise UnsupportedDeviceError(
f"Unable to parse discovery from device: {config.host}: {ex}"
) from ex
@@ -551,7 +573,13 @@ class Discover:
discovery_result=discovery_result.get_dict(),
)
_LOGGER.debug("[DISCOVERY] %s << %s", config.host, info)
if debug_enabled:
data = (
redact_data(info, NEW_DISCOVERY_REDACTORS)
if Discover._redact_data
else info
)
_LOGGER.debug("[DISCOVERY] %s << %s", config.host, pf(data))
device = device_class(config.host, protocol=protocol)
di = discovery_result.get_dict()