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.
150 lines
5.6 KiB
Markdown
150 lines
5.6 KiB
Markdown
# 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
|
|
```bash
|
|
# 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` \| `credssp`
|
|
- `LDAP_ENABLED` — `true`/`false` (stub)
|
|
|
|
## Testing
|
|
```bash
|
|
# 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`
|
|
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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**: `structlog` JSON, level from `LOG_LEVEL` env
|
|
- **Errors**: Custom exceptions in `core/exceptions.py`, mapped to HTTP in `main.py`
|
|
- **Async**: All I/O async (asyncpg, asyncssh, httpx)
|
|
- **Types**: Strict mypy, Pydantic v2, SQLAlchemy 2.0 |