Work · National food brokerage
Client Manager group sync (distribution lists + Fabric access)
Skills exercised
Keeps two things in step with live CRM account-assignment data, nightly, for every client: the Exchange Online distribution list used for email, and the Entra ID security group that grants Microsoft Fabric workspace access for that client's data. The Fabric piece is what makes this more than a mail-routing job: a membership error changes who can read a client's data, not only who gets email.
Why PowerShell for one leg, Power Automate for the other
Power Automate handles the cloud-native side well: reading the CRM export and staging it as a SharePoint list. But distribution list membership changes are governed by Exchange Online cmdlets with no native Power Automate equivalent, so that leg has to run as PowerShell. Splitting the work this way uses each platform where it's strong instead of forcing one to do the whole job.
Re-architected onto Azure Automation
Originally an on-prem scheduled task, the pipeline was rebuilt onto a single Azure Automation runbook authenticating with a system-assigned managed identity, found and prioritized through a fleet-wide audit of undocumented scheduled automation. The rebuild collapsed two scripts into one runbook, reads the SharePoint list directly through Microsoft Graph instead of a hand-off file, removed a stored credential tied to a named account, and replaced a permissive parser with one that can't execute untrusted input.
Safety guards
- Empty-source refusal a client row with no members but an active group is skipped and reported, not silently applied, since a broken CRM export looks identical to "everybody left."
- Per-client change caps a client needing an unusually large membership change is skipped and flagged for review rather than applied automatically.
- Least-privilege Graph permissions scoped to the one SharePoint site and to group membership only, with no create, delete, or mail-read access anywhere.
Cutover discipline
Verified the source timing against the SharePoint list's own item history rather than an inherited assumption, checked the retiring server's copy against source control for undocumented business rules before cutover, and kept the old scheduled task disabled rather than deleted through a rollback window. The first production run was verified independently in Exchange rather than trusting the job's own summary.