Skip to content

Commit 4b8dd0d

Browse files
anwatherAnthony Watherston
and
Anthony Watherston
authored
Feature/aw/p 10 6 1 (#763)
* Remove suppress documentation * Check for reference ID's --------- Co-authored-by: Anthony Watherston <Anthony.Watherston@microsoft.com>
1 parent 75a8c58 commit 4b8dd0d

File tree

5 files changed

+78
-64
lines changed

5 files changed

+78
-64
lines changed

Docs/operational-scripts.md

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@ This script executes all remediation tasks in a Policy as Code environment speci
1515

1616
#### Links
1717

18-
- [Remediate non-compliant resources with Azure Policy](https://learn.microsoft.com/en-us/azure/governance/policy/how-to/remediate-resources?tabs=azure-portal)
19-
- [Start-AzPolicyRemediation](https://learn.microsoft.com/en-us/powershell/module/az.policyinsights/start-azpolicyremediation?view=azps-10.1.0)
18+
* [Remediate non-compliant resources with Azure Policy](https://learn.microsoft.com/en-us/azure/governance/policy/how-to/remediate-resources?tabs=azure-portal)
19+
* [Start-AzPolicyRemediation](https://learn.microsoft.com/en-us/powershell/module/az.policyinsights/start-azpolicyremediation?view=azps-10.1.0)
2020

2121
## Documenting Policy
2222

2323
`Build-PolicyDocumentation` builds documentation from instructions in the `policyDocumentations` folder reading the deployed Policy Resources from the EPAC environment. It is also used to generate parameter/effect CSV files for Policy Assignment files. See usage documentation in [Documenting Policy](operational-scripts-documenting-policy.md).
2424

2525
## Policy Resources Exports
2626

27-
- `Export-AzPolicyResources` exports Azure Policy resources in EPAC. It also generates documentation for the exported resources (can be suppressed with `-SuppressDocumentation`). See usage documentation in [Extract existing Policy Resources](start-extracting-policy-resources.md).
28-
- `Get-AzExemptions` retrieves Policy Exemptions from an EPAC environment and saves them to files.
29-
- `Get-AzPolicyAliasOutputCSV` exports Policy Aliases to CSV format.
27+
* `Export-AzPolicyResources` exports Azure Policy resources in EPAC. See usage documentation in [Extract existing Policy Resources](start-extracting-policy-resources.md).
28+
* `Get-AzExemptions` retrieves Policy Exemptions from an EPAC environment and saves them to files.
29+
* `Get-AzPolicyAliasOutputCSV` exports Policy Aliases to CSV format.
3030

3131
## Hydration Kit
3232

@@ -36,36 +36,36 @@ The Hydration Kit is a set of scripts that can be used to deploy an EPAC environ
3636

3737
The scripts `New-AzureDevOpsBug` and `New-GitHubIssue` create a Bug or Issue when there are one or multiple failed Remediation Tasks.
3838

39-
4039
## Export from AzAdvertizer
4140

42-
The script `Export-AzAdvertizer.ps1` creates for you the policyAssignments, policyDefinitions, and policySetDefinitions based on the provided URL in an Output folder under 'ALZ-Export'.
41+
The script `Export-AzAdvertizerPolicy.ps1` creates for you the policyAssignments, policyDefinitions, and policySetDefinitions based on the provided URL in an Output folder under 'ALZ-Export'.
4342

4443
Parameters:
45-
- **AzAdvertizerUrl**: Mandatory url of the policy or policy set from AzAdvertizer.
4644

47-
- **OutputFolder**: Output Folder. Defaults to the path 'Output'.
48-
49-
- **AutoCreateParameters**: Automatically create parameters for Azure Policy Sets and Assginment Files.
45+
* **AzAdvertizerUrl**: Mandatory url of the policy or policy set from AzAdvertizer.
46+
47+
* **OutputFolder**: Output Folder. Defaults to the path 'Output'.
5048

51-
- **UseBuiltIn**: Default to using builtin policies rather than local versions.
49+
* **AutoCreateParameters**: Automatically create parameters for Azure Policy Sets and Assginment Files.
5250

53-
- **Scope**: Used to set scope value on each assignment file.
51+
* **UseBuiltIn**: Default to using builtin policies rather than local versions.
5452

55-
- **PacSelector**: Used to set PacEnvironment for each assignment file.
53+
* **Scope**: Used to set scope value on each assignment file.
5654

57-
- **OverwriteOutput**: Used to Overwrite the contents of the output folder with each run. Helpful when running consecutively.
55+
* **PacSelector**: Used to set PacEnvironment for each assignment file.
56+
57+
* **OverwriteOutput**: Used to Overwrite the contents of the output folder with each run. Helpful when running consecutively.
5858

5959
## Non-compliance Reports
6060

6161
`Export-NonComplianceReports` exports non-compliance reports for EPAC environments . It outputs the reports in the `$OutputFolders/non-compliance-reports` folder.
6262

63-
- `summary-by-policy.csv` contains the summary of the non-compliant resources by Policy definition. The columns contain the resource counts.
64-
- `summary-by-resource.csv` contains the summary of the non-compliant resources. The columns contain the number of Policies causing the non-compliance.
65-
- `details-by-policy.csv` contains the details of the non-compliant resources by Policy definition including the non-compliant resource ids. Assignments are combined by Policy definition.
66-
- `details-by-resource.csv` contains the details of the non-compliant resources sorted by Resource id. Assignments are combined by Resource id.
67-
- `full-details-by-assignment.csv` contains the details of the non-compliant resources sorted by Policy Assignment id.
68-
- `full-details-by-resource.csv` contains the details of the non-compliant resources sorted by Resource id including the Policy Assignment details.
63+
* `summary-by-policy.csv` contains the summary of the non-compliant resources by Policy definition. The columns contain the resource counts.
64+
* `summary-by-resource.csv` contains the summary of the non-compliant resources. The columns contain the number of Policies causing the non-compliance.
65+
* `details-by-policy.csv` contains the details of the non-compliant resources by Policy definition including the non-compliant resource ids. Assignments are combined by Policy definition.
66+
* `details-by-resource.csv` contains the details of the non-compliant resources sorted by Resource id. Assignments are combined by Resource id.
67+
* `full-details-by-assignment.csv` contains the details of the non-compliant resources sorted by Policy Assignment id.
68+
* `full-details-by-resource.csv` contains the details of the non-compliant resources sorted by Resource id including the Policy Assignment details.
6969

7070
### Sample `summary-by-policy.csv`
7171

@@ -80,4 +80,3 @@ Parameters:
8080
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
8181
| /subscriptions/******************************** | ******************************** | PAC-DEV-001 | | subscriptions | | | 25 | 481 | 0 | 0 | 0 | 0 |
8282
| /subscriptions/********************************/providers/microsoft.authorization/roledefinitions/0b00bc79-2207-410c-b9d5-d5d182ad514f | ******************************** | PAC-DEV-001 | | microsoft.authorization/roledefinitions | 0b00bc79-2207-410c-b9d5-d5d182ad514f | | 0 | 0 | 0 | 0 | 0 | 0 |
83-

Scripts/Helpers/Build-AssignmentDefinitionAtLeaf.ps1

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,14 @@ function Build-AssignmentDefinitionAtLeaf {
196196
}
197197
foreach ($nonComplianceMessageRaw in $nonComplianceMessagesList) {
198198
if ($null -eq $nonComplianceMessageRaw.message -or $nonComplianceMessageRaw.message -eq "") {
199-
Write-Error " Leaf Node $($nodeName): each nonComplianceMessage must conatin a message string: $($nonComplianceMessageRaw | ConvertTo-Json -Depth 100 -Compress)"
199+
Write-Error " Leaf Node $($nodeName): each nonComplianceMessage must contain a message string: $($nonComplianceMessageRaw | ConvertTo-Json -Depth 100 -Compress)"
200+
$hasErrors = $true
201+
}
202+
}
203+
204+
foreach ($referenceId in $nonComplianceMessagesList.policyDefinitionReferenceId) {
205+
if ($referenceId -notin $CombinedPolicyDetails.policySets[$definitionEntry.policyDefinitionId].policyDefinitions.policyDefinitionReferenceId) {
206+
Write-Error " Reference Id $referenceId in nonComplianceMessages is not found in the policy definition: $($definitionEntry.policyDefinitionId)"
200207
$hasErrors = $true
201208
}
202209
}

Scripts/Helpers/Out-DocumentationForPolicyAssignments.ps1

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,15 +287,15 @@ function Out-DocumentationForPolicyAssignments {
287287
$null = $allLines.Add("`n$leadingHeadingHashtag# Policy Effects by Policy`n")
288288
$null = $allLines.Add("| Category | Policy | Group Names |$addedTableHeader")
289289
$null = $allLines.Add("| :------- | :----- | :---------- |$addedTableDivider")
290-
$null = $assignmentsByCategoryHeader.Add("`n$leadingHeadingHashtag# Security Controls by Policy`n")
290+
$null = $assignmentsByCategoryHeader.Add("`n$leadingHeadingHashtag# Policy Effects by Policy`n")
291291
$null = $assignmentsByCategoryHeader.Add("| Category | Policy | Group Names |$addedTableHeader")
292292
$null = $assignmentsByCategoryHeader.Add("| :------- | :----- | :---------- |$addedTableDivider")
293293
}
294294
else {
295295
$null = $allLines.Add("`n$leadingHeadingHashtag# Policy Effects by Policy`n")
296296
$null = $allLines.Add("| Category | Policy |$addedTableHeader")
297297
$null = $allLines.Add("| :------- | :----- |$addedTableDivider")
298-
$null = $assignmentsByCategoryHeader.Add("`n$leadingHeadingHashtag# Security Controls by Policy`n")
298+
$null = $assignmentsByCategoryHeader.Add("`n$leadingHeadingHashtag# Policy Effects by Policy`n")
299299
$null = $assignmentsByCategoryHeader.Add("| Category | Policy |$addedTableHeader")
300300
$null = $assignmentsByCategoryHeader.Add("| :------- | :----- |$addedTableDivider")
301301
}
@@ -448,10 +448,21 @@ function Out-DocumentationForPolicyAssignments {
448448
# Add to main markdown
449449
$null = $allLines.Add("| $($_.category) | **$($_.displayName)**$($inTableAfterDisplayNameBreak)$($_.description) |$($addedParametersColumns)")
450450
# Add to sub-page markdown
451-
if ($assignmentsByCategory.ContainsKey($_.category)) {
452-
$assignmentsByCategory[$_.category].subLines += "| $($_.category) | **$($_.displayName)**$($inTableAfterDisplayNameBreak)$($_.description) |$($addedParametersColumns)"
451+
if ($assignmentsByCategory.ContainsKey($_.category)) {
452+
if ($assignmentsByCategory[$_.category].subLines -match "Policy Parameters by Policy") {
453+
$assignmentsByCategory[$_.category].subLines += "| $($_.category) | **$($_.displayName)**$($inTableAfterDisplayNameBreak)$($_.description) |$($addedParametersColumns)"
454+
}
455+
else {
456+
$null = $assignmentsByCategory[$_.category].subLines += "`n$leadingHeadingHashtag# Policy Parameters by Policy`n"
457+
$null = $assignmentsByCategory[$_.category].subLines += "| Category | Policy |$addedTableHeader"
458+
$null = $assignmentsByCategory[$_.category].subLines += "| :------- | :----- |$addedTableDividerParameters"
459+
$assignmentsByCategory[$_.category].subLines += "| $($_.category) | **$($_.displayName)**$($inTableAfterDisplayNameBreak)$($_.description) |$($addedParametersColumns)"
460+
}
453461
}
454462
else {
463+
$null = $assignmentsByCategory[$_.category].subLines += "`n$leadingHeadingHashtag# Policy Parameters by Policy`n"
464+
$null = $assignmentsByCategory[$_.category].subLines += "| Category | Policy |$addedTableHeader"
465+
$null = $assignmentsByCategory[$_.category].subLines += "| :------- | :----- |$addedTableDividerParameters"
455466
$assignmentsByCategory[$_.category] = @{}
456467
$assignmentsByCategory[$_.category].subLines = $assignmentsByCategoryHeader
457468
$assignmentsByCategory[$_.category].subLines += "| $($_.category) | **$($_.displayName)**$($inTableAfterDisplayNameBreak)$($_.description) |$($addedParametersColumns)"

Scripts/Operations/Export-AzAdvertizerPolicy.ps1

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ param (
4444
[string] $OutputFolder,
4545

4646
[Parameter(Mandatory = $false, HelpMessage = "Automatically create parameters for Azure Policy Sets and Assginment Files")]
47-
[bool] $AutoCreateParameters = $false,
47+
[bool] $AutoCreateParameters = $true,
4848

4949
[Parameter(Mandatory = $false, HelpMessage = "Default to using builtin policies rather than local versions")]
5050
[bool] $UseBuiltIn = $true,
@@ -61,33 +61,40 @@ param (
6161

6262
#region Policy
6363

64+
# Validate session with Azure exists
65+
if (-not (Get-AzContext)) {
66+
$null = Connect-AzAccount
67+
}
68+
69+
# Pull HTML
70+
try {
71+
$restResponse = Invoke-RestMethod -Uri "$AzAdvertizerUrl" -Method Get
72+
}
73+
catch {
74+
if ($_.Exception.Response.StatusCode -lt 200 -or $_.Exception.Response.StatusCode -ge 300) {
75+
Write-Error "Error gathering Policy Information, please validate AzAdvertizerUrl is valid." -ErrorAction Stop
76+
}
77+
}
78+
6479
# Determine if PolicySet or Policy Assignment
6580
if ($AzAdvertizerUrl -match "azpolicyadvertizer") {
6681
$policyType = "policyDefinitions"
82+
# Pull Built-In Policies and Policy Sets
83+
$builtInPolicies = Get-AzPolicyDefinition -Builtin
84+
$builtInPolicyNames = $builtInPolicies.name
6785
}
6886
elseif ($AzAdvertizerUrl -match "azpolicyinitiativesadvertizer") {
6987
$policyType = "policySetDefinitions"
88+
# Pull Built-In Policies and Policy Sets
89+
$builtInPolicies = Get-AzPolicyDefinition -Builtin
90+
$builtInPolicyNames = $builtInPolicies.name
91+
$builtInPolicySets = Get-AzPolicySetDefinition -Builtin
92+
$builtInPolicySetNames = $builtInPolicySets.name
7093
}
7194
else {
7295
Write-Error "AzAdvertizerUrl is not referencing Policy or Policy Initiative"
7396
}
7497

75-
# Pull Built-In Policies and Policy Sets
76-
$builtInPolicies = Get-AzPolicyDefinition -Builtin
77-
$builtInPolicyNames = $builtInPolicies.name
78-
$builtInPolicySets = Get-AzPolicySetDefinition -Builtin
79-
$builtInPolicySetNames = $builtInPolicySets.name
80-
81-
# Pull HTML
82-
try {
83-
$restResponse = Invoke-RestMethod -Uri "$AzAdvertizerUrl" -Method Get
84-
}
85-
catch {
86-
if ($_.Exception.Response.StatusCode -eq 404) {
87-
Write-Error "Error 404: Not Found." -ErrorAction Stop
88-
}
89-
}
90-
9198
# Parse HTML response to find copyEPACDef
9299
Write-Information "" -InformationAction Continue
93100
$response = $restResponse.split("function copyEPACDef() ")[1]
@@ -133,16 +140,11 @@ if ($OutputFolder -eq "") {
133140
$OutputFolder = "Output"
134141
}
135142
if ($OverwriteOutput) {
136-
if (Test-Path -Path "$OutputFolder/ALZ-Export/policyDefinitions") {
137-
Get-ChildItem -Path "$OutputFolder/ALZ-Export/policyDefinitions" -File | Remove-Item
138-
}
139-
if (Test-Path -Path "$OutputFolder/ALZ-Export/policyAssignments") {
140-
Get-ChildItem -Path "$OutputFolder/ALZ-Export/policyAssignments" -File | Remove-Item
141-
}
142-
if (Test-Path -Path "$OutputFolder/ALZ-Export/policySetDefinitions") {
143-
Get-ChildItem -Path "$OutputFolder/ALZ-Export/policySetDefinitions" -File | Remove-Item
143+
if (Test-Path -Path "$OutputFolder/ALZ-Export") {
144+
Remove-Item -Path "$OutputFolder/ALZ-Export" -Recurse -Force
144145
}
145146
}
147+
146148
# Export File
147149
if ($policyType -eq "policyDefinitions") {
148150
if ($UseBuiltIn -and $builtInPolicyNames -contains $policyName) {
@@ -317,7 +319,7 @@ if ($AutoCreateParameters) {
317319
if ($UseBuiltIn) {
318320
if ($policyType -eq "policySetDefinitions" -and $builtInPolicySetNames -contains $policyName) {
319321
$policyObject = $builtInPolicySets | Where-Object { $_.Name -eq $policyName }
320-
$policySetParameters = $policyObject.properties.parameters
322+
$policySetParameters = $policyObject.parameter
321323
$parameterNames = $policySetParameters | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
322324
foreach ($parameter in $parameterNames) {
323325
$defaultEffect = ""
@@ -332,15 +334,15 @@ if ($AutoCreateParameters) {
332334
}
333335
elseif ($policyType -eq "policyDefinitions" -and $builtInPolicyNames -contains $policyName) {
334336
$policyObject = $builtInPolicies | Where-Object { $_.Name -eq $policyName }
335-
$policyParameters = $policyObject.properties.parameters
337+
$policyParameters = $policyObject.parameter
336338
$parameterNames = $policyParameters | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
337339
foreach ($parameter in $parameterNames) {
338340
$defaultEffect = ""
339-
if ($null -eq $($policySetParameters).$($parameter).defaultValue) {
341+
if ($null -eq $($policyParameters).$($parameter).defaultValue) {
340342
Write-Warning "Default Value not found for '$parameter' in PolicySet '$policyName'" -InformationAction Continue
341343
}
342344
else {
343-
$defaultEffect = $($policySetParameters).$($parameter).defaultValue
345+
$defaultEffect = $($policyParameters).$($parameter).defaultValue
344346
}
345347
$assignmentObject.children.parameters | Add-Member -MemberType NoteProperty -Name "$parameter" -Value $defaultEffect
346348
}

Scripts/Operations/Export-AzPolicyResources.ps1

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
Exports Azure Policy resources in EPAC format or raw format.
44
55
.DESCRIPTION
6-
Exports Azure Policy resources in EPAC format or raw format. It has 4 operating modes - see -Mode parameter for details.
7-
It also generates documentation for the exported resources (can be suppressed with -SuppressDocumentation).
8-
To just generate EPAC formatted Definitions without generating documentation files, use -supressEpacOutput.
6+
Exports Azure Policy resources in EPAC format or raw format. It has 5 operating modes - see -Mode parameter for details.
97
108
.PARAMETER DefinitionsRootFolder
119
Definitions folder path. Defaults to environment variable $env:PAC_DEFINITIONS_FOLDER or './Definitions'.
@@ -40,9 +38,6 @@ Operating mode:
4038
Limits the collection to one EPAC environment, useful for non-interactive use in a multi-tenant scenario, especially with -Mode 'collectRawFile'.
4139
The default is '*' which will execute all EPAC-Environments.
4240
43-
.PARAMETER SuppressDocumentation
44-
Suppress documentation generation.
45-
4641
.PARAMETER SuppressEpacOutput
4742
Suppress output generation in EPAC format.
4843
@@ -103,8 +98,8 @@ param (
10398
")]
10499
[string] $InputPacSelector = '*',
105100

106-
[Parameter(Mandatory = $false, HelpMessage = "Suppress documentation generation")]
107-
[switch] $SuppressDocumentation,
101+
# [Parameter(Mandatory = $false, HelpMessage = "Suppress documentation generation")]
102+
# [switch] $SuppressDocumentation,
108103

109104
[Parameter(Mandatory = $false, HelpMessage = "Suppress output generation in EPAC format")]
110105
[switch] $SuppressEpacOutput,

0 commit comments

Comments
 (0)