import os import logging from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from database import get_db from utils.auth import verify_token from services import generator, process, config logger = logging.getLogger(__name__) router = APIRouter(dependencies=[Depends(verify_token)]) @router.post("/server/configure") def configure_server(db: Session = Depends(get_db)): try: # Generate to a temporary location or standard location # As per plan, we behave like srvconf output_path = "/etc/openvpn/server.conf" # Unprivileged service: render to the staging dir, the root helper validates and installs it if not process.is_container() and os.geteuid() != 0: staged = os.path.join(os.getenv("OVPMON_STAGING_DIR", "/var/lib/ovpmon/staging"), "server.conf") os.makedirs(os.path.dirname(staged), exist_ok=True) generator.generate_server_config(db, output_path=staged) ok, msg = process.install_config() if not ok: raise HTTPException(status_code=400, detail=f"Configuration rejected: {msg}") ok, msg = process.publish_crl() if not ok: if config.get_system_settings(db).crl_verify: raise HTTPException(status_code=500, detail=f"Configuration installed, but CRL publishing failed: {msg}") logger.warning(f"[SERVER] CRL not published (crl_verify is off): {msg}") return {"message": "Server configuration generated", "path": output_path} # Ensure we can write to /etc/openvpn if not os.path.exists(os.path.dirname(output_path)) or not os.access(os.path.dirname(output_path), os.W_OK): # For local dev or non-root host, use staging output_path = "staging/server.conf" os.makedirs("staging", exist_ok=True) logger.info(f"[SERVER] /etc/openvpn not writable, using staging path: {output_path}") else: os.makedirs(os.path.dirname(output_path), exist_ok=True) content = generator.generate_server_config(db, output_path=output_path) return {"message": "Server configuration generated", "path": output_path} except HTTPException: raise except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) except Exception as e: raise HTTPException(status_code=500, detail=str(e))