Open-source project
Azure/enterprise-azure-policy-as-code avatar
Azure/enterprise-azure-policy-as-code

EPAC manages Azure Policy from a git repository with PowerShell modules

Enterprise Azure Policy-as-Code (EPAC) solution

556 stars332 forksPowerShellMIT

At a glance

What is it?
Enterprise Azure Policy as Code, or EPAC, is Microsoft's solution for holding Azure Policy assignments, definitions and exemptions in source control and shipping them through pipelines. It suits platform teams who need policy changes reviewed and versioned rather than clicked in the portal.
Who is it for?
Adopt EPAC if your organisation already runs Azure Policy across several subscriptions and needs those assignments, definitions and exemptions reviewed, versioned and promoted through pipelines rather than edited by hand in the portal. Do not adopt it for a handful of assignments in one subscription, where the portal is faster and the operational overhead of a git workflow is not worth it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly PowerShell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What problem EPAC is actually solving

Azure Policy lets you attach rules to a scope and have Azure enforce them, and the enforcement side is solid. The difficulty is on the authoring side. Assignments, initiative definitions, exemptions and parameters are objects that a platform team creates and edits, and a team doing that at scale ends up with three problems: no review on who changed what, no way to roll a change back to a previous state, and no way to promote a policy from a test subscription to production with confidence. The project describes itself plainly as a solution that allows you to manage Azure Policy as code in a git repository, and the whole point is to move that authoring into a normal software delivery workflow, where a pull request is the review, a merge is the approval and a pipeline run is the deployment.

The audience is therefore not the person with one subscription and two assignments. It is the platform or cloud governance team running policy across a large estate, likely already using Azure DevOps, and likely already holding infrastructure definitions in git through Bicep, ARM or Terraform. EPAC sits alongside that existing practice rather than replacing it. The repository is written in PowerShell, which is a deliberate fit for the audience rather than a neutral choice, since the team administering Azure Policy is usually the same team administering Azure DevOps, and the module is consumed the same way any other PowerShell module is.

The repository layout shows how the workflow is organised

The top level of the repository is more informative than the project description, which is short and points at the documentation for an overview. There is a Module/ directory, which is where the PowerShell module that does the actual work lives, and a Scripts/ directory for the entry points that a pipeline invokes. There is a Schemas/ directory, and that is the most interesting entry for anyone evaluating the approach, because schemas are what let a policy repository be validated before anything reaches Azure. The Examples/ directory holds worked configurations, with named folders for Auto-Documentation, for MCSBv2 and for MFA, which tells you the shape of a real policy set: documentation generation, a management container strategy, and multifactor authentication requirements. There is a StarterKit/ directory, which is the intended on-ramp for a new adoption, and a Docs/ directory alongside a mkdocs.yml file, so the documentation for the project is itself built from files in this repository rather than hosted somewhere separate.

Then there are the scripts at the root: Sync-FromGH.ps1, Sync-ToGH.ps1 and Sync-Repo.ps1. The naming tells the story of how the solution is distributed. The solution is not consumed as a copy of this repository that you clone and edit, because then every team would fork it and diverge. Instead the pattern implied by these names is that configuration is synchronised between a central repository and the consuming repositories, with a script that moves state from GitHub into the local solution and scripts that move the solution state back out to GitHub. That is a different design from the usual fork-and-edit approach, and it is the reason the three sync scripts are named the way they are. The Tests/ directory is there to check the module, and SECURITY.md and SUPPORT.md carry the usual project governance files.

Schemas and validation, which is where the real value sits

Policy as code only pays off if the code is checked before it is applied, and the presence of a Schemas/ directory says that this is where the design puts the effort. A schema describes the expected shape of a configuration file, so a policy set can be validated for structure, required fields, valid parameter names and consistent naming across assignments and exemptions. That is a real class of bug that otherwise appears only after a deployment: a misspelled effect name, an exemption that references an assignment that has been renamed, a parameter with a type that does not match the definition it feeds.

The naming of the Examples folders reinforces the point. MCSBv2, as shown in the Examples folder, is a governance configuration the project ships as a worked example, and MFA is a policy requirement that every tenant needs and that every tenant gets wrong the first few times. Both are configurations where a schema and a reviewed git history are worth more than an experienced click path, because the errors show up as failed assignments across dozens of scopes rather than as a small local mistake. The Auto-Documentation example points at the same idea from another direction. Policy that nobody understands gets waived, and a repository that can regenerate documentation from the policy definitions keeps the written description close to what is actually enforced. That is a maintenance concern that a portal cannot address at all, because in a portal the description and the rule drift apart.

Moving a policy change from a branch to production

The delivery shape implied by the repository is a promotion pipeline rather than a single deployment. Configuration lives in git, so the sequence is the familiar one: a change is made on a branch, the pipeline validates it against the schemas, it is reviewed and merged, and a separate pipeline applies it to the target scope. The three sync scripts fit into that sequence. Sync-ToGH.ps1 moves the solution content out to the GitHub repository, Sync-FromGH.ps1 brings the current shared state down into a local working copy, and Sync-Repo.ps1 appears to handle the repository level synchronisation that keeps a consuming repository in step with the shared configuration.

