Files

65 lines
2.3 KiB
Python

"""Exempt loopback addresses (127.0.0.1 / ::1) from Home Assistant's HTTP login-ban handling.
Home Assistant has no built-in way to whitelist an IP from the ``http`` ban
system. Local tools running on the same host (e.g. a VS Code session that
queries ``/api/config`` without a token) therefore show up as failed login
attempts from ``127.0.0.1`` and can eventually get localhost banned, which
would break legitimate local access.
This integration wraps ``process_wrong_login`` so that any request whose remote
address is a loopback address is silently ignored. External addresses are still
processed normally, so ``login_attempts_threshold`` protection stays intact.
"""
from __future__ import annotations
import logging
from ipaddress import ip_address
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType
_LOGGER = logging.getLogger(__name__)
DOMAIN = "loopback_ban_exempt"
# Modules that hold a reference to process_wrong_login (either the definition
# itself or an ``from ... import process_wrong_login``). All must be patched.
_TARGET_MODULES = (
"homeassistant.components.http.ban",
"homeassistant.components.auth.login_flow",
"homeassistant.components.websocket_api.auth",
)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Patch the ban handler to skip loopback addresses."""
from homeassistant.components.http import ban as ban_module
original = ban_module.process_wrong_login
async def process_wrong_login(request):
"""Ignore loopback, otherwise defer to the original handler."""
remote = getattr(request, "remote", None)
try:
if remote is not None and ip_address(remote).is_loopback:
return None
except ValueError:
pass
return await original(request)
patched = 0
for mod_path in _TARGET_MODULES:
try:
module = __import__(mod_path, fromlist=["process_wrong_login"])
except ImportError:
continue
if getattr(module, "process_wrong_login", None) is not None:
module.process_wrong_login = process_wrong_login
patched += 1
_LOGGER.info(
"Loopback ban exemption active (patched %s reference(s))", patched
)
return True