diff --git a/docs/plan-mailbox-scanning.md b/docs/plan-mailbox-scanning.md new file mode 100644 index 0000000..faac4cc --- /dev/null +++ b/docs/plan-mailbox-scanning.md @@ -0,0 +1,119 @@ +# Plan — Mailbox Permission Scanning + +Voorstel voor het uitbreiden van Clearview met mailbox-rechten scanning naast de bestaande SharePoint-scan. Status: **voorstel, nog niet geïmplementeerd**. + +## 1. Scope & aanpak + +In Exchange Online zijn dit de relevante permissie-categorieën: + +| Permissie | Bron | Waarop | +|---|---|---| +| **Full Access / Read** | `Get-MailboxPermission` | hele mailbox | +| **Send As** | `Get-RecipientPermission` | identiteit | +| **Send on Behalf** | mailbox-property `GrantSendOnBehalfTo` | identiteit | +| **Folder delegaties** (Calendar, Inbox) | `Get-MailboxFolderPermission` | per folder | + +Microsoft Graph dekt dit slechts gedeeltelijk (vooral folder-permissies). De volledige set vereist **Exchange Online PowerShell met certificaat-auth** (`Connect-ExchangeOnline -CertificateThumbprint ... -AppId ... -Organization ...`). Dat sluit goed aan op het bestaande cert-model van Clearview — dezelfde Azure-app kan zowel `Sites.FullControl.All` (SharePoint) als `Exchange.ManageAsApp` (Exchange) krijgen. + +**Voorgestelde aanpak:** EXO PowerShell aanroepen vanuit Python via `pwsh` subprocess, JSON-output retour. Alternatief is pure Graph, maar dan mist Send As / Send on Behalf grotendeels. + +**Deviation-baseline voor mailboxen:** anders dan SharePoint heeft een mailbox geen "root vs. child" hiërarchie waar een baseline uit volgt. Voorstel: rapporteer **alle non-default permissies** (filter standaard-entries als `NT AUTHORITY\SELF`, `S-1-5-10`, default folder-permissies "Default"/"Anonymous=None") als deviation. Dus géén delta-vergelijk, maar wel dezelfde dedup-logica per (principal, role). + +## 2. Layout-wijzigingen frontend + +Huidige website is volledig op SharePoint gemodelleerd (één scanflow, één resultaattabel). Voorstel: + +**a. Scan-type keuze in "Start New Scan"** +- Tabs of segmented control bovenaan: **SharePoint Sites** / **Mailboxes** +- Bij Mailboxes verandert het invoerveld: één UPN/email per regel (geen "skip default sites") +- CSV-import: extra accept-formaat (kolom `UserPrincipalName` / `Email` / `Mailbox`) + +**b. Jobs-tabel** +- Nieuwe kolom **Type** (SharePoint / Mailbox) +- Tenant-filter blijft, extra filter op type + +**c. Job Details panel** +- Sectie heading wordt dynamisch: "Targets" blijft, maar URL-kolom wordt "Mailbox" voor mailbox-jobs +- Permission Deviations tabel krijgt voor mailbox-jobs andere kolommen: + - Mailbox · Folder (leeg voor mailbox-level) · Permission Type (FullAccess/SendAs/SendOnBehalf/Folder) · Principal · Access Rights +- SharingLinks-blok wordt verborgen voor mailbox-jobs +- Site-filter wordt mailbox-filter + +**d. Tenants-panel** +- In de onboarding-instructies een extra stap erbij: API permission `Office 365 Exchange Online → Exchange.ManageAsApp` + role `Exchange Administrator` toekennen aan de service principal. Voor de geautomatiseerde flow betekent dit een extra Graph-call (rol-toekenning kan niet altijd, dus mogelijk handmatige stap). +- Statuskolom `Auth` toont al cert/secret; voorstel: extra capability-badge per tenant (`SP`, `EXO`) zodat zichtbaar is welke scans mogelijk zijn. + +## 3. Backend-optimalisatie / herstructurering + +`scanner.py` is nu één bestand met SharePoint-specifieke logica én generieke helpers (auth, HTTP, dedup, role-name normalization). Voorstel: + +``` +src/clearview_app/scanners/ + __init__.py # dispatcher: scan(target_type, ...) + common.py # AuthConfig, DeviationRecord, ScanResult, ProbeResult, + # MSAL token cache, _request_json, _iter_paged, + # _deduplicate_hierarchical, role-name normalization + sharepoint.py # huidige scan_site_for_deviations + probe_site + resolve_sharing_link_members + mailbox.py # nieuw: scan_mailbox_for_deviations + probe_mailbox + # roept pwsh aan met EXO-script en parseert JSON + exo_scripts/ + get-permissions.ps1 # connect + get mailbox/recipient/folder permissions, output JSON + probe.ps1 # lichtgewicht: Get-EXOMailbox -Identity x | select Identity +``` + +Voordelen: +- `scanner.py` was richting 540 regels en mengt concerns; opsplitsen maakt testen makkelijker +- `worker.py` krijgt één dispatcher-call: `scan(target_type, target, auth, progress)` ipv. directe import van SharePoint-specifieke functies +- Toekomstige scan-types (OneDrive, Teams) passen in hetzelfde patroon + +**Worker.py** moet leren: per target weten welke scanner aan te roepen op basis van `scan_targets.target_type` (of `scan_jobs.scan_type`). + +## 4. Datamodel + +Minimale, niet-brekende wijzigingen — toegepast via bestaand `_ensure_schema_columns()`: + +| Tabel | Nieuwe kolom | Default | +|---|---|---| +| `scan_jobs` | `scan_type` VARCHAR(32) | `'sharepoint'` | +| `scan_targets` | (geen — `site_url` blijft, bevat UPN voor mailbox-jobs; of hernoem naar `target` met DB-view voor compat) | — | +| `permission_deviations` | `permission_type` VARCHAR(32) NULL | NULL (voor SP-rows) | +| `permission_deviations` | `object_type` krijgt nieuwe waarden: `Mailbox`, `MailboxFolder` | — | + +**Vraag:** liever `site_url` houden als generieke "target identifier" (compacter, geen migratie), of nu hernoemen? Eerste optie is mijn voorstel. + +## 5. API-endpoints + +Bestaand blijft werken. Toevoegingen: + +``` +POST /api/scan-jobs payload krijgt optioneel "scan_type": "sharepoint"|"mailbox" + en "mailboxes": [...] naast/ipv "site_urls" +POST /api/scan-jobs/import-csv extra "scan_type" form-field +GET /api/scan-jobs?scan_type=mailbox filter +``` + +Nieuwe response-velden in `ScanJobDetail`: `scan_type`, en deviations krijgen `permission_type`. + +## 6. Onboarding & runtime-vereisten + +- **Container**: PowerShell 7 (`pwsh`) en de `ExchangeOnlineManagement` PS-module installeren in de Docker image. Dit voegt ~150MB toe. Acceptabel? +- **Azure-app**: extra permission `Office 365 Exchange Online → Exchange.ManageAsApp` + Entra-rol "Exchange Administrator" voor de service principal. In Mode A (automated) kan het permission-deel via Graph, het rol-deel meestal niet — handmatige bevestigingsstap nodig. +- **Probe**: voor mailboxen één kleine call (`Get-EXOMailbox -Identity -Properties Identity` via een korter PS-script) om vroeg te falen op auth/rol. + +## 7. Implementatiestappen (volgorde) + +1. Backend refactor: scanner-module opsplitsen, geen functionele wijziging (groen test) +2. Datamodel: `scan_type` + `permission_type` toevoegen, default `'sharepoint'` +3. Mailbox-scanner: PS-scripts + Python-wrapper + dispatcher; alleen via API testbaar +4. API: scan-job creatie uitbreiden met `scan_type`/`mailboxes` +5. Frontend: scan-type segment in formulier + dynamische kolommen in details +6. Onboarding-tekst en build (Dockerfile voor `pwsh`) +7. Documentatie: TECHNICAL.md + changelog-develop.md + +## Open vragen + +1. **PowerShell-route akkoord**, of liever Graph-only (incompleter, maar pure Python)? +2. **Eén scan-type per job** (voorstel), of mengbare jobs (SharePoint + mailboxen door elkaar)? +3. **Baseline voor mailbox**: alle non-default rechten als deviation rapporteren (voorstel), of moet er een "expected baseline" per mailbox/tenant configureerbaar worden? +4. **Image-grootte**: is +150 MB voor `pwsh` + EXO-module aanvaardbaar? +5. **`site_url` kolom hergebruiken** als generieke target-identifier, of nu hernoemen naar `target`?