From f84f16fcd6d2549213902683e9678dd33a3cbdde Mon Sep 17 00:00:00 2001 From: Dmitrii Iurco Date: Sat, 6 Jun 2026 05:54:17 -0400 Subject: [PATCH] fix: add /api/network/dns/corefile endpoint and per-line iptables check The e2e tests were reading a stale Corefile at a hardcoded fallback path (/home/roof/pic/config/dns/Corefile) instead of the live one written by the API (/opt/pic/config/dns/Corefile on pic1). Adding a proper API endpoint eliminates the path ambiguity. The iptables test was checking whether peer_ip, DROP, and dpt:80 appeared anywhere in the full multi-line output rather than on the same rule line, producing false positives. Now checks per line. Co-Authored-By: Claude Sonnet 4.6 --- api/routes/network.py | 17 ++++++++++++++++- tests/e2e/api/test_peer_access_update.py | 5 ++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/api/routes/network.py b/api/routes/network.py index 6a2c704..7df2f3d 100644 --- a/api/routes/network.py +++ b/api/routes/network.py @@ -1,5 +1,6 @@ import logging -from flask import Blueprint, request, jsonify +import os +from flask import Blueprint, request, jsonify, Response logger = logging.getLogger('picell') bp = Blueprint('network', __name__) @@ -99,6 +100,20 @@ def get_dns_status(): logger.error(f"Error getting DNS status: {e}") return jsonify({"error": str(e)}), 500 +@bp.route('/api/network/dns/corefile', methods=['GET']) +def get_corefile(): + try: + from app import COREFILE_PATH + with open(COREFILE_PATH, 'r') as f: + content = f.read() + return Response(content, mimetype='text/plain') + except FileNotFoundError: + return Response('', mimetype='text/plain'), 404 + except Exception as e: + logger.error(f"Error reading Corefile: {e}") + return jsonify({"error": str(e)}), 500 + + @bp.route('/api/network/test', methods=['POST']) def test_network(): try: diff --git a/tests/e2e/api/test_peer_access_update.py b/tests/e2e/api/test_peer_access_update.py index 8002bfa..86011c9 100644 --- a/tests/e2e/api/test_peer_access_update.py +++ b/tests/e2e/api/test_peer_access_update.py @@ -85,7 +85,10 @@ class TestServiceAccessUpdate: if not rules: return # can't verify without iptables access — skip silently # No Caddy-targeted DROP for this peer; service blocking is DNS-ACL only - caddy_drop = f'{peer_ip}' in rules and 'DROP' in rules and 'dpt:80' in rules + caddy_drop = any( + peer_ip in line and 'DROP' in line and 'dpt:80' in line + for line in rules.splitlines() + ) assert not caddy_drop, ( f'Found Caddy DROP rule for {peer_ip} after service_access=[] — ' f'this blocks the PIC UI. Service access should be DNS-ACL only.\n{rules}'