Skip to content

Commit

Permalink
Bugs 2024 04 11 (#551)
Browse files Browse the repository at this point in the history
* Bug fixes

* Strange behavior
  • Loading branch information
techlake authored Apr 12, 2024
1 parent e1b5be1 commit 622ab9c
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 54 deletions.
5 changes: 4 additions & 1 deletion Docs/ci-cd-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ New-PipelinesFromStarterKit -StarterKitFolder .\StarterKit -PipelinesFolder .\.g

## Developing Policy Resources in a Feature Branch

Developing Policy resources is the dame for `GitHub Flow` and `Release Flow`. The following steps are recommended:
Developing Policy resources is the same for `GitHub Flow` and `Release Flow`. The following steps are recommended:

1. Developers create feature branches from `main` branch with a name `feature/*user-id*/*feature-name*`.
2. Developers create or update Policy definitions, Policy Set definitions, Policy Assignment, amd Policy Exemptions files in the `Definitions` folder. Developers push changes to the feature branch.
Expand Down Expand Up @@ -156,13 +156,16 @@ Furthermore, it shows the consumption of the `Definitions` files by script Build

Analyzes changes in Policy definition, Policy Set definition, and Policy Assignment files. It calculates a plan to apply deltas. The deployment scripts are **declarative** and **idempotent**: this means, that regardless how many times they are run, they 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, the pipeline will create/update/delete the Policy and/or Policy Set and/or Policy Assignments definition in Azure. If there are no changes, the pipeline can be run any number of times, as it won't make any changes to Azure.

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

|Parameter | Explanation |
|----------|-------------|
| `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 [Microsoft Release Flow](#advanced-cicd-with-microsoft-release-flow) Default: not set. |
| `VirtualCores` | Number of (virtual) cores available to calculate the deployment plan. Defaults to 4. |


### Deploy-PolicyPlan.ps1

Deploys Policies, Policy Sets, Policy Assignments, and Policy Exemptions at their desired scope based on the plan.
Expand Down
4 changes: 2 additions & 2 deletions Docs/settings-desired-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ After short transitioning period (weeks), it is recommended to set `desiredState

## Exclude Resource Groups

!!! warning "Warning - Breaking Change in v10.0.0"
!!! warning

Policy Assignments at resource groups are **managed** by EPAC. The element `includeResourceGroups` has been deprecated and removed.
**Breaking Change in v10.0.0:** Policy Assignments at resource groups are **managed** by EPAC. The element `includeResourceGroups` has been deprecated and removed.

To exclude resource groups from management by EPAC, add an `excludedScopes` array element with a wild card for the subscription and resourceGroups to `desiredState`.

Expand Down
17 changes: 17 additions & 0 deletions Scripts/Deploy/Remove-AzPolicyExemptionEpac.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
$Scope,

[Parameter(Mandatory = $true)]
$Name,

[Parameter(Mandatory = $false)]
$ApiVersion = "2022-07-01-preview"
)

. "$PSScriptRoot/../Helpers/Add-HelperScripts.ps1"

$id = "$Scope/providers/Microsoft.Authorization/policyExemptions/$Name"

Remove-AzResourceByIdRestMethod -Id $id -ApiVersion $ApiVersion
57 changes: 57 additions & 0 deletions Scripts/Deploy/Set-AzPolicyExemptionEpac.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
$Scope,

[Parameter(Mandatory = $true)]
$Name,

[Parameter(Mandatory = $true)]
$DisplayName,

[Parameter(Mandatory = $false)]
$Description = "description",

[Parameter(Mandatory = $false)]
$ExemptionCategory = "Waiver",

[Parameter(Mandatory = $false)]
$ExpiresOn = $null,

[Parameter(Mandatory = $true)]
$PolicyAssignmentId,

[Parameter(Mandatory = $false)]
$PolicyDefinitionReferenceIds = $null,

[Parameter(Mandatory = $false)]
$AssignmentScopeValidation = "Default",

[Parameter(Mandatory = $false)]
$ResourceSelectors = $null,

