Skip to content

CI/CD Overview

EPAC is written in PowerShell and any CI/CD tool with the ability to execute PowerShell can be used. The starter kits currently include pipeline definitions for Azure DevOps, GitHub Actions and GitLab.

This repository contains starter pipelines and instructions for can be found here:

General EPAC Deployment Steps

EPAC has three major steps in the deployment process for each environment. - Build Deployment Plans - Policy Deployment - Role Deployment

Each step can be called by using the EnterprisePolicyAsCode PowerShell module (recommended), or calling the script directly. For more details on EPAC installation options, please refer to the Start Implementation section.

Tip

EPAC is declarative and idempotent: this means, that regardless how many times it is run, EPAC will always push all changes that were implemented in the JSON files to the Azure environment, i.e. if a JSON file is newly created/updated/deleted, EPAC will create/update/delete the Policy and/or Policy Set and/or Policy Assignments definition in Azure. If there are no changes, EPAC can be run any number of times, as it won't make any changes to Azure.

Build Deployment Plans

Analyzes changes in Policy definition, Policy Set definition, Policy Assignment & Policy Exemption files for a given environment. It calculates and displays any deltas, while creating the deployment plan(s) to apply any changes. A "Policy Plan" will be created for use by the Policy Deployment step if any changes are found to the policy objects, assignments, or exemptions while a "Role Plan" will be created for use by the Role deployment step should there be any changes to role assignments for the deployed policies. If no changes are found, no plans are created.

For saving the output related to Build-DeploymentPlans there is global variable called $epacInfoStream which captures all output from the commands. If required, this can be used as a PR message or to present a summary of the plan.

Deployment Mechanism

Deployment Mode Command/Script
Module (Recommended) Build-DeploymentPlans
Script Build-DeploymentPlans.ps1

Parameters

Parameter Explanation
PacEnvironmentSelector Selects the EPAC environment for this plan. If omitted, interactively prompts for the value.
DefinitionsRootFolder Definitions folder path. Defaults to environment variable $env:PAC_DEFINITIONS_FOLDER or ./Definitions. It must contain the file global-settings.jsonc.
Interactive Defaults to $false.
OutputFolder Output folder path for plan files. Defaults to environment variable $env:PAC_OUTPUT_FOLDER or ./Output.
DevOpsType If set, outputs variables consumable by conditions in a DevOps pipeline. Default: not set.
BuildExemptionsOnly If set, only builds the Exemptions plan. This useful to fast-track Exemption when utilizing Release Flow Default: not set.
SkipExemptions If set exemptions will not be built as part of the plan.
DetailedOutput Displays detailed policy change information.
SuppressVersionUpdateInformation Suppresses the default informational reporting about available major version updates for built-in Policy and Policy Set definitions.
AutoUpgradeMajorVersions Plans an upgrade to the latest major version for built-in Policy and Policy Set Assignments which do not specify definitionVersion in the assignment files. Explicitly versioned Assignments are never upgraded automatically. Planned automatic upgrades are reported as warnings.
ReportMajorVersionUpdates Deprecated compatibility switch. Major version update information is now reported by default; use SuppressVersionUpdateInformation to disable it.

Built-in definition major versions

By default, Build-DeploymentPlans checks every managed Assignment which uses a built-in Policy or Policy Set definition. Available major version updates are reported at information level. Version status is diagnostic information and is not written to the Policy Plan in the output folder.

Azure stamps {latestMajor}.*.* onto an Assignment created without definitionVersion. The Assignment then automatically receives minor and patch updates within that major version, but it does not automatically move to a later major version.

Use -SuppressVersionUpdateInformation to hide the informational version report. This does not suppress warnings generated by -AutoUpgradeMajorVersions.

Use -AutoUpgradeMajorVersions to add Assignment updates to the plan when all of the following are true:

  • The Assignment uses a built-in Policy or Policy Set definition.
  • The assignment file does not specify definitionVersion.
  • Azure has stamped the deployed Assignment with an older major version.
  • A newer major version is currently published.

The planned Assignment is set to {latestMajor}.*.*, so it continues to receive minor and patch updates within the new major version. An Assignment which specifies definitionVersion in the assignment file is never changed by this switch, even when a newer major version exists.

# Report available major versions at information level (default behavior)
Build-DeploymentPlans -PacEnvironmentSelector "test"

# Suppress informational version reporting
Build-DeploymentPlans -PacEnvironmentSelector "test" -SuppressVersionUpdateInformation

# Plan upgrades for unversioned Assignments and report those changes as warnings
Build-DeploymentPlans -PacEnvironmentSelector "test" -AutoUpgradeMajorVersions

-ReportMajorVersionUpdates is retained for compatibility with existing pipelines but is no longer required.

Policy Deployment

Deploys Policies, Policy Sets, Policy Assignments, and Policy Exemptions at their desired scope based on the plan.

