fix(telefoni): accept callbacks via db whitelist and internal fallback

This commit is contained in:
Christian 2026-05-16 13:16:35 +02:00
parent 8e5b3cf3d2
commit 6a68aecafa
3 changed files with 34 additions and 1 deletions

6
RELEASE_NOTES_v2.3.6.md Normal file
View File

@ -0,0 +1,6 @@
# Release Notes v2.3.6 — 16. maj 2026
## Telefoni Callback Fix
- telefoni callbacks now use both env and DB whitelist
- added internal 172.16.0.0/12 fallback acceptance
- added migration `migrations/186_telefoni_ip_whitelist_setting.sql`

View File

@ -122,11 +122,23 @@ def _is_internal_bmc_ip(client_ip: str) -> bool:
return ip_obj in ipaddress.ip_network("172.16.31.0/24") return ip_obj in ipaddress.ip_network("172.16.31.0/24")
def _is_internal_bmc_supernet_ip(client_ip: str) -> bool:
if not client_ip:
return False
try:
ip_obj = ipaddress.ip_address(client_ip)
except ValueError:
return False
return ip_obj in ipaddress.ip_network("172.16.0.0/12")
def _validate_yealink_request(request: Request, token: Optional[str]) -> None: def _validate_yealink_request(request: Request, token: Optional[str]) -> None:
env_secret = (getattr(settings, "TELEFONI_SHARED_SECRET", "") or "").strip() env_secret = (getattr(settings, "TELEFONI_SHARED_SECRET", "") or "").strip()
db_secret = (_get_setting_value("telefoni_shared_secret", "") or "").strip() db_secret = (_get_setting_value("telefoni_shared_secret", "") or "").strip()
accepted_tokens = {s for s in (env_secret, db_secret) if s} accepted_tokens = {s for s in (env_secret, db_secret) if s}
whitelist = (getattr(settings, "TELEFONI_IP_WHITELIST", "") or "").strip() env_whitelist = (getattr(settings, "TELEFONI_IP_WHITELIST", "") or "").strip()
db_whitelist = (_get_setting_value("telefoni_ip_whitelist", "") or "").strip()
whitelist = ",".join([part for part in (env_whitelist, db_whitelist) if part])
client_ip = _get_client_ip(request) client_ip = _get_client_ip(request)
path = request.url.path path = request.url.path
@ -174,6 +186,15 @@ def _validate_yealink_request(request: Request, token: Optional[str]) -> None:
else: else:
logger.info(" Telefoni callback whitelist not configured path=%s ip=%s", path, client_ip) logger.info(" Telefoni callback whitelist not configured path=%s ip=%s", path, client_ip)
# Safety fallback: allow callbacks from internal BMC network range.
if _is_internal_bmc_supernet_ip(client_ip):
logger.warning(
"⚠️ Telefoni callback accepted via internal supernet fallback path=%s ip=%s",
path,
client_ip,
)
return
logger.warning("❌ Telefoni callback forbidden path=%s ip=%s", path, client_ip) logger.warning("❌ Telefoni callback forbidden path=%s ip=%s", path, client_ip)
raise HTTPException(status_code=403, detail="Forbidden") raise HTTPException(status_code=403, detail="Forbidden")

View File

@ -0,0 +1,6 @@
-- Migration 186: Telefoni callback IP whitelist setting
INSERT INTO settings (key, value, category, description, value_type, is_public)
VALUES
('telefoni_ip_whitelist', '', 'telefoni', 'CSV med tilladte callback IP/CIDR til Yealink callbacks', 'string', false)
ON CONFLICT (key) DO NOTHING;