Enterprise Azure Policy as Code (EPAC)
repository·main·Indexed 20 days ago
https://github.com/azure/enterprise-azure-policy-as-codeA GitOps solution for managing Azure Policy as code. EPAC enables the definition, versioning, and automated deployment of Azure Policy definitions, assignments, and exemptions within Git repositories. It includes support for multi-tenant deployments via epacCloudEnvironments, Azure Lighthouse cross-tenant role assignments, and programmatic exemption management using PowerShell cmdlets like Set-AzPolicyExemptionEpac and Get-AzExemptions.
What's inside Enterprise Azure Policy as Code (EPAC)
- Enterprise Azure Policy as Code (EPAC) is a solution designed to enable the management of Azure Policy using a GitOps approach. It allows you to define, version, and manage your Azure Policy definitions and assignments as code within a Git repository, facilitating automated deployment and governance workflows.
Overview of Enterprise Azure Policy as Code (EPAC)
mainEnterprise Azure Policy as Code (EPAC) is a collection of PowerShell scripts designed for CI/CD-based or semi-automated deployment of Azure Policy resources. It enables managing Policies, Policy Sets (Initiatives), Policy Assignments, Policy Exemptions, and Role Assignments at scale.
Key Capabilities:
- Single and multi-tenant policy deployment.
- Easy integration with any CI/CD tool.
- Extraction of existing Policy resources from an environment into code.
- Deployment sequencing based on resource dependencies.
- Support for Azure Landing Zone (ALZ) recommended policies.
- Desired state deployment (Note: EPAC will delete any Policy resources at the
deploymentRootScopeand its children that are not defined in the EPAC repository).
Update policy default structure parameters
mainAfter generating the structure file, you must update it to match your environment. Key fields to modify include:
- Parameters: Update values within the
parametersobject (e.g.,dcrResourceId). - Management Group IDs: Update the
valuein themanagementsection to your specific management group ID. - Enforcement Mode: Change
enforcementModeto eitherDefaultorDoNotEnforce.
Example JSON snippets:
// Updating a parameter "ama_vm_insights_data_collection_rule_id": { "policy_assignment_name": [ "Deploy-VM-Monitoring", "Deploy-VMSS-Monitoring", "Deploy-vmHybr-Monitoring" ], "description": "The data collection rule id that should be used for the VM Insights deployment.", "parameters": { "parameter_name": "dcrResourceId", "value": "" } } // Updating a management group ID "management": { "management_group_function": "Management", "value": "/providers/Microsoft.Management/managementGroups/management" } // Modifying enforcement mode "enforcementMode": "Default"- Parameters: Update values within the
Use CSV files for large Policy Set parameters and overrides
mainFor large Policy Sets (e.g., Azure Security Benchmark, NIST 800-53), managing parameters, overrides, and
nonComplianceMessagesin JSON can become unmanageable. EPAC allows you to use a CSV spreadsheet to manage these values across multiple environments.EPAC uses the CSV to create:
parametersoverrides(if the effect is not a parameter in the Policy Set)nonComplianceMessages(optional)
Best Practice: Use this approach for large Policy Sets. For smaller Policy Sets, continue using standard JSON
parameters,overrides, andnonComplianceMessages.Configure Metadata and the deployedBy field
mainThe
metadatasection of a policy definition is used for organizational purposes.Metadata Fields:
category: Should be one of the standard categories used in built-in Azure Policies.version: Should be a semantic version number.deployedBy: EPAC automatically injects this string into themetadatasection to identify the deployment source.
Managing
deployedBy:- Default Value:
epac/$pacOwnerId/$pacSelector. - Global Override: You can override the default value for all definitions in
global-settings.jsonc. - Local Override (Not Recommended): You can manually add
deployedByto a specific policy definition file to override the global/default value for that definition only.
Choose the right scope exclusion method
mainWhen you need to exclude a scope from a
policyAssignment, choose a method based on your specific requirement:- Periodic Review Required: Use Exemptions. This leverages Azure's native functionality to manage reviews and can include an
ExpiresOndate. - Descope specific items within a
policySetDefinition: UseNotScopewithin thepolicyAssignment. This allows you to change the effect for specific policy definitions inside a set (e.g., exempting one specific service from a larger security initiative). - Sweeping changes for all assignments: Use
globalNotScopesin the Global Settings file. This is useful for blocking all inheritance for policies delivered by EPAC across a wide scope. - Exclude from Desired State Enforcement: Use Desired State Adjustments in the Global Settings file. This allows assignments to be deployed in a scope without being affected by the
"desiredState":{"strategy":"full"}configuration. - Remove from EPAC management entirely: Define the scope in the Global Settings file to remove it from EPAC management.
- Periodic Review Required: Use Exemptions. This leverages Azure's native functionality to manage reviews and can include an
Understand how EPAC generates exemption names and display names
mainWhen defining exemptions using Option A (Policy Definition IDs/Names), Option C (Policy Set IDs/Names), or when using
scopes, EPAC automatically generates uniquename,displayName, anddescriptionvalues to ensure they are readable and unique across different assignments.Naming Logic
name: Generated by concatenating the providednamewith a dash-and the Assignmentname(the last part of thepolicyAssignmentId).displayNameanddescription: Generated by concatenating the provideddisplayName/descriptionwith a space-dash-space (-), followed by the last part of the scope or the human-readable name (if using thehumanReadableName:prefix).
Example: Using
policyDefinitionIdandscopesIf you provide a definition file like this:
{ "exemptions": [ { "name": "short-name", "displayName": "Descriptive name", "description": "More details", "exemptionCategory": "Waiver", "scopes": [ "/subscriptions/11111111-2222-3333-4444-555555555555", "/subscriptions/11111111-2222-3333-4444-555555555556/resourceGroups/resourceGroupName1" ], "policyDefinitionId": "/providers/microsoft.authorization/policyDefinitions/00000000-0000-0000-0000-000000000000" } ] }EPAC generates the following for the resource group scope:
name:short-name-assignmentNamedisplayName:Descriptive name - resourceGroupName1 - assignmentNamedescription:More details - resourceGroupName1 - assignmentName
Use Exemptions for periodic reviews
mainExemptions are the preferred method when you need to review the validity of an exclusion periodically.
Key Characteristics:
- Location: Defined in the
./Definitions/policyExemptions/[pacSelectorName]directory using management files. - Format: JSON is recommended over CSV for easier reviews.
- Granularity: Can be filtered within a
policyAssignmentto specificpolicyDefinitionswithin apolicySetDefinitionusingpolicyDefinitionsReferenceIds. - Lifecycle: Supports the Azure native
ExpiresOnproperty for automated periodic review requirements. - Reporting: Can be reported on as exceptions to the specific definitions they are tied to.
- Location: Defined in the
Configure Metadata and deployedBy injection
mainThe
metadatasection of a Policy Set should ideally include acategory(matching standard built-in policy categories) and aversion(semantic versioning).Automatic Injection: EPAC automatically injects a
deployedBystring into themetadatasection.- Default value:
epac/$pacOwnerId/$pacSelector. - Customization: You can override the default value in
global-settings.jsonc.
Warning: Adding
deployedBymanually to a Policy definition file will override the value provided byglobal-settings.jsoncor the default for that specific definition only.- Default value:
When to use Manual Configuration
mainManual configuration is used when the EPAC Hydration Kit does not meet specific requirements. Use this approach for:
- Complex multi-tenant scenarios
- Custom folder structures or naming conventions
- Advanced customization requirements
- Specific compliance or organizational constraints
Note: It is recommended to try the Hydration Kit first and customize the generated configuration before committing to a manual setup.
How to use overrides for custom management group structures
mainIn EPAC v11, if your environment does not follow the standard Azure Landing Zones (ALZ) management group structure, you can use the
overrideskey in your policy structure file to define custom archetypes and map them to your specific management groups.1. Define Custom Archetypes
Use the
overrides.archetypes.customkey. Settypeto"new"to create entirely new archetypes. Each archetype defines a list ofpolicy_assignments.2. Map Archetypes to Management Groups
Use the
managementGroupNameMappingskey to map your custom archetype names to actual Azure Management Group resource IDs. Thevaluecan be a single string or an array of strings.3. Run the Sync
When running the sync command, you must include the
-EnableOverridesparameter.{ "overrides":{ "archetypes": { "custom": [ { "name": "production", "type": "new", "policy_assignments": [ "Audit-PeDnsZones", "Deny-HybridNetworking" ] } ] } }, "managementGroupNameMappings": { "production": { "management_group_function": "Production", "value": "/providers/Microsoft.Management/managementGroups/prod" } } }Sync-ALZPolicyFromLibrary.ps1 -DefinitionsRootFolder .\Definitions\ -Type ALZ -PacEnvironmentSelector epac-dev -EnableOverridesChoose an Exemption Method (Options A, B, or C)
mainEPAC provides three ways to specify which policy or policy set to exempt. Choosing the right one depends on your goal.
Option A: Policy Definition IDs or Names (Recommended)
Best for new exemptions. It creates one exemption per Assignment containing the Policy definition.
- Use
policyDefinitionIdfor built-in definitions. - Use
policyDefinitionNamefor custom definitions (In CSV, usepolicyDefinitions/{{policyDefinitionName}}in theassignmentReferenceIdcolumn). - Note:
policyDefinitionReferenceIdsmust be empty/omitted.
Option B: Policy Assignment ID
The traditional method. Creates one exemption for a specific assignment.
- Use
policyAssignmentId(e.g.,/providers/Microsoft.Management/managementGroups/.../providers/Microsoft.Authorization/policyAssignments/...). - For Policy Set Assignments, you can use
policyDefinitionReferenceIdsto exempt specific policies within that set.
Option C: Policy Set Definition IDs or Names
Useful for exempting multiple policies within a Policy Set using a single exemption.
- Use
policySetDefinitionIdorpolicySetDefinitionName. - For custom sets in CSV, use
policySetDefinitions/{{policySetDefinitionName}}in theassignmentReferenceIdcolumn. - Can be used with
policyDefinitionReferenceIdsto target a subset of the set.
- Use