76 lines
3.0 KiB
Python
76 lines
3.0 KiB
Python
import json
|
|
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
from app.auth import get_current_agent
|
|
from app.scopes import has_scope_access, ALL_SCOPES
|
|
from app.models import get_rule, get_all_rules, get_all_ports, add_audit_log, set_rule
|
|
|
|
router = APIRouter(prefix="/api")
|
|
|
|
async def log_audit(request: Request, agent: str, scope: str):
|
|
ip_address = request.client.host if request.client else "unknown"
|
|
await add_audit_log(agent, scope, ip_address)
|
|
|
|
@router.get("/rules/{scope}")
|
|
async def get_scope_rules(scope: str, request: Request, agent: str = Depends(get_current_agent)):
|
|
if not has_scope_access(agent, scope):
|
|
await log_audit(request, agent, f"{scope} (FORBIDDEN)")
|
|
raise HTTPException(status_code=403, detail="Forbidden")
|
|
|
|
await log_audit(request, agent, scope)
|
|
rule = await get_rule(scope)
|
|
if not rule:
|
|
raise HTTPException(status_code=404, detail="Scope not found")
|
|
|
|
return rule
|
|
|
|
@router.get("/ports")
|
|
async def get_ports_registry(request: Request, agent: str = Depends(get_current_agent)):
|
|
if not has_scope_access(agent, "infra"):
|
|
await log_audit(request, agent, "ports (FORBIDDEN)")
|
|
raise HTTPException(status_code=403, detail="Forbidden: Requires infra scope")
|
|
|
|
await log_audit(request, agent, "ports")
|
|
ports = await get_all_ports()
|
|
return ports
|
|
|
|
@router.get("/search")
|
|
async def search_rules(q: str, request: Request, agent: str = Depends(get_current_agent)):
|
|
await log_audit(request, agent, f"search (q={q})")
|
|
|
|
all_rules = await get_all_rules()
|
|
results = {}
|
|
|
|
for scope in ALL_SCOPES:
|
|
if has_scope_access(agent, scope):
|
|
content = all_rules.get(scope, {})
|
|
# Basic string matching in JSON serialization
|
|
if q.lower() in json.dumps(content).lower():
|
|
results[scope] = content
|
|
|
|
return results
|
|
|
|
@router.patch("/rules/{scope}")
|
|
async def patch_scope_rules(scope: str, request: Request, agent: str = Depends(get_current_agent)):
|
|
if not has_scope_access(agent, scope):
|
|
await log_audit(request, agent, f"{scope} (WRITE FORBIDDEN)")
|
|
raise HTTPException(status_code=403, detail="Forbidden")
|
|
body = await request.json()
|
|
if not isinstance(body, dict):
|
|
raise HTTPException(status_code=400, detail="Body must be a JSON object")
|
|
existing = await get_rule(scope) or {}
|
|
existing.update(body)
|
|
await set_rule(scope, existing)
|
|
await log_audit(request, agent, f"{scope} (WRITE)")
|
|
return {"status": "ok", "scope": scope, "updated_keys": list(body.keys())}
|
|
|
|
@router.get("/context")
|
|
async def get_agent_context(request: Request, agent: str = Depends(get_current_agent)):
|
|
await log_audit(request, agent, "context (READ ALL)")
|
|
all_rules = await get_all_rules()
|
|
result = {}
|
|
for scope in ALL_SCOPES:
|
|
if has_scope_access(agent, scope):
|
|
result[scope] = all_rules.get(scope, {})
|
|
ports = await get_all_ports()
|
|
return {"agent": agent, "scopes": result, "ports": ports}
|