Files
A-Team-Security-Infra-Agent…/backend/services/cis_reports.py
nogueiraguh 1135e9d6a9 refactor: decompose monolith — app.py 10,600→143 lines, 30+ modules
Fase 0 complete: extract all business logic, auth, database, and 176
endpoints from monolithic app.py into dedicated modules.

Structure:
- app.py: FastAPI hub (CORS, routers, startup/shutdown)
- models.py: 13 Pydantic request models
- utils.py: shared utilities (embed status, upload validation, process registries)
- config.py: constants, env vars, model catalogs
- auth/: crypto, jwt_auth, oidc, rate_limit
- database/: db(), init_db(), schema DDL
- services/: genai, compliance, chat, terraform, embeddings, cis_reports, mcp
- routes/: 13 APIRouter modules (auth, users, oci_config, oci_explorer,
  genai, mcp, adb, embeddings, reports, chat, terraform, settings, cis_engine)

Also: README updated with OCIR auth instructions for manual docker run.

86 tests passing.
2026-04-06 15:20:10 -03:00

81 lines
4.1 KiB
Python

"""CIS report execution — subprocess management."""
import os, json, uuid, asyncio
from pathlib import Path
from datetime import datetime
from config import OCI_DIR, REPORTS, log
from database import db
from auth.jwt_auth import _audit, _config_log
from utils import running_reports, classify_report_file
async def _exec_report(rid, cfg, regions, level=2, obp=False, raw=False, redact_output=False):
rdir = REPORTS / rid; rdir.mkdir(parents=True, exist_ok=True)
config_path = str(OCI_DIR / cfg["id"] / "config")
try:
cmd = ["python3", "-u", "/app/cis_reports.py",
"-c", config_path,
"--report-directory", str(rdir),
"--level", str(level),
"--print-to-screen", "True",
"--report-summary-json"]
if regions: cmd += ["--regions", ",".join(regions)]
if obp: cmd.append("--obp")
if raw: cmd.append("--raw")
if redact_output: cmd.append("--redact-output")
proc = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
running_reports[rid] = proc
with db() as c:
c.execute("UPDATE reports SET worker_pid=? WHERE id=?", (proc.pid, rid))
progress_lines = []
try:
while True:
line = await proc.stdout.readline()
if not line:
break
text = line.decode(errors="replace").strip()
if text:
progress_lines.append(text)
with db() as c:
c.execute("UPDATE reports SET progress=? WHERE id=?",
("\n".join(progress_lines[-50:]), rid))
await proc.wait()
finally:
running_reports.pop(rid, None)
stderr_data = await proc.stderr.read()
# Check if cancelled
with db() as c:
cur_status = c.execute("SELECT status FROM reports WHERE id=?", (rid,)).fetchone()
if cur_status and cur_status["status"] == "cancelled":
return
if proc.returncode == 0:
# Scan output directory for all generated files
html_path = None; json_path = None
with db() as c:
for fpath in rdir.iterdir():
if fpath.is_file():
fname = fpath.name
ftype = fpath.suffix.lstrip(".")
category = classify_report_file(fname)
fsize = fpath.stat().st_size
c.execute("INSERT INTO report_files (id,report_id,file_name,file_path,file_type,file_category,file_size) VALUES (?,?,?,?,?,?,?)",
(str(uuid.uuid4()), rid, fname, str(fpath), ftype, category, fsize))
if "summary_report" in fname and fname.endswith(".html"):
html_path = str(fpath)
elif "summary_report" in fname and fname.endswith(".json"):
json_path = str(fpath)
c.execute("UPDATE reports SET status='completed',progress=?,html_path=?,json_path=?,completed_at=datetime('now') WHERE id=?",
("\n".join(progress_lines), html_path, json_path, rid))
_config_log("oci", cfg["id"], cfg["tenancy_name"], "success", "report", f"Report completed: {rid}")
else:
err = (stderr_data.decode(errors="replace") if stderr_data else "Unknown")[:2000]
with db() as c:
c.execute("UPDATE reports SET status='failed',progress=?,error_msg=?,completed_at=datetime('now') WHERE id=?",
("\n".join(progress_lines), err, rid))
_config_log("oci", cfg["id"], cfg["tenancy_name"], "error", "report", err)
except Exception as e:
running_reports.pop(rid, None)
with db() as c:
c.execute("UPDATE reports SET status='failed',error_msg=?,completed_at=datetime('now') WHERE id=?", (str(e)[:2000], rid))
_config_log("oci", cfg["id"], cfg["tenancy_name"], "error", "report", str(e)[:2000])