cf7c29639c
Backend: config/db/security/logging core, SQLAlchemy models (Server, Credential, UpdateJob, UpdateLog, AuditLog, User), services (winrm, ssh, cau, audit, job_runner), REST API (auth, servers, updates, audit), Socket.io WebSocket layer. Frontend: Vue 3 + TS + Pinia + Tailwind, Views (Dashboard, Servers, Updates, Audit, Login), axios + socket.io-client, nginx prod config.
5.6 KiB
5.6 KiB
Insight Updater - Agent Orientation
Project Purpose
Self-hosted update orchestration for Windows (CAU/WSUS) and Linux servers via WinRM/SSH. Web UI to manage inventory, trigger updates, stream live progress via WebSocket.
Quick Start
# Local development
cd ~/projects/insight-updater
docker compose up -d --build
# Backend only
cd backend && pip install -e . && uvicorn app.main:app --reload
# Frontend only
cd frontend && npm install && npm run dev
Architecture Overview
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Frontend │────▶│ Backend │────▶│ Database │
│ (Vue 3) │ WS │ (FastAPI) │ │ (SQLite/ │
│ Port 3000 │◀─── │ Port 8000 │ │ PostgreSQL)│
└─────────────┘ └──────┬──────┘ └─────────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ WinRM │ │ SSH │ │ CAU │
│ Service │ │ Service │ │ Service │
└─────────┘ └─────────┘ └─────────┘
Key Directories
| Path | Purpose |
|---|---|
backend/app/api/ |
FastAPI route definitions (REST + WS) |
backend/app/core/ |
Config, security, database, logging |
backend/app/models/ |
SQLAlchemy ORM models |
backend/app/schemas/ |
Pydantic request/response models |
backend/app/services/ |
Business logic: winrm, ssh, cau, audit |
backend/app/websocket/ |
Socket.io handlers for live updates |
frontend/src/views/ |
Page components (Dashboard, Servers, Updates, Audit) |
frontend/src/components/ |
Reusable UI components |
frontend/src/stores/ |
Pinia stores (auth, servers, updates) |
frontend/src/api/ |
Axios/Socket.io client setup |
Core Models
| Model | Description |
|---|---|
Server |
Inventory item: Windows/WinRM, Linux/SSH, CAU-Cluster |
Credential |
Encrypted credentials (WinRM user/pass, SSH key/pass) |
UpdateJob |
One update execution: server, status, started_by, started_at, finished_at |
UpdateLog |
Streamed log lines per job (WebSocket → DB) |
AuditLog |
Immutable audit trail: user, action, target, result |
User |
Local admin or LDAP-mapped user |
Key Services
| Service | File | Responsibility |
|---|---|---|
WinRMService |
services/winrm.py |
Connect, run PS commands, stream output |
SSHService |
services/ssh.py |
Connect, run commands, sudo handling |
CAUService |
services/cau.py |
Invoke-CauRun, cluster status, node phases |
AuditService |
services/audit.py |
Structured logging to DB + JSON file |
EncryptionService |
core/security.py |
Fernet encrypt/decrypt credentials |
WebSocket Events
| Event | Direction | Payload |
|---|---|---|
job:start |
Server→Client | {job_id, server_id, type} |
job:log |
Server→Client | {job_id, line, timestamp, level} |
job:progress |
Server→Client | {job_id, percent, phase, node?} |
job:complete |
Server→Client | {job_id, status, duration} |
job:cancel |
Client→Server | {job_id} |
API Endpoints (Key)
| Method | Path | Description |
|---|---|---|
| GET | /api/servers |
List all servers |
| POST | /api/servers |
Create server |
| GET | /api/servers/{id}/health |
Test WinRM/SSH connectivity |
| POST | /api/updates/trigger |
Start update job |
| GET | /api/updates/{job_id}/logs |
Get job logs (REST fallback) |
| WS | /ws/updates |
Socket.io connection |
| GET | /api/audit |
Paginated audit log |
| POST | /api/auth/login |
JWT login |
| GET | /health |
Health check |
Environment Variables
See .env.example — key ones:
DATABASE_URL— SQLite (dev) or PostgreSQL (prod)SECRET_KEY— JWT signing (32+ chars)ENCRYPTION_KEY— Fernet key for credentials (32 bytes base64)WINRM_TRANSPORT—ntlm|kerberos|credsspLDAP_ENABLED—true/false(stub)
Testing
# Backend
cd backend && pytest -v
# Frontend
cd frontend && npm run test
# E2E (Playwright)
cd frontend && npm run test:e2e
Deployment
Target: monitoring (10.0.2.105)
User: b0rbor4d (sudo via Vaultwarden)
Reverse Proxy: Traefik (Docker labels)
Git Remote: ssh://git@gitea.insight-it.de:2222/b0rbor4d/insight-updater.git
# On monitoring host
git clone ssh://git@gitea.insight-it.de:2222/b0rbor4d/insight-updater.git
cd insight-updater
cp .env.example .env # fill secrets
docker compose -f docker-compose.prod.yml up -d --build
Useful Commands
# DB migrations
cd backend && alembic upgrade head
# Generate keys
openssl genrsa -out keys/private.pem 2048
openssl rsa -in keys/private.pem -pubout -out keys/public.pem
# Encrypt a test credential
python -c "from app.core.security import encrypt; print(encrypt('secret'))"
Conventions
- Language: German for user-facing text, English for code/comments
- Logging:
structlogJSON, level fromLOG_LEVELenv - Errors: Custom exceptions in
core/exceptions.py, mapped to HTTP inmain.py - Async: All I/O async (asyncpg, asyncssh, httpx)
- Types: Strict mypy, Pydantic v2, SQLAlchemy 2.0