This is where the difference from a fork based approach becomes concrete. In a fork, each subscription team owns a copy, and a change to a shared policy definition requires that someone push it to every copy. With a central repository and a sync step, the shared definition is changed once and each consuming repository pulls it, then its own pipeline applies it to its own scope. The cost of that design is real too, and it is the cost the tool asks you to pay: a pipeline stage that pulls shared state, a merge strategy for shared versus local configuration, and the discipline of not editing policy in the portal at all, because a portal edit creates drift that the next sync silently overwrites. Teams that adopt this need to be explicit about the portal being read only for policy, and the repository gives them the tooling to enforce that rather than asking nicely.

Where this approach is the wrong choice

There are two honest limitations. The first is scale. EPAC earns its cost when policy touches many scopes, when several people can propose changes, and when an audit trail matters. If you have one subscription, two assignments and one operator, a git repository plus a pipeline is more moving parts than the problem, and the portal does the same job with fewer clicks. Adding a source control layer to a governance process that is not under pressure is a common and expensive mistake.

The second limitation is that this solution is opinionated about how it is delivered, and it assumes a Microsoft hosted pipeline. The module is PowerShell and the repository includes Azure DevOps oriented content and topics covering azure-pipeline and devops, so a team that standardises on GitHub Actions or on a self hosted runner arrangement is working outside the shape the project assumes. The sync scripts also assume a central shared repository exists somewhere, which means the governance question of who can propose a change to shared policy has to be answered before the tooling helps rather than after.

And there is a limit on what policy as code can express at all. Azure Policy rules are a defined vocabulary of effects and conditions, and moving them into git does not widen that vocabulary. A policy set that drifts toward encoding approval workflows inside policy conditions tends to become unreadable and slow to evaluate, and at that point a deployment pipeline with a proper gate is the better tool. EPAC and a deployment pipeline are complements rather than substitutes, and confusing the two is how teams end up with slow, fragile policy.

Licence, release cadence and upgrade cost

The project is MIT licensed, with the terms in the LICENSE file at the root of the repository, and the code is public under a Microsoft Open Source Code of Conduct with contributions handled through a Contributor License Agreement bot. The trademark notice in the project description is worth noting for a commercial deployment: authorised use of Microsoft trademarks and logos is subject to Microsoft's brand guidelines, and use in a modified version must not imply Microsoft sponsorship. In practice that means you can run and adapt the solution internally under MIT without asking, but you should not brand your internal portal or product with the Microsoft marks.

The release cadence is fast and predictable. Version 11.5.9 was published on 2026-10-13, with 11.5.8 on 2026-09-22 and 11.5.6 on 2026-09-15, and the last push to the repository was on 2026-10-22. The repository is not archived. A minor version stream at that frequency means the module is genuinely being worked on, and it also means your pipeline has a decision to make: pin a version and upgrade on your schedule, or track the branch and absorb changes on release day. Given that this tool writes policy assignments into your Azure estate, pinning a version and reading the release notes before upgrading is the sensible default. The documentation is published from this repository under Docs/ with mkdocs.yml, and the overview lives at aka.ms/epac, so the upgrade notes and the migration guidance arrive in the same place as the code.

Editorial conclusion

Adopt EPAC if your organisation already runs Azure Policy across several subscriptions and needs those assignments, definitions and exemptions reviewed, versioned and promoted through pipelines rather than edited by hand in the portal. Do not adopt it for a handful of assignments in one subscription, where the portal is faster and the operational overhead of a git workflow is not worth it. Before you start, read the EPAC documentation at aka.ms/epac, look at the StarterKit/ directory and the Examples/ folders for Auto-Documentation, MCSBv2 and MFA, and confirm your PowerShell and Azure DevOps environment can run the Scripts/ entry points, because the repository itself is only the source and the workflow lives in that module.

Frequently asked questions

What is Enterprise Azure Policy as Code (EPAC)?

EPAC is Microsoft's solution for managing Azure Policy as code in a git repository, so that policy assignments, definitions and exemptions can be reviewed, versioned and deployed through a pipeline instead of being edited by hand in the Azure portal. It is written in PowerShell and released under the MIT licence.

How do I get started with EPAC?

The repository includes a StarterKit/ directory intended as the starting point for a new adoption, and an Examples/ directory with worked configurations for Auto-Documentation, MCSBv2 and MFA. The overview documentation is published at aka.ms/epac and the project's own docs live under Docs/ in this repository, built with mkdocs.yml.

What do the Sync scripts in the EPAC repository do?

Sync-FromGH.ps1, Sync-ToGH.ps1 and Sync-Repo.ps1 handle synchronisation between the shared configuration and the consuming repositories, rather than requiring every team to fork and edit its own copy of the solution. The Scripts/ directory holds the entry points a pipeline invokes to apply configuration to an Azure scope.

Does EPAC validate policy definitions before deployment?

The repository includes a Schemas/ directory for describing the expected shape of configuration files, which is what allows a policy set to be checked for structure and required fields before anything is applied to Azure. The Examples/ folders for MCSBv2 and MFA show the kind of configuration that is meant to be validated this way.

Is EPAC still being maintained and what licence is it under?

The repository is not archived and the last push was on 2026-10-22, with version 11.5.9 released on 2026-10-13 after 11.5.8 and 11.5.6 in September 2026. The code is MIT licensed, and contributions require agreeing to a Microsoft Contributor License Agreement.

Official sources

  1. Azure/enterprise-azure-policy-as-code on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/azure-enterprise-azure-policy-as-code.svg)](https://hysenlabs.com/projects/azure-enterprise-azure-policy-as-code)

Was this useful?