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.middleware.cors import CORSMiddleware
import os
@@ -25,4 +28,33 @@ def read_root():
@app.get("/api/nft/ruleset")
def read_root():
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