feat: add netplan configuration models and backend API for applying netplan
All checks were successful
Build and Deploy MITM Webserver / build (push) Successful in 8s

This commit is contained in:
2025-11-22 23:25:39 +01:00
parent 9d8542a0a7
commit 0615d83134
3 changed files with 161 additions and 1 deletions

View File

@@ -0,0 +1,36 @@
from pydantic import BaseModel, Field
from typing import List, Dict, Optional
class Nameservers(BaseModel):
addresses: List[str] = Field(default_factory=list)
search: List[str] = Field(default_factory=list)
class EthernetConfig(BaseModel):
dhcp4: Optional[bool] = None
dhcp6: Optional[bool] = None
addresses: Optional[List[str]] = None
gateway4: Optional[str] = None
gateway6: Optional[str] = None
nameservers: Optional[Nameservers] = None
optional: Optional[bool] = None
class BridgeConfig(BaseModel):
interfaces: List[str] = Field(default_factory=list) # ["eth1", "eth2"]
dhcp4: Optional[bool] = None
dhcp6: Optional[bool] = None
addresses: Optional[List[str]] = None
gateway4: Optional[str] = None
gateway6: Optional[str] = None
nameservers: Optional[Nameservers] = None
parameters: Optional[dict] = None # allows spanning-tree, port-priority, forward-delay, etc.
optional: Optional[bool] = None
class NetworkConfig(BaseModel):
version: int = 2
renderer: Optional[str] = "networkd"
ethernets: Dict[str, EthernetConfig] = Field(default_factory=dict)
bridges: Dict[str, BridgeConfig] = Field(default_factory=dict)

View File

@@ -1,3 +1,6 @@
from asyncio import subprocess
from http.client import HTTPException
import src.Models.netplan as netplan
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
import os import os
@@ -25,4 +28,33 @@ def read_root():
@app.get("/api/nft/ruleset") @app.get("/api/nft/ruleset")
def read_root(): def read_root():
message = os.popen("sudo nft --json list ruleset").read().strip() message = os.popen("sudo nft --json list ruleset").read().strip()
return {"message": message} return {"message": message}
NETPLAN_FILE = "/etc/netplan/99-app.yaml"
@app.post("/netplan/apply")
def apply_netplan(config: netplan.NetworkConfig):
try:
data = {"network": config.dict(exclude_none=True)}
with open(NETPLAN_FILE, "w") as f:
yaml.dump(data, f, sort_keys=False)
# Safety: rollback if config breaks connectivity
result = subprocess.run(
["netplan", "try", "--timeout", "10"],
capture_output=True,
text=True,
)
if result.returncode != 0:
raise HTTPException(
status_code=500,
detail=f"Netplan failed: {result.stderr}"
)
return {"status": "ok", "output": result.stdout}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

92
start_dev.sh Executable file
View File

@@ -0,0 +1,92 @@
#!/bin/bash
set -e
# Kill children on exit
cleanup() {
echo
echo "🛑 Stopping dev environment…"
kill 0 2>/dev/null
}
trap cleanup EXIT
START_BE=true
START_FE=true
case "$1" in
backend|be)
START_FE=false
;;
frontend|fe)
START_BE=false
;;
"" )
# default → both
;;
* )
echo "❌ Unknown argument: $1"
echo "Usage:"
echo " ./dev.sh → start both"
echo " ./dev.sh be → start backend only"
echo " ./dev.sh fe → start frontend only"
exit 1
;;
esac
###############################
# Backend
###############################
if [ "$START_BE" = true ]; then
(
echo "🚀 Starting backend…"
cd backend || { echo "❌ backend folder missing"; exit 1; }
if [ ! -d venv ]; then
echo "⚙️ Creating virtual environment…"
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
fi
echo "📡 Backend at http://localhost:8000"
./venv/bin/uvicorn src.main:app --reload --host 0.0.0.0 --port 8000
) &
BE_PID=$!
else
echo "⏭ Skipping backend"
fi
###############################
# Frontend
###############################
if [ "$START_FE" = true ]; then
(
echo "🚀 Starting frontend…"
cd frontend || { echo "❌ frontend folder missing"; exit 1; }
if [ ! -d node_modules ]; then
echo "📦 Installing frontend dependencies…"
npm install
fi
echo "🌍 Frontend at http://localhost:5173"
npm run dev-local
) &
FE_PID=$!
else
echo "⏭ Skipping frontend"
fi
###############################
# Wait for both
###############################
echo
echo "💡 Dev environment running."
[ "$START_BE" = true ] && echo " Backend PID: $BE_PID"
[ "$START_FE" = true ] && echo " Frontend PID: $FE_PID"
echo " Press CTRL+C to stop everything."
echo
wait