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.
154 lines
5.2 KiB
Markdown
154 lines
5.2 KiB
Markdown
# Insight Updater - Project Prompt
|
|
|
|
## Overview
|
|
Build a self-hosted update orchestration tool for Windows (CAU/WSUS) and Linux servers via WinRM/SSH. Web UI to manage servers, trigger updates, monitor progress live via WebSocket.
|
|
|
|
## Target Stack
|
|
- **Backend**: FastAPI + Python 3.11+, SQLAlchemy + SQLite/PostgreSQL, structlog, python-winrm, paramiko
|
|
- **Frontend**: Vue 3 + TypeScript + Vite, Pinia, VueUse, Tailwind CSS, Socket.io client
|
|
- **Infra**: Docker Compose (backend, frontend, db, redis), Traefik labels for reverse proxy
|
|
- **CI/CD**: Gitea Actions / Woodpecker CI for build & deploy to monitoring (10.0.2.105)
|
|
|
|
## Core Features
|
|
1. **Server Inventory** - Add/edit/delete servers (Windows/WinRM, Linux/SSH, CAU-Cluster)
|
|
2. **Live Update Streaming** - WebSocket log stream with progress, status per node
|
|
3. **CAU Cluster Orchestration** - Trigger `Invoke-CauRun`, show per-node phases
|
|
4. **Linux Patch Management** - `apt/dnf/yum update` via SSH with sudo
|
|
5. **Audit Log** - Structured JSON logs: who, when, what server, outcome
|
|
5. **Health Checks** - `/health` endpoint, WinRM/SSH connectivity test
|
|
6. **LDAP-ready Auth** - JWT tokens, LDAP config schema prepared, local admin fallback
|
|
|
|
## Non-Goals
|
|
- No WSUS/SCCM replacement, no approval workflows
|
|
- No agent deployment (agentless WinRM/SSH only)
|
|
- No multi-tenancy / RBAC beyond admin/user
|
|
|
|
## Success Criteria
|
|
- Add server → see "Online/Offline", last patch date
|
|
- Click "Update" → live WebSocket log stream → final status Success/Failed
|
|
- CAU: Trigger cluster update, see per-node Pre/Post/Reboot phases
|
|
- Linux: Add SSH creds, trigger update, see apt/dnf output
|
|
- `docker compose up -d` → all healthy in <5 min on fresh VM
|
|
- Deploy to monitoring (10.0.2.105) via `git push` + CI works
|
|
- LDAP config schema exists, service stub wired, functional later
|
|
|
|
## Verification Commands
|
|
```bash
|
|
curl -f http://localhost:8000/health
|
|
curl -f http://localhost:3000/ # frontend
|
|
docker compose ps # all healthy
|
|
```
|
|
|
|
## Deployment Target
|
|
- **Host**: monitoring.insight.local (10.0.2.105)
|
|
- **User**: b0rbor4d (sudo via Vaultwarden)
|
|
- **Docker**: Podman/Docker Compose v2
|
|
- **Reverse Proxy**: Traefik (labels on compose services)
|
|
- **Git Remote**: ssh://git@gitea.insight-it.de:2222/b0rbor4d/insight-updater.git
|
|
|
|
## Security
|
|
- Credentials encrypted at rest (Fernet/AES-GCM, key from env)
|
|
- WinRM: NTLM/Kerberos, HTTPS preferred, Cert validation configurable
|
|
- SSH: Key-based auth preferred, password fallback encrypted
|
|
- JWT: RS256, short expiry, refresh token rotation
|
|
- Audit log: immutable append-only (SQLite WAL / PG)
|
|
|
|
## Project Structure
|
|
```
|
|
~/projects/insight-updater/
|
|
├── backend/
|
|
│ ├── app/
|
|
│ │ ├── api/ # FastAPI routes
|
|
│ │ ├── core/ # config, security, db
|
|
│ │ ├── models/ # SQLAlchemy models
|
|
│ │ ├── schemas/ # Pydantic schemas
|
|
│ │ ├── services/ # business logic (winrm, ssh, cau, audit)
|
|
│ │ ├── websocket/ # Socket.io / FastAPI WS handlers
|
|
│ │ └── main.py
|
|
│ ├── tests/
|
|
│ ├── Dockerfile
|
|
│ ├── requirements.txt
|
|
│ └── pyproject.toml
|
|
├── frontend/
|
|
│ ├── src/
|
|
│ │ ├── components/
|
|
│ │ ├── views/
|
|
│ │ ├── stores/
|
|
│ │ ├── api/
|
|
│ │ └── main.ts
|
|
│ ├── Dockerfile
|
|
│ ├── package.json
|
|
│ └── vite.config.ts
|
|
├── docker-compose.yml
|
|
├── docker-compose.prod.yml
|
|
├── .env.example
|
|
├── .gitignore
|
|
├── README.md
|
|
├── AGENTS.md
|
|
└── PROMPT.md
|
|
```
|
|
|
|
## Key Libraries
|
|
- `fastapi`, `uvicorn`, `sqlalchemy[asyncio]`, `alembic`
|
|
- `python-winrm[kerberos]`, `paramiko`, `asyncssh`
|
|
- `python-socketio[asyncio]`, `redis`, `structlog`
|
|
- `cryptography`, `python-jose[cryptography]`, `passlib[bcrypt]`
|
|
- `pydantic-settings`, `pydantic[email]`
|
|
- `pytest`, `pytest-asyncio`, `httpx`
|
|
|
|
## Environment Variables (.env.example)
|
|
```env
|
|
# Core
|
|
APP_ENV=development
|
|
SECRET_KEY=change-me-32-chars-min
|
|
ENCRYPTION_KEY=change-me-32-chars-base64
|
|
JWT_ALGORITHM=RS256
|
|
JWT_PRIVATE_KEY_PATH=/app/keys/private.pem
|
|
JWT_PUBLIC_KEY_PATH=/app/keys/public.pem
|
|
|
|
# Database
|
|
DATABASE_URL=sqlite+aiosqlite:///./data/app.db
|
|
# DATABASE_URL=postgresql+asyncpg://user:pass@db:5432/updater
|
|
|
|
# Redis
|
|
REDIS_URL=redis://redis:6379/0
|
|
|
|
# WinRM
|
|
WINRM_TRANSPORT=ntlm
|
|
WINRM_CERT_VALIDATION=ignore
|
|
|
|
# LDAP (stub)
|
|
LDAP_ENABLED=false
|
|
LDAP_URI=ldaps://dc.insight.local:636
|
|
LDAP_BIND_DN=CN=svc_updater,OU=Services,DC=insight,DC=local
|
|
LDAP_BIND_PASSWORD=
|
|
LDAP_USER_SEARCH_BASE=OU=Users,DC=insight,DC=local
|
|
LDAP_USER_FILTER=(sAMAccountName={username})
|
|
|
|
# Frontend
|
|
VITE_API_URL=http://localhost:8000
|
|
VITE_WS_URL=ws://localhost:8000
|
|
```
|
|
|
|
## Development Workflow
|
|
```bash
|
|
# Local dev
|
|
cd backend && pip install -e . && uvicorn app.main:app --reload
|
|
cd frontend && npm install && npm run dev
|
|
|
|
# Docker dev
|
|
docker compose up -d --build
|
|
|
|
# Tests
|
|
cd backend && pytest
|
|
cd frontend && npm run test
|
|
```
|
|
|
|
## Remote Deploy (monitoring)
|
|
```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
|
|
``` |