Deployment Mechanism

Deployment Mode Command/Script
Module (Recommended) Deploy-PolicyPlan
Script Deploy-PolicyPlan.ps1

Parameters

Parameter Explanation
PacEnvironmentSelector Selects the EPAC environment for this plan. If omitted, interactively prompts for the value.
DefinitionsRootFolder Definitions folder path. Defaults to environment variable $env:PAC_DEFINITIONS_FOLDER or ./Definitions. It must contain the file global-settings.jsonc.
Interactive Defaults to $false.
InputFolder Input folder path for plan files. Defaults to environment variable $env:PAC_INPUT_FOLDER, $env:PAC_OUTPUT_FOLDER or ./Output.
SkipExemptions If set, Policy Exemptions will not be deployed.

Role Deployment

Creates the role assignments for the Managed Identities required for DeployIfNotExists and Modify Policies.

Deployment Mechanism

Deployment Mode Command/Script
Module (Recommended) Deploy-RolesPlan
Script Deploy-RolesPlan.ps1

Parameters

Parameter Explanation
PacEnvironmentSelector Selects the EPAC environment for this plan. If omitted, interactively prompts for the value.
DefinitionsRootFolder Definitions folder path. Defaults to environment variable $env:PAC_DEFINITIONS_FOLDER or ./Definitions. It must contain the file global-settings.jsonc.
Interactive Defaults to $false.
InputFolder Input folder path for plan files. Defaults to environment variable $env:PAC_INPUT_FOLDER, $env:PAC_OUTPUT_FOLDER or ./Output.

Create Azure DevOps Pipelines or GitHub Workflows from Starter Pipelines.

Starter Pipelines have been created to orchestrate the EPAC deployment steps listed above. The scripts New-PipelinesFromStarterKit create Azure DevOps Pipelines or GitHub Workflows from the starter kit. You select the type of pipeline to create, the branching flow to implement, and the ScriptType to use. - The starter kits support two branching/release strategies (GitHub and Release). More details on these branching flows refer to the Branching Flow Guidance. - The recommended ScriptType is module, which utilizes the EnterprisePolicyAsCode Powershell module. For more details on EPAC installation options, please refer to the Start Implementation section.

Azure DevOps Pipelines

The following commands create Azure DevOps Pipelines from the starter kit; use one of the commands:

New-PipelinesFromStarterKit -StarterKitFolder .\StarterKit -PipelinesFolder .\pipelines -PipelineType AzureDevOps -BranchingFlow GitHub -ScriptType script
New-PipelinesFromStarterKit -StarterKitFolder .\StarterKit -PipelinesFolder .\pipelines -PipelineType AzureDevOps -BranchingFlow Release -ScriptType script
New-PipelinesFromStarterKit -StarterKitFolder .\StarterKit -PipelinesFolder .\pipelines -PipelineType AzureDevOps -BranchingFlow GitHub -ScriptType module
New-PipelinesFromStarterKit -StarterKitFolder .\StarterKit -PipelinesFolder .\pipelines -PipelineType AzureDevOps -BranchingFlow Release -ScriptType module

GitHub Workflows

The following commands create GitHub Workflows from the starter kit; use one of the commands:

New-PipelinesFromStarterKit -StarterKitFolder .\StarterKit -PipelinesFolder .\.github/workflows -PipelineType GitHubActions -BranchingFlow GitHub -ScriptType script
New-PipelinesFromStarterKit -StarterKitFolder .\StarterKit -PipelinesFolder .\.github/workflows -PipelineType GitHubActions -BranchingFlow Release -ScriptType script
New-PipelinesFromStarterKit -StarterKitFolder .\StarterKit -PipelinesFolder .\.github/workflows -PipelineType GitHubActions -BranchingFlow GitHub -ScriptType module
New-PipelinesFromStarterKit -StarterKitFolder .\StarterKit -PipelinesFolder .\.github/workflows -PipelineType GitHubActions -BranchingFlow Release -ScriptType module

General Hardening Guidelines

  • Least Privilege: Use the least privilege principle when assigning roles to the SPNs used in the CI/CD pipeline. The roles should be assigned at the root or pseudo-root management group level. For more details on the SPNs to use and required permissions refer to App Registrations Setup
  • Require a Pull Request for changes to the main branch. This ensures that changes are reviewed before deployment.
  • Require additional reviewers for yml pipeline and script changes.
  • Require branches to be in a folder feature to prevent accidental deployment of branches.
  • Require an approval step between the Plan stage/job and the Deploy stage/job. This ensures that the changes are reviewed before deployment.
  • [Optional] Require an approval step between the Deploy stage/job and the Role Assignments stage/job. This ensures that the role assignments are reviewed before deployment.
  • For Release Flow only: allow only privileged users to create releases-prod and releases-exemptions-only branches and require those branches to be created from the main branch only.