Entitlements as Code in practice
What the method looks like on Microsoft Entra ID and your platforms, with your own tools or with a product.
The principles and the framework do not depend on a tool. This page shows them on a common setup: people and groups in Microsoft Entra ID, and platforms such as Azure DevOps, GitHub, GitLab, AWS or Jira that give access to those groups. Then it shows two ways to put them in place: with tools you already have, or with a product built for it.
One flow for every platform
Access lives in groups in Microsoft Entra ID, and your platforms map those groups to their own access: a project role, a team, an account, a Jira project. Change the group through a reviewed pull request, and every platform that follows it changes too.
Access requests as pull requests
A ticket says that someone asked. A pull request also says exactly what changes, who approved it and when it was applied, and it can be undone. So every access request is a pull request:
- Ask. A person picks the access, and writes why they need it and until when.
- Approve. The owner of the group approves it; the approval is recorded on the pull request.
- Apply. The change is merged and applied: the group in Entra is updated, and every platform that follows it changes too.
The person asking never approves their own access, and neither does anyone who edited the request or the people getting the access. A change of owners needs two different people. Leaving a group follows the same path, access with an end date ends on its own, and periodic access reviews let owners confirm who should keep it.
More: Who approves an access request, and why the person asking never counts.
Drift: when Entra and Git disagree
Sooner or later, someone with admin rights adds a person to a group directly in the Azure portal: a quick fix during an incident, a favour for a colleague. That change has no request, no reason and no approver. Git does not list the person, Entra does, and that difference is drift. A member removed by hand, or a group created in Entra that Git does not know about, is drift too.
| The organization | A member added by hand |
|---|---|
| Enforces | Removed, back to what Git says |
| Observes | Kept for now and listed in the drift report, for a person to decide |
An organization that enforces can also choose a gentler setting: instead of being put back at once, each change made by hand becomes a request for its owner to keep or remove.
More: Drift: what happens when someone grants access by hand in Entra.
Observe, then enforce
Your Entra groups already have members and owners. So adoption starts read-only:
- Import. The groups that exist today are written into Git, one file per group, with their members and owners.
- Observe. Nothing is written. People ask and owners approve, checks flag naming problems and sensitive groups with no owner, and the drift report lists access granted outside Git.
- Enforce. When an organization is ready, it is switched to enforce with a reviewed change. From then on approved requests are applied, and changes made by hand go back to what Git says.
One organization at a time: each has its own groups, owners and habits, and one whose owners are not ready keeps observing without holding the others back. The maturity model describes these stages as levels.
More: Start read-only: observe first, then enforce one organization at a time.
Do it yourself
The method can be applied with tools many IT teams already run. A minimal setup on Microsoft Entra ID:
- A repository with one file per group. Each file lists the group's members and owners. Folders follow your organizations.
- Owners as required reviewers. A
CODEOWNERSfile (GitHub) or path-based required reviewers (Azure DevOps, with a group of the owners as the reviewer so that any one of them is enough) makes the owners of each group file the people who must approve changes to it. Branch protection blocks merging without their approval. - Checks on every pull request. A pipeline validates the files: naming, owners present, sensitive groups with two owners, end dates in the right format. It also shows the plan of what would change.
- Apply on merge. OpenTofu or Terraform with the
azureadprovider manages the groups, their members and their owners from the files. The pipeline signs in with workload identity federation rather than a stored secret. - Drift on a schedule. A scheduled plan compares Entra with the files and reports any difference (observe). A scheduled apply puts differences back (enforce), as long as each group's members are declared as one list, so that anyone added by hand is removed too.
The limits you will meet. Requesters have to edit files and open pull requests, which most people outside engineering will not do. Approval rules only go as far as your Git host allows: it can require an owner's review, but checking that nobody who edited a request approves it, or that owner changes get two approvers, takes extra work. End dates and access reviews need jobs of their own. And each platform that does not follow Entra groups needs its own stack.
With a product
Entitlements as Code by MoreThanOps is a product built on this method, so the pieces above come ready:
- a web app where people ask for access and owners approve, review and end it, with no files to edit;
- pull requests in your own Git for every change, with the approval rules of the principles built in: the requester never counts, and owner changes need two people;
- observe and enforce per organization, with a drift report and the choice of putting hand changes back or turning them into requests;
- end dates and access reviews as part of the same flow;
- modules for your platforms: Azure DevOps as the reference module, and more platforms through modules.
Early access starts from the waitlist on eac.morethanops.pro.