130 lines
3.8 KiB
Python
130 lines
3.8 KiB
Python
import os
|
|
import re
|
|
import subprocess
|
|
from typing import List
|
|
|
|
from fastapi import FastAPI, Form, HTTPException, Header, Request, Depends
|
|
from fastapi.responses import JSONResponse
|
|
from dotenv import load_dotenv
|
|
from slowapi import Limiter, _rate_limit_exceeded_handler
|
|
from slowapi.util import get_remote_address
|
|
from slowapi.errors import RateLimitExceeded
|
|
|
|
# Load .env variables
|
|
load_dotenv()
|
|
API_KEY = os.getenv("API_KEY")
|
|
WHITELISTED_IPS = os.getenv("WHITELISTED_IPS", "").split(",")
|
|
|
|
# Constants
|
|
VESTA_BIN = "/usr/local/hestia/bin"
|
|
DEFAULT_RATE_LIMIT = "10/minute"
|
|
|
|
# FastAPI setup
|
|
app = FastAPI()
|
|
limiter = Limiter(key_func=get_remote_address)
|
|
app.state.limiter = limiter
|
|
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
|
|
|
|
# ---------------------- Helpers ----------------------
|
|
|
|
def check_api_key(x_api_key: str = Header(...)):
|
|
if x_api_key != API_KEY:
|
|
raise HTTPException(status_code=403, detail="Invalid API key")
|
|
|
|
def check_whitelisted_ip(request: Request):
|
|
ip = request.client.host
|
|
if WHITELISTED_IPS and ip not in WHITELISTED_IPS:
|
|
raise HTTPException(status_code=403, detail="IP not allowed")
|
|
|
|
def valid_username(name: str):
|
|
return re.match(r"^[a-zA-Z0-9_]+$", name)
|
|
|
|
def run_cmd(cmd: List[str]):
|
|
try:
|
|
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
return result.stdout.strip()
|
|
except subprocess.CalledProcessError as e:
|
|
raise HTTPException(status_code=500, detail=f"Command error: {e.stderr.strip()}")
|
|
|
|
# ---------------------- Endpoints ----------------------
|
|
|
|
@app.post("/vesta/add-user")
|
|
@limiter.limit(DEFAULT_RATE_LIMIT)
|
|
async def add_user(
|
|
request: Request,
|
|
user: str = Form(...),
|
|
password: str = Form(...),
|
|
email: str = Form(...),
|
|
package: str = Form("default"),
|
|
auth: None = Depends(check_api_key),
|
|
_: None = Depends(check_whitelisted_ip)
|
|
):
|
|
if not valid_username(user):
|
|
raise HTTPException(status_code=400, detail="Invalid username")
|
|
|
|
cmd = [f"{VESTA_BIN}/v-add-user", user, password, email, package]
|
|
output = run_cmd(cmd)
|
|
return {"message": "User created", "output": output}
|
|
|
|
|
|
@app.post("/vesta/add-domain")
|
|
@limiter.limit(DEFAULT_RATE_LIMIT)
|
|
async def add_domain(
|
|
request: Request,
|
|
user: str = Form(...),
|
|
domain: str = Form(...),
|
|
ssl: bool = Form(False),
|
|
php: bool = Form(False),
|
|
auth: None = Depends(check_api_key),
|
|
_: None = Depends(check_whitelisted_ip)
|
|
):
|
|
if not valid_username(user):
|
|
raise HTTPException(status_code=400, detail="Invalid username")
|
|
|
|
cmd = [f"{VESTA_BIN}/v-add-web-domain", user, domain]
|
|
output = run_cmd(cmd)
|
|
|
|
ssl_out, php_out = None, None
|
|
|
|
if ssl:
|
|
ssl_cmd = [f"{VESTA_BIN}/v-add-web-domain-ssl", user, domain]
|
|
ssl_out = run_cmd(ssl_cmd)
|
|
|
|
if php:
|
|
php_cmd = [f"{VESTA_BIN}/v-add-web-php", user, domain]
|
|
php_out = run_cmd(php_cmd)
|
|
|
|
return {
|
|
"message": "Domain added",
|
|
"domain_output": output,
|
|
"ssl_output": ssl_out,
|
|
"php_output": php_out
|
|
}
|
|
|
|
# ---------------------- Launch ----------------------
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
uvicorn.run("hestia_runner:app", host="0.0.0.0", port=3001)
|
|
|
|
|
|
# .env
|
|
#API_KEY=your-secret-key
|
|
#WHITELISTED_IPS=127.0.0.1,192.168.1.10
|
|
|
|
# cd /root/hestia_runner/ && source .venv/bin/activate.fish && uvicorn hestia_runner:app --host 0.0.0.0 --port 1002
|
|
|
|
#curl -X POST http://your-server-ip:3001/vesta/add-user \
|
|
# -H "x-api-key: your_api_key_here" \
|
|
# -F "user=testuser" \
|
|
# -F "password=securepass123" \
|
|
# -F "email=test@example.com" \
|
|
# -F "package=default"
|
|
|
|
#curl -X POST http://your-server-ip:3001/vesta/add-domain \
|
|
# -H "x-api-key: your_api_key_here" \
|
|
# -F "user=testuser" \
|
|
# -F "domain=example.com" \
|
|
# -F "ssl=true" \
|
|
# -F "php=true"
|