config manager server

main
Kar 2025-04-29 13:43:38 +00:00
parent f4d353a707
commit 7dded4d9a2
1 changed files with 107 additions and 0 deletions

107
wg_api.py Normal file
View File

@ -0,0 +1,107 @@
import subprocess
import base64
from fastapi import FastAPI, Form, HTTPException, Query, Header, Depends
from fastapi.responses import JSONResponse
from pathlib import Path
import uvicorn
from dotenv import load_dotenv
import os
# Load environment variables
load_dotenv()
API_KEY_ENV = os.getenv("API_KEY")
WG_DIR = Path("/etc/wireguard")
SCRIPT_PATH = Path("/etc/wireguard/wg_config.sh")
app = FastAPI()
# Dependency to enforce API key
def verify_api_key(x_api_key: str = Header(...)):
if x_api_key != API_KEY_ENV:
raise HTTPException(status_code=403, detail="Invalid API key")
def is_valid_name(name):
return name.isalnum()
@app.post("/vpn")
async def create_vpn_client(
new: str = Form(...),
auth: None = Depends(verify_api_key)
):
client_name = new.strip()
if not is_valid_name(client_name):
raise HTTPException(status_code=400, detail="Invalid client name")
client_dir = WG_DIR / client_name
conf_file = client_dir / f"{client_name}.conf"
png_file = client_dir / f"{client_name}.png"
if client_dir.exists():
return JSONResponse(status_code=409, content={"error": "Client already exists"})
try:
subprocess.run(
["bash", str(SCRIPT_PATH), "add", client_name],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
if not conf_file.exists() or not png_file.exists():
raise FileNotFoundError("Missing config or QR code after creation")
config_data = conf_file.read_text()
with open(png_file, "rb") as f:
qr_base64 = base64.b64encode(f.read()).decode("utf-8")
return {
"client": client_name,
"config": config_data,
"qr_base64": qr_base64
}
except subprocess.CalledProcessError as e:
raise HTTPException(status_code=500, detail=f"Script error: {e.stderr.decode()}")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.delete("/vpn")
async def remove_vpn_client(
remove: str = Query(...),
auth: None = Depends(verify_api_key)
):
client_name = remove.strip()
if not is_valid_name(client_name):
raise HTTPException(status_code=400, detail="Invalid client name")
client_dir = WG_DIR / client_name
if not client_dir.exists():
raise HTTPException(status_code=404, detail="Client not found")
try:
subprocess.run(
["bash", str(SCRIPT_PATH), "remove", client_name],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
return {"message": f"Client '{client_name}' removed."}
except subprocess.CalledProcessError as e:
raise HTTPException(status_code=500, detail=f"Script error: {e.stderr.decode()}")
@app.get("/vpn/list")
async def list_vpn_clients(auth: None = Depends(verify_api_key)):
clients = []
for dir in WG_DIR.iterdir():
if dir.is_dir():
conf = dir / f"{dir.name}.conf"
if conf.exists():
clients.append(dir.name)
return {"clients": clients}
if __name__ == "__main__":
uvicorn.run("wg_api:app", host="0.0.0.0", port=3000)