# 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)