EPAC – Managing Enterprise Policies
In our quest to make all things IT easier to automate, we often turn to Infrastructure as Code. Of course, to make it possible to automate in the first place, we depend on software and cloud providers to help us get started. Microsoft, as one such cloud provider, has a number of resources that live in Azure but are not yet supported to deploy automatically. Some bright minds within Microsoft took matters in their own hands and decided to make life a little easier for us developers. With the help of EPAC – Enterprise Policies As Code – we now have a tool to automate deployment of Enterprise Policies within our pipelines. Even though the tool is not officially supported by Microsoft, it is one of the easiest ways to deploy Enterprise Policies automatically.
To understand why you would want this tool, it’s useful to know what Enterprise Policies are in case you are new to these. Enterprise policies are a way to manage rules and restrictions on your Azure resources. You can set a policy on a high level in your Azure Management group or Subscription, or on a lower level on a Resource group. One of the most well-known examples of an Enterprise Policy is to restrict everyone within a subscription to only be allowed to deploy Azure resources to the Azure location nearest to your physical location. You can make these policies as complex as you wish, and control your environment in detail.
The Beans
What is EPAC
EPAC, Enterprise Policies As Code, is a PowerShell tool that helps automate deployment of Enterprise Policies. It allows the rollout of policies that govern Management Groups, Subscriptions and Resource Groups. The project is open source, based on a PowerShell module, and available in the PowerShell gallery.
Using EPAC makes sense of you have complex policies that govern your Azure resources. Of course, this also includes benefits of infrastructure as code in general.
Another reason to want to use EPAC is if you want to report on (non) compliance with your policies, and create remediation tasks to improve adherence.
What problems does EPAC solve?
So why would you want to use EPAC in the first place? Clicking through the Azure Portal works just fine, right? While this might be true at first glance, there are many reasons why we tend to prefer infrastructure as code over manual work.
First and foremost, deploying policies with EPAC reduces manual labour after the initial deployment. Instead of clicking through a graphical interface for every major and minor change, modifying or adding a few lines of text to a file and then hitting the upload-button is much less time consuming.
But, lets assume that you actually enjoy clicking through menus on a portal. You create a beautiful set of policies for your latest client, and proudly announce when it is finished. Of course, coworkers and (project) managers are impressed as well. So naturally there is only one thing they could possibly say to that: “Do it again!”. Hopefully you documented every move you made, or you will be spending a lot of time comparing environments and going through whatever steps you think you took on the first round. With EPAC, though, it would have been as easy as changing around some values and running the deployment to a different environment.
Of course this isn’t a problem you run into when you only maintain a single environment, with no chance of ever needing to deploy multiple environments. That is, until disaster strikes and your environment is wiped or damaged severely. In this day and age you never know what might hit your business environment: ransomware, hacks, outages, interns… It sure would be nice if you had some way to easily reproduce everything you lost. All you need with EPAC is a backup of your policy code. Which reminds me: make sure you have backups!
Considering that documentation part I mentioned earlier: not many feel documentation is the most fun part of the job. Having all your policies and settings in code, means it is documented by default. Changes are then also documented by default in your version control process. Now you can suddenly skip (most) documentation work.
Going on a different tangent, then. Imagine you have all your enterprise policies set up in your Azure environment. For one reason or another, it is decided that everything needs to move to a new Azure landing zone. Copying over every single policy and policy setting manually would be very time consuming and error prone. EPAC allows you to export your current set of policies, and readily move them over to a new landing zone.
Finally, some corporations prefer to divide responsibilities between different teams. For example, you might have a security team and an infra team. Both of which would like to maintain their own sets of policies and restrictions, without having to ask the other team to implement these. With EPAC it is possible to split responsibilities for parts of policy code by team, allowing both teams to work independently without having to rely on eachother or the worry to break something that someone else has just put in place.
How do we do things now?
Now that you know why, the next question is how? In order to understand what makes EPAC different from the way we do things now, it is good to get a sense of the current workings of rolling out policies and definitions. Currently we do this in the Azure Portal, by clicking through a number of policy pages. In those pages we then select either existing policy definitions or create custom ones. Then we apply those and document what we have done. Let’s look at the process in a little more detail.
Policy Dashboard
The starting point is the Azure Policy Dashboard. You will find this in the Azure Portal by searching for ‘Policy’ and selecting the service in the portal. You will presented with the Policy Dashboard, which gives access to the state of your policy environment. Here you can see if there are any resources that are non-compliant, for example. More importantly for our case, this is also where you find the Policy Definitions and Policy Assignments.
Policy Definitions
From the Policy Dashboard overview page, you can go into the Policy Definitions. Azure provides many definitions already, allowing you to relatively quickly. This is also where you create your own policy definitions. You do this by clicking the big plus next to ‘Policy Definition’ in the top left corner.
A new window opens that lets you define a new definition. You define some basic data fields like name and location, and add a description. You can also opt to create a new category to add the definition to if you feel like the existing ones aren’t exactly right. Finally you define the actual policy through a JSON file. Which, if you might have noticed, is already somewhat like applying a definition in code. You can test your own definitions here, but below you’ll find a basic definition that only allows deployment of resources to a list of specified locations. The JSON is the default sample you get when starting a new policy definition.
1. {
2. "mode": "All",
3. "policyRule": {
4. "if": {
5. "not": {
6. "field": "location",
7. "in": "[parameters('allowedLocations')]"
8. }
9. },
10. "then": {
11. "effect": "audit"
12. }
13. },
14. "parameters": {
15. "allowedLocations": {
16. "type": "Array",
17. "metadata": {
18. "description": "The list of allowed locations for resources.",
19. "displayName": "Allowed locations",
20. "strongType": "location"
21. }
22. }
23. }
24. }
Policy Assignments
After creating the policy definition, you need to assign it to where it is required. You can assign policies on a subscription level, on management group level, or on resource group level. You can do this by selecting Assignments under Authoring in the left sidebar. From here, you can opt to ‘Assign policy’ or ‘Assign initiative’. Select ‘Assign policy’ to assign the policy definition we created before. Here you will select a scope for the policy to apply to, you select the definition you want to assign as policy and optionally give it a custom name and description. In the next step you can then select the parameters we referenced in the definition JSON, in this case location.
How do we do things with EPAC?
Now that you have spent some time clicking through the Azure Portal and exploring policy definitions and assignments, we can look at how it is done with policies as code. We will be looking at the process broken down into 4 major steps:
- Preparing your environment
- Starting the project
- Create your own
- Build and Deploy
Preparing your environment
As mentioned before, the basis of EPAC is a Powershell Module. In order to use it, we will need to install it. But before we can do so, it is important to know that the EPAC module has some dependencies with a couple other Powershell modules that need to be installed first.
- Resources
- Accounts
- ResourceGraph
These modules allow you access to your Azure environment through PowerShell, as well as allowing you to list resources and manage them. You can test whether they are installed or not by running the following command:
1. Get-Module -ListAvailable
Then, you can install each module by running:
1. Install-Module -Name Az.Resources
1. Install-Module -Name Az.Accounts
1. Install-Module -Name Az.ResourceGraph
Or, all in one go with this command:
Finally, install the EPAC module for the current user by running:
1. Install-Module EnterprisePolicyAsCode -Scope CurrentUser
Starting the project
Now that you have your modules installed, it is time to create your first project. Before we do this, it is important to know a little background on how EPAC handles projects.
In your project you have a set of JSON files with the .jsonc extension, which contain your definitions, assignments, exemptions and a single global settings file. When you run a build, the module outputs two new JSON files: a policy-plan.json and a roles-plan.json.
The policy-plan file is based on your definitions and assignments, and is the basis for the eventual deployment to your Azure Environment.
The roles-plan file has its origin in the global settings file, and is responsible for creating roles. More on the global settings file later.
Rather than trying to explain it though, a picture says more than a thousand words. Take a look at the graphical representation from the EPAC github page below.
When you start your project, you do not need to have all of your definitions in place initially. You start with an empty project, import your existing policy definitions, policy set definitions and assignments and then run a build and deploy.
First, you create your project folder from where you plan to start everything. This is your root folder. Within the root folder of your project, all you need is a Definitions folder, which contains your global settings file. When you are done, the structure should look like this:
What should be in that global settings file though? As it turns out, this is a rather important file.
Firstly, it contains a pacOwnerId, which is important in identifying the owner of deployed policies. The ‘PAC-owner’, or policy as code owner, is the person or team that manages the specific resource defined in the template. You are free to generate your own ID as you see fit. This ID will be added to all your create policies and is, among other things, key in splitting responsibilities. This id is self-generated (as in: you make it) and you can create your own by creating a guid with Powershell. If you have multiple teams that need to do their own deployments, you can hand them both a different pacOwnerId. Each policy will then only be editable by referencing the associated ID.
Besides this pacOwnerId, you will also need your tenant ID (so the scripts know where to deploy to) and the ID of the management group to which you wish to deploy. Some places in the documentation suggest you need to use the Management Group name, but you can save yourself a lot of headaches by using the ID instead. When you finish filling your global settings file, it should look something like this:
Don’t worry, these are not my actual ID’s. You can safely test them and see what happens (to save you some time: it will be nothing).
After making sure your global settings file is complete, your next step is to fetch all existing policies that might already be in place.
You do so by running the following command from your project root:
1. Export-AzPolicyResources -DefinitionsRootFolder .\Definitions -OutputFolder Output -IncludeAutoAssigned
The result will be a new file folder named Output, which contains a subfolder with Definitions. This Definitions folder will then contain a tree of subfolders, one for each policy item. These will be filled with .jsonc files containing all your already existing policy resources. The resulting project structure will look like below:
Create your own
Now that you have your environment fetched and stored locally, you can start making modifications. You start by copying or moving all folders in the export/Definitions folder to your project root/Definitions folder. This will give you the structure and files the Powershell module expects when preparing to build and deploy. In these folders in project root/Definitions you modify and add or remove policy assignments, definitions and exemptions. The .jsonc files go in their corresponding folders.
When you are done, you will have one or more policy assignment .jsonc files in your project root/Definitions/policyAssignments folder that look somewhat like below.
And you will also have one or more policy definition .jsonc files in your project root/Definitions/policyDefinitions folder that look somewhat like below.
You may have noticed that this file contains a few more fields than the JSON document we saw in the portal earlier. This is because this file does not only contain the policy definition itself, but also some of the values that we selected in a later step in the portal. This file allows you to create parameters, for example. Which you can then use in your assignment file to be able to easily change settings as you see fit. If we take the example from before, where we set a policy that only allows resource deployment to specific regions. Rather than having to go to the portal and click through a number of menus in order to change the assignment, this can now be done as easily as changing a few parameter values and then running a build and deploy.
When you are creating your own definitions and assignments, it is vital that you keep any files that are already in your export. Leaving any folder in your project root/Definitions subfolders empty, will make the EPAC Powershell module think you intend to delete them and act accordingly. If you have no changes to make to any of the resources in these subfolders, you can opt to remove the folder entirely. But just to make sure I got the point across: No empty folders!!
Build and Deploy
Onto the step of finally building and deploying, then. You should now have your Definitions folder filled with subfolder containing definitions, and a global-settings file. If we look back at the process chart from before, we can see the next step is to run a build, which will then output a policy-plan.json.
Running the build is pretty straightforward, by issuing the following command in your PowerShell window from your project root:
1. Build-DeploymentPlans
You will now have a new folder in your project root/Output folder, named ‘plans’. As you might have suspected from the name, this contains your automagically created policy-plan.json file. Your folder structure should look something like below.
Now, there is just one final step to complete the process. Verify your plan is in place in the expected folder, and then run the deploy command. Again, from your project root:
1. Deploy-PolicyPlan
Done! You are now the proud owner of deployed policies as code. Take a few moments to admire your great work, and then go forth and prosper.
Considerations
As briefly mentioned before, it is possible to deploy policies to the same environment by different teams. Important here is the pacOwnerId, which you can manually generate yourself. Policies that do not have a pacOwnerId attached that matches the pacOwnerId of what is being deployed, will not be affected by that deployment. However, since the pacOwnerId is manually assigned, this requires some care on your side. There is nothing stopping Team B from copying the pacOwnerId of Team A and do to their resources as they please. Of course, you could simply agree between teams to not use each others pacOwnerId and leave it at that. But if you require a bit more rigorous separation between teams, you need to account for that by for example obfuscating the pacOwnerId. When using multiple teams to deploy to the same environment, make sure you also have a plan in place to manage any existing policies. You want to prevent them ending up in no-mans-land and lose track of these policies.
Now that you have gained the skillset to deploy your policies with great ease, make quick modifications and document efficiently, you might be interested in seeing if there are more tools that could help you maintaining your environment. One such tool, also created by a Microsoft employee but not officially supported by Microsoft, is AzAdvertizer. This tool helps you by providing overview and insights on new releases and changes/updates for Azure Governance capabilities such as Azure Policy’s policy definitions, initiatives (set definitions), aliases, security & regulatory compliance controls and Azure RBAC’s role definitions and resource provider operations. You can find more on AzAdvertizer here: Project Site.
Another great tool that can help you in your endeavors is Azure Governance Visualizer. This PowerShell tool analyses your Azure Management Group hierarchy all the way down to resource level. Then helps you create an overview with possible outputs in CSV, HTML, Markdown and JSON. Allowing you to create a map of your environment. More info on this project can be found on its GitHub page: GitHub Project.
Conclusion
While enterprise policies are a great way to manage and control your Azure cloud environment, working with them through a web portal that requires lots of clicking is not always the best experience.
EPAC solves this by allowing you to create your enterprise policies from code files that can go into your favorite version control system. Using EPAC to deploy your enterprise policies, you:
- Reduce manual labour
- Improve repeatability of your environment
- Improve disaster recovery times
- Document settings and changes by default
- Move existing policies to a new Azure landing zone easily
- Help splitting responsibilities for policy management and infrastructure deployment (security team vs infra team)
Using EPAC for large and complex environments makes a lot of sense. You can use this document as your guide in getting started with your first deployment. When you have deployed your first policy set, also take a look at AzAdvertizer and Azure Governance Visualizer to expand your toolkit going forward.
Want to know more about what we do?
We are your dedicated partner. Reach out to us.