[Parameter(Mandatory = $false)]
$Metadata = $null,

[Parameter(Mandatory = $false)]
$ApiVersion = "2022-07-01-preview"
)

. "$PSScriptRoot/../Helpers/Add-HelperScripts.ps1"

$id = "$Scope/providers/Microsoft.Authorization/policyExemptions/$Name"

$exemptionObject = [ordered]@{
id = $id
policyAssignmentId = $PolicyAssignmentId
exemptionCategory = $ExemptionCategory
assignmentScopeValidation = $AssignmentScopeValidation
displayName = $DisplayName
description = $Description
expiresOn = $ExpiresOn
metadata = $Metadata
policyDefinitionReferenceIds = $PolicyDefinitionReferenceIds
resourceSelectors = $ResourceSelectors
}

Set-AzPolicyExemptionRestMethod -ExemptionObj $exemptionObject -ApiVersion $ApiVersion
92 changes: 46 additions & 46 deletions Scripts/Helpers/Out-PolicyAssignmentDocumentationToFile.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -150,58 +150,24 @@ function Out-PolicyAssignmentDocumentationToFile {
#region Markdown

[System.Collections.Generic.List[string]] $allLines = [System.Collections.Generic.List[string]]::new()
[System.Collections.Generic.List[string]] $headerAndToc = [System.Collections.Generic.List[string]]::new()
[System.Collections.Generic.List[string]] $body = [System.Collections.Generic.List[string]]::new()
$null = $allLines.Add("# $title`n")
$null = $allLines.Add("Auto-generated Policy effect documentation across environments '$($environmentCategories -join "', '")' sorted by Policy category and Policy display name.`n")
$null = $allLines.Add("## Table of Contents`n")
$null = $allLines.Add("- [Policy Effects](#policy-effects)")

$allLines.Clear()
$headerAndToc.Clear()
$body.Clear()
#region Policy Effects

#region Overview
$null = $headerAndToc.Add("# $title $markdownOutputType`n")
$null = $headerAndToc.Add("Auto-generated Policy effect documentation across environments '$($environmentCategories -join "', '")' sorted by Policy category and Policy display name.`n")
$null = $headerAndToc.Add("## Table of contents`n")

$null = $headerAndToc.Add("- [Environments](#environments)")
$null = $body.Add("`n## <a id=`"environments`"></a>Environments`n")
$addedTableHeader = ""
$addedTableDivider = ""
foreach ($environmentCategory in $environmentCategories) {
$perEnvironment = $AssignmentsByEnvironment.$environmentCategory
$itemList = $perEnvironment.itemList
$assignmentsDetails = $perEnvironment.assignmentsDetails
$scopes = $perEnvironment.scopes
$null = $body.Add("`n### **$environmentCategory environment**")

$null = $body.Add("`nScopes`n")
foreach ($scope in $scopes) {
$null = $body.Add("- $scope")
}

foreach ($item in $itemList) {
$assignmentId = $item.assignmentId
if ($assignmentsDetails.ContainsKey($assignmentId)) {
# should always be true
$assignmentsDetails = $assignmentsDetails.$assignmentId
$null = $body.Add("`nAssignment $($assignmentsDetails.assignment.displayName)`n")
$null = $body.Add("- PolicySet: $($assignmentsDetails.displayName)")
$null = $body.Add("- Type: $($assignmentsDetails.policyType)")
$null = $body.Add("- Category: $($assignmentsDetails.category)")
$null = $body.Add("- Description: $($assignmentsDetails.description)")
}
}

$null = $allLines.Add("- [Environment Category ``$environmentCategory``](#environment-category-$($environmentCategory.ToLower()))")
# Calculate environment columns
$addedTableHeader += " $environmentCategory |"
$addedTableDivider += " :-----: |"
}

#endregion Overview

$null = $headerAndToc.Add("- [Policy effects across environments](#policy-effects-across-environment)")
$null = $body.Add("`n<br/>`n`n## <a id='policy-effects-across-environment'></a>Policy effects across environment`n`n<br/>`n")
$null = $body.Add("| Category | Policy |$addedTableHeader")
$null = $body.Add("| :------- | :----- |$addedTableDivider")
$null = $allLines.Add("`n## Policy Effects`n")
$null = $allLines.Add("| Category | Policy |$addedTableHeader")
$null = $allLines.Add("| :------- | :----- |$addedTableDivider")

$flatPolicyListAcrossEnvironments.Values | Sort-Object -Property { $_.category }, { $_.displayName } | ForEach-Object -Process {
# Build additional columns
Expand Down Expand Up @@ -256,10 +222,44 @@ function Out-PolicyAssignmentDocumentationToFile {
$sortedGroupNames = $groupNames | Sort-Object -Unique
$additionalInfoFragment += ($sortedGroupNames -join $separator)
}
$null = $body.Add("| $($_.category) | **$($_.displayName)**<br/>$($_.description)$($additionalInfoFragment) | $($addedEffectColumns)")
$null = $allLines.Add("| $($_.category) | **$($_.displayName)**<br/>$($_.description)$($additionalInfoFragment) | $($addedEffectColumns)")
}

#endregion Policy Effects

#region Environment Categories

foreach ($environmentCategory in $environmentCategories) {
$perEnvironment = $AssignmentsByEnvironment.$environmentCategory
$itemList = $perEnvironment.itemList
$assignmentsDetails = $perEnvironment.assignmentsDetails
$scopes = $perEnvironment.scopes
$null = $allLines.Add("`n## Environment Category ``$environmentCategory``")

$null = $allLines.Add("`n### Scopes`n")
foreach ($scope in $scopes) {
$null = $allLines.Add("- $scope")
}

foreach ($item in $itemList) {
$assignmentId = $item.assignmentId
if ($assignmentsDetails.ContainsKey($assignmentId)) {
# should always be true
$assignmentsDetail = $assignmentsDetails.$assignmentId
$null = $allLines.Add("`n### Assignment: ``$($assignmentsDetail.assignment.properties.displayName)```n")
$null = $allLines.Add("| Property | Value |")
$null = $allLines.Add("| :------- | :---- |")
$null = $allLines.Add("| Assignment Id | $($assignmentId) |")
$null = $allLines.Add("| Policy Set | ``$($assignmentsDetail.displayName)`` |")
$null = $allLines.Add("| Policy Set Id | $($assignmentsDetail.policySetId) |")
$null = $allLines.Add("| Type | $($assignmentsDetail.policyType) |")
$null = $allLines.Add("| Category | ``$($assignmentsDetail.category)`` |")
$null = $allLines.Add("| Description | $($assignmentsDetail.description) |")
}
}
}
$null = $allLines.AddRange($headerAndToc)
$null = $allLines.AddRange($body)

#endregion Environment Categories

# Output file
$outputFilePath = "$($OutputPath -replace '[/\\]$', '')/$($fileNameStem).md"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function Set-AzPolicyExemptionRestMethod {
Write-Warning "Ignoring scope locked error: $($statusCode) -- $($content)"
}
else {
Write-Error "Policy Exemption error $($statusCode) -- $($content)" -ErrorAction Continue
Write-Warning "Error, continue deployment: $($statusCode) -- $($content)"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,12 @@ function Set-AzRoleAssignmentRestMethod {
# Process response
$statusCode = $response.StatusCode
if ($statusCode -lt 200 -or $statusCode -ge 300) {
$content = $response.Content
if ($statusCode -eq 409) {
$errorBody = $content | ConvertFrom-Json -Depth 100
Write-Information $errorBody.error.message
Write-Warning "Role assignment already exists (ignore): $($RoleAssignment.assignmentDisplayName)"
}
else {
Write-Error "Role Assignment error $($statusCode) -- $($content)" -ErrorAction Continue
$content = $response.Content
Write-Warning "Error, continue deployment: $($statusCode) -- $($content)"
}
}
}
Loading

0 comments on commit 622ab9c

Please sign in to comment.