When someone needs access, two questions matter more than how fast it happens: who said yes, and could that person say yes? Entitlements as Code answers both for every request. Each one is a pull request in your Git, approved by the right person in the web app, and applied to your platforms once it is approved. This post walks through who approves what, who never counts, and why.
One request, start to finish
Ana works at ACME, a fictional company, and needs to work on the web-platform project in its Azure DevOps organization. She opens the Entitlements as Code web app, picks the project and the access level, writes why she needs it and until when, and sends the request.
Marco owns the group that grants that access. He sees Ana's request in his Approvals page, with her reason and the end date, and approves it there. Behind the scenes the request is a pull request: Marco's approval is recorded on it, the checks pass, and it is merged. The group in Microsoft Entra ID is updated, Azure DevOps follows the group, and Ana's My access page shows the new access and when it ends.
Animation: Ana opens the Entitlements as Code web app and requests Contributor access to the web-platform project, with a reason and an expiry date of 31 January 2027. Marco, the owner, sees the request in Approvals and approves it. In Azure DevOps the pull request shows Marco's approval and the checks passed, and it completes. In the Azure portal Ana is now a member of the WebPlatform Contributors group, which gives her Contributor in Azure DevOps. Ana's My access page lists the new access with its expiry date.11122233344455ASKAPPROVEMERGEAPPLIEDACCESSRequest access | En…access.acme.example/requestEntitlements as CodeAREQUEST ACCESSAsk for access. The owners of the group review it.ProjectChoose…web-platform (acme)Access levelChoose…ContributorUntilChoose…31 Jan 2027ReasonRelease work on checkoutSend requestRequest sent to Marco,owner of the group.Approvals | Entitlem…access.acme.example/approvalsEntitlements as CodeMAPPROVALSRequests waiting for you as an ownerAAna asks for Contributorweb-platform, acme (Azure DevOps)“Release work on the checkout service”Until 31 Jan 2027Checks passedPull request #142ApproveDenyApproved by youRecorded on the pull requestIcon-devops-261Pull request 142 | Az…dev.azure.com/acme/web-platf…Icon-devops-261Repos/Pull requestsAActiveCompletedPull request 142Ana: Contributor on web-platformAAna wants to merge access/ana into mainOverviewFilesDescriptionRequested by Ana in Entitlements as Code.Reason: release work on the checkout service.Until: 31 Jan 2027.ReviewersMMarcoOwner, approved in Entitlements as CodeRequiredApprovedChecksAccess files are validOwner approvalMerged by Entitlements as CodeMembers | Microsof…portal.azure.com/#view/Group…Microsoft AzureEHome > Groups >Icon-identity-223ACME WebPlatform ContributorsGroup, Members+Add members↻RefreshNameBBenCChenDDanaAAnaAdded from GitIcon-devops-261Azure DevOps follows the group:Ana is a Contributor on web-platformMy access | Entitle…access.acme.example/my-acce…Entitlements as CodeAMY ACCESSWhat you have, and until whenIcon-devops-261web-platformAzure DevOps, acmeContributorUntil 31 Jan 2027Icon-devops-261docs-siteAzure DevOps, acmeReaderNo end dateCheckoutJira projectMemberUntil 30 Jun 2027checkout-stagingAWS accountRead onlyUntil 31 Mar 2027One request, one approval, applied everywhere
One request: Ana asks, Marco approves, and the access is applied, with a pull request behind every step.
Nobody opened an admin console, and nobody had to remember to write anything down. The pull request holds who asked, what for, why, until when, and who approved it.
Who approves what
The person who approves depends on what the change does.
Change
Who approves
Someone joins or leaves a group
One owner of that group
A group's owners change
An owner and an EaC admin, two different people
A group is created or deleted
An EaC admin
An organization's settings change
An EaC admin
In the demo, Marco owns the group and the request only adds a member, so his approval is enough.
If the same request had made Ana an owner, Marco's approval would not be enough on its own. Owners decide who gets in, so a change to the owners needs a second person: an EaC admin who is not Marco.
An owner can also say no. A rejected request is not applied, and the rejection stays on record with the request.
Who never counts
Three kinds of people never count as approvers, even when they own the group:
The person asking. Ana cannot approve her own request.
Anyone who edited the request. They helped write the change, so they are not independent of it.
The people getting the access. Some people can ask on behalf of a colleague. If Ana asks for Marco, Marco cannot approve his own access, even though he owns the group.
The reason is separation of duties. A record that says "Ana asked, Ana approved" answers nothing. When an auditor or a customer's security questionnaire asks who approved a grant, the answer has to be someone other than the person who asked for it, wrote it or received it.
That is also why EaC admins step in when no owner can vote. Say Marco is the only owner and he needs Contributor himself. He is the one asking, so he cannot approve, and an EaC admin approves instead. Marco still gets his access through the same flow, and the record still shows two different people.
The rules are enforced, not just suggested. The pull request cannot be merged until the right approval is there, and the owners that count are the ones already on record, so nobody can make themselves an owner in the same request and then approve it.
The same flow, for every platform
Azure DevOps is the example here, but the flow does not depend on it. Access lives in groups in Microsoft Entra ID, and the platforms you use map those groups to their own access: a project role, a team, an account, a Jira project. A module connects each platform.
ONE FLOW, EVERY PLATFORMPEOPLEAnaasks for accessMarcoowner, approvesENTITLEMENTS AS CODEWeb appask, approve, reviewGitevery change is a pull requestMICROSOFT ENTRA IDGroupsmembers and ownersYOUR PLATFORMSAzure DevOpsprojects and rolesGitHubteams and reposGitLabgroups, projectsAWSaccounts and rolesJiraprojectsMore platformsthrough a moduleARROWSAsk and approveAppliedasksapprovespull requestappliedaccess follows the groups12345
ONE FLOW, EVERY PLATFORMPEOPLEAnaasks for accessMarcoowner, approvesENTITLEMENTS AS CODEWeb appask, approve, reviewGitevery change is a pull requestMICROSOFT ENTRA IDGroupsmembers and ownersYOUR PLATFORMSAzure DevOpsprojects and rolesGitHubteams and reposGitLabgroups, projectsAWSaccounts and rolesJiraprojectsMore platformsthrough a moduleARROWSAsk and approveAppliedasksapprovespull requestappliedaccess follows the groups12345
One flow for every platform: ask and approve in the web app, a pull request in Git, groups in Entra, and every platform follows.
So the questions never change from one platform to the next: who asked, who approved, and until when.
Taking access away
Removing access follows the same path. Leaving a group is a request like any other, approved by the group's owner. Offboarding someone from every group is a single request. Access with an end date ends on its own, and periodic access reviews let owners confirm who should keep it. Every removal has an author, a reason and an approver, like every grant.
The result is a history where every grant and every removal has an author, a reason, an approver who is not the author, and a date. That is the evidence, and it lives in your own Git.
Adopt Entitlements as Code on a live directory without changing it. Import what exists, observe with nothing written, then enforce one organization at a time.