atlas-academy/docs/SECURITY.md
Atlas Developer 03829a38b2 feat: Atlas Academy — Odoo eLearning platform, full fusion
9-course Dutch e-learning platform fused onto atlasacademy.nl via Caddy
reverse proxy. Odoo 19 Community as course engine (website_slides), static
HTML for marketing front. Single Odoo account system.

- static/: 8 marketing pages (index, pricing, coaching, leerpad, over, shop, bisl, esf)
- backend/odoo_relay.py: lead relay Flask service (POST /academy-lead → Odoo CRM)
- caddy/academy.caddyfile: full Caddy config with Odoo proxy + auth rewrites
- docs/: ARCHITECTURE, USERFLOW, COURSES, DEPLOYMENT, SECURITY, ODOO

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 00:48:45 +02:00

108 lines
3.6 KiB
Markdown

# Security Model — Atlas Academy
## Dreigingsmodel
| Dreiging | Maatregel | Status |
|----------|-----------|--------|
| Hardcoded secrets in source | Env-bestanden (`/etc/atlas/*.env`, root 600) | ✅ Opgelost |
| Zwakke wachtwoord-hashing | bcrypt via `academy_auth_v2.py` (nu retired; Odoo native auth) | ✅ Opgelost |
| PII in publieke admin-panel | `academy_admin.py` verwijderd uit docroot | ✅ Opgelost |
| Odoo backend publiek bereikbaar | `/web` niet geproxied via academy-domein | ✅ Opgelost |
| Open signup op corp-website | `website 1.auth_signup_uninvited = 'b2b'` | ✅ Opgelost |
| Clickjacking | `X-Frame-Options: DENY` via Caddy | ✅ Actief |
| MIME-sniffing | `X-Content-Type-Options: nosniff` | ✅ Actief |
| HTTPS downgrade | `Strict-Transport-Security: max-age=31536000` | ✅ Actief |
| ESF-tracker indexeerbaar | `X-Robots-Tag: noindex, nofollow` + `robots.txt` | ✅ Actief |
| Stale SMTP app-wachtwoord | Handmatige rotatie vereist (Google Account UI) | ⚠️ Openstaand |
| XML-RPC relay-wachtwoord | In env, maar waarde mogelijk stale | ⚠️ Controleren |
---
## Secrets locaties
Alle secrets zijn **buiten source** gehouden. Alleen locaties zijn gedocumenteerd.
| Bestand | Inhoud | Rechten |
|---------|--------|---------|
| `/etc/atlas/academy-relay.env` | `ODOO_RELAY_LOGIN`, `ODOO_RELAY_PASS`, `ACADEMY_ADMIN_PASS`, `LEAD_SMTP_PASS` | `root:root 600` |
| `/etc/atlas/academy-auth.env` | `AA_SECRET` (retired Flask JWT secret) | `root:root 600` |
---
## Toegangsarchitectuur
```
Internet
atlasacademy.nl (Caddy)
├── /slides, /web/login, /web/signup → Odoo (public eLearning)
├── /academy-lead → odoo_relay.py (localhost only)
├── /var/www/atlasacademy.nl/* → Static files
└── /web (NIET geproxied) → ❌ Geblokkeerd voor publiek
(Odoo backend enkel via tailnet)
odoo.atlascorporation.nl (Caddy)
└── Authentik forward_auth → Alleen via SSO bereikbaar
```
---
## Odoo signup-beveiliging
```
Website 1 (Atlas Corporation) → auth_signup_uninvited = 'b2b' → GESLOTEN
Website 3 (Atlas Academy) → auth_signup_uninvited = 'b2c' → OPEN (gewenst)
```
Verificatie:
```bash
ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http" <<'EOF'
for w in env['website'].sudo().search([]):
print(f"Website {w.id} ({w.name}): signup={w.auth_signup_uninvited}")
EOF
```
---
## Headers (Caddy)
```caddyfile
header {
X-Frame-Options DENY
X-Content-Type-Options nosniff
Referrer-Policy strict-origin-when-cross-origin
Strict-Transport-Security max-age=31536000
}
```
---
## Secrets roteren
### SMTP app-wachtwoord (`LEAD_SMTP_PASS`)
1. Ga naar [myaccount.google.com/apppasswords](https://myaccount.google.com/apppasswords)
2. Verwijder het oude wachtwoord, maak een nieuw aan
3. Update op atlas-01: `sudo nano /etc/atlas/academy-relay.env`
4. Herstart: `sudo systemctl restart atlas-academy-relay`
### Odoo relay-wachtwoord (`ODOO_RELAY_PASS`)
1. Log in op Odoo backend (tailnet)
2. Wijzig wachtwoord van de relay-gebruiker
3. Update `/etc/atlas/academy-relay.env`
4. `sudo systemctl restart atlas-academy-relay`
---
## Wat NIET te doen
- ❌ Nooit secrets committen in git
- ❌ Nooit `/web` proxien via het publieke academy-domein
- ❌ Nooit wachtwoorden automatisch roteren (operator handelt dit af)
- ❌ Nooit `--send` gebruiken in `atlas_client_email.py` zonder goedkeuring
- ❌ Nooit studentgegevens publiceren (geen nep-reviews, nep-studentaantallen)