Series - Compliance as Code
Microsoft 365 Security as Code
The CIS Microsoft 365 benchmark tells you what to set. This series is about everything else: the decisions you make before the code, the tools that reach each setting, a pipeline that deploys without stored secrets, and the evidence you can show an auditor.
What this series is
The benchmark has 160 recommendations, and the PDF already tells you what each setting should be. It does not tell you which profile you are signing up to, which tool can really change a setting, how to run a Windows-first tool in a Linux pipeline, what to do when a control breaks your estate, or what evidence is honest to show. Those are the questions I ran into while building this for a regulated financial-services client, and each post takes one of them.
Every post reads on its own. You do not need to start at part 1.
A note on the benchmark
I do not copy benchmark text. The posts use control numbers and my own words, because the CIS terms of use do not allow hosting or quoting the benchmark on other sites without asking. You can get the benchmark itself from CIS.
Start where it hurts
- You have to decide or approve: start with part 1, about profile, scope, what "done" means and who accepts an exception.
- You are choosing tools: start with part 2, about Terraform, Microsoft365DSC, small scripts and why the code lives in several repositories.
- Your pipeline runs on Linux: start with part 3, about running Microsoft365DSC where its own engine does not exist.
Published
All parts so far
-
Part 1: Before you write any code
The CIS Microsoft 365 Foundations Benchmark has 160 recommendations, and writing the code is the easy part. These are the decisions that have to come first: which profile you sign up to, what is in scope, what 'done' means, and who accepts the exceptions.
-
Part 2: One benchmark, four tools
No single tool reaches every setting in the CIS Microsoft 365 benchmark. This is the order in which I choose a tool for each control, a worked example of a setting that no tool exposes, and why the code lives in several repositories with several identities.
-
Part 3: Running Microsoft365DSC on Linux
Microsoft365DSC was built for Windows, but our pipeline runs on Linux. This is how I made the apply step work without the Windows engine: a small parser for the compiled configuration, a careful Exchange Online session, and the permission problem that looked like a code problem.
Coming next
These are planned. The titles and the order may change as I write them.
| Part | Topic |
|---|---|
| 4 | Deploying to a production tenant with no secrets: workload identity, one identity per job, and approval in the pipeline |
| 5 | Conditional Access as code: where policies look right but are not |
| 6 | Entra ID hardening: the controls that have no API |
| 7 | When the benchmark breaks your estate: deviations as data |
| 8 | Evidence, not a score |
What the series does not cover
The code behind these posts covers Entra ID, Conditional Access, Exchange Online, SharePoint, Teams and the admin center. It does not cover Microsoft Purview, Intune or Fabric, which together hold 19 of the 160 recommendations. I write only about what I have built and checked.
Need this in your own tenant?
I help teams write Microsoft 365 security down as code, review it like code and prove it to an auditor, especially in financial services and other regulated environments.