The problem.
A higher-education group has several schools, each with its own Microsoft 365 tenant. Launching and tracking a simulated phishing campaign meant going into each tenant's Defender portal, and the third-party tool used until then cost a licence, while Defender Attack Simulation and Training is already included in A5 licences.
What I built.
01
Central control
- One multi-tenant Entra app, one token per school; Defender's 7 tabs reproduced for all schools at once, with per-school filters and rights.
- 6-step campaign wizard: technique, template, login page, targets (whole tenant, Entra groups or list), training, scheduling, with “send me a test first”.
- Reports: simulation and training coverage, repeat clickers, training effectiveness, monthly report per school.
02
Sending guardrails
- Every write to Microsoft requires a server-validated, logged confirmation.
- Blackout periods per school, recipient cap, permanent exclusions, large sends split, licence check.
03
GDPR
- Database stores counters only, no address or name; named details are read from Microsoft on demand and cached for 10 minutes.
- Every named view and export is logged; aggregates under 5 people are masked.
- Documented prerequisites: works council information, processing register, notice to people (awareness, not sanction).
The architecture.
Security teamKeycloak SSO
Laravel portalnginx · php-fpm
Worker + schedulerRedis queues
Microsoft Graph/security/attackSimulation
School tenant ADefender P2
School tenant BDefender P2
School tenant …Defender P2
Security & guardrails.
- Server-side confirmation and log for every write action.
- Launch jobs never retried automatically.
- Personal data minimised by design.
The results.
- Replaces a paid third-party tool with a feature already included in existing licences.
- One interface for every school, with per-school permissions.