Skip to content

Commit

Permalink
Minor cleanup (#307)
Browse files Browse the repository at this point in the history
  • Loading branch information
techlake authored Aug 9, 2023
1 parent bfd2c3a commit e38aa00
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 52 deletions.
41 changes: 24 additions & 17 deletions Docs/export-non-compliance.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# Exporting Non-Compliance Reports

The script `Export-AzPolicyNonCompliance` exports non-compliance reports for EPAC environments in the `global-settings.jsonc` file. It outputs the reports in the `$outputFolders/non-compliance-reports` folder in two files:
The script `Export-AzPolicyNonCompliance` exports non-compliance reports for EPAC environments in the `global-settings.jsonc` file. It outputs the reports in the `$outputFolders/non-compliance-reports` folder:

- `summary.csv` contains the summary of the non-compliant resources including the non-compliant resource count
- `details.csv` contains the details of the non-compliant resources including the non-compliant resource ids
- `summary-by-policy.csv` contains the summary of the non-compliant resources by Policy definition. The columns contain the resource counts.
- `summary-by-resource.csv` contains the summary of the non-compliant resources. The columns contain the number of Policies causing the non-compliance.
- `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.
- `details-by-resource.csv` contains the details of the non-compliant resources sorted by Resource id. Assignments are combined by Resource id.
- `full-details-by-assignment.csv` contains the details of the non-compliant resources sorted by Policy Assignment id.
- `full-details-by-resource.csv` contains the details of the non-compliant resources sorted by Resource id including the Policy Assignment details.

## Script parameters

Expand All @@ -15,9 +19,11 @@ The script `Export-AzPolicyNonCompliance` exports non-compliance reports for EPA
| `WindowsNewLineCells` | Formats CSV multi-object cells to use new lines and saves it as UTF-8 with BOM - works only fro Excel in Windows. Default uses commas to separate array elements within a cell |
| `Interactive` | Set to false if used non-interactive |
| `OnlyCheckManagedAssignments` | Include non-compliance data only for Policy assignments owned by this Policy as Code repo |
| `PolicyDefinitionFilter` | Filter by Policy definition names (array) or ids (array). |
| `PolicySetDefinitionFilter` | Filter by Policy Set definition names (array) or ids (array). Can only be used when PolicyAssignmentFilter is not used. |
| `PolicyAssignmentFilter` | Filter by Policy Assignment names (array) or ids (array). Can only be used when PolicySetDefinitionFilter is not used. |
| `PolicyEffectFilter` | Filter by Policy effect (array). |
| `RemediationOnly` | Filter by Policy Effect "deployifnotexists" and "modify" and compliance status "NonCompliant"

## Examples

Expand Down Expand Up @@ -45,21 +51,22 @@ Export-NonComplianceReports -PolicySetDefinitionFilter "org-sec-initiative", "/p
Export-NonComplianceReports -PolicyAssignmentFilter "/providers/microsoft.management/managementgroups/11111111-1111-1111-1111-111111111111/providers/microsoft.authorization/policyassignments/taginh-env", "prod-asb"
```

## Example output
## Sample Output

### `summary.csv`
### `summary-by-policy.csv`

|Category|Policy|Policy Id|Non-Compliant|Unknown|Exempt|Conflicting|Not-Started|Error|
|-|-|-|-|-|-|-|-|-|
API Management|API Management APIs should use only encrypted protocols|/providers/microsoft.authorization/policydefinitions/ee7495e7-3ba7-40b6-bfee-c29e22cc75d4|1|0|0|0|0|0
API Management|API Management services should use a virtual network|/providers/microsoft.authorization/policydefinitions/ef619a2c-cc4d-4d03-b2ba-8c94a834d85b|1|0|0|0|0|0
App Configuration|App Configuration should use private link|/providers/microsoft.authorization/policydefinitions/ca610c1d-041c-4332-9d88-7ed3094967c7|1|0|0|0|0|0
App Service|App Service apps should have resource logs enabled|/providers/microsoft.authorization/policydefinitions/91a78b24-f231-4a8a-8da9-02c35b2b6510|1|0|0|0|0|0
App Service|App Service apps should only be accessible over HTTPS|/providers/microsoft.authorization/policydefinitions/a4af4a39-4135-47fb-b175-47fbdf85311d|4|0|0|0|0|0
| Category | Policy Name | Policy Id | Non Compliant | Unknown | Not Started | Exempt | Conflicting | Error | Assignment Ids | Group Names |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| General | Audit usage of custom RBAC roles | /providers/microsoft.authorization/policydefinitions/a451c1ef-c6ca-483d-87ed-f49761e3ffb5 | 9 | 0 | 0 | 0 | 0 | 0 | /providers/microsoft.management/managementgroups/pac-heinrich-dev-dev/providers/microsoft.authorization/policyassignments/dev-nist-800-53-r5,/providers/microsoft.management/managementgroups/pac-heinrich-dev-dev/providers/microsoft.authorization/policyassignments/dev-asb | azure_security_benchmark_v3.0_pa-7,nist_sp_800-53_r5_ac-6(7),nist_sp_800-53_r5_ac-2(7),nist_sp_800-53_r5_ac-6,nist_sp_800-53_r5_ac-2 |
| Regulatory Compliance | Control use of portable storage devices | /providers/microsoft.authorization/policydefinitions/0a8a1a7d-16d3-4d8e-9f2c-6b8d9e1c7c1d | 0 | 0 | 0 | 0 | 0 | 0 | /providers/microsoft.management/managementgroups/pac-heinrich-dev-dev/providers/microsoft.authorization/policyassignments/dev-nist-800-53-r5,/providers/microsoft.management/managementgroups/pac-heinrich-dev-dev/providers/microsoft.authorization/policyassignments/dev-asb | azure_security_benchmark_v3.0_pa-7,nist_sp_800-53_r5_ac-6(7),nist_sp_800-53_r5_ac-2(7),nist_sp_800-53_r5_ac-6,nist_sp_800-53_r5_ac-2 |
| Regulatory Compliance | Deploy Azure Policy to audit Windows VMs that do not use managed disks | /providers/microsoft.authorization/policydefinitions/0b2b84f2-eb8a-4f0a-8a1c-0c0d6e4cdeea | 0 | 0 | 0 | 0 | 0 | 0 | /providers/microsoft.management/managementgroups/pac-heinrich-dev-dev/providers/microsoft.authorization/policyassignments/dev-nist-800-53-r5,/providers/microsoft.management/managementgroups/pac-heinrich-dev-dev/providers/microsoft.authorization/policyassignments/dev-asb | azure_security_benchmark_v3.0_pa-7,nist_sp_800-53_r5_ac-6(7),nist_sp_800-53_r5_ac-2(7),nist_sp_800-53_r5_ac-6,nist_sp_800-53_r5_ac-2 |
| Regulatory Compliance | Deploy Azure Policy to audit Windows VMs that do not use managed disks | /providers/microsoft.authorization/policydefinitions/0b2b84f2-eb8a-4f0a-8a1c-0c0d6e4cdeea | 0 | 0 | 0 | 0 | 0 | 0 | /providers/microsoft.management/managementgroups/pac-heinrich-dev-dev/providers/microsoft.authorization/policyassignments/dev-nist-800-53-r5,/providers/microsoft.management/managementgroups/pac-heinrich-dev-dev/providers/microsoft.authorization/policyassignments/dev-asb | azure_security_benchmark_v3.0_pa-7,nist_sp_800-53_r5_ac-6(7),nist_sp_800-53_r5_ac-2(7),nist_sp_800-53_r5_ac-6,nist_sp_800-53_r5_ac-2 |

### `details.csv`
### `summary-by-resource.csv`

|Category|Policy|Effect|State|Resource Id|Policy Id|Group Names|Assignments|
|-|-|-|-|-|-|-|-|
|API Management|API Management APIs should use only encrypted protocols|audit|NonCompliant|/subscriptions/11111111-1111-1111-1111-111111111111/resourcegroups/rg001/providers/microsoft.apimanagement/service/*****|/providers/microsoft.authorization/policydefinitions/ee7495e7-3ba7-40b6-bfee-c29e22cc75d4|azure_security_benchmark_v3.0_dp-3|/providers/microsoft.management/managementgroups/mg-1/providers/microsoft.authorization/policyassignments/prod-asb|
|API Management|API Management calls to API backends should be authenticated|audit|NonCompliant|/subscriptions/11111111-1111-1111-1111-111111111111/resourcegroups/rg001/providers/microsoft.apimanagement/service/*****|/providers/microsoft.authorization/policydefinitions/c15dcc82-b93c-4dcb-9332-fbf121685b54|azure_security_benchmark_v3.0_im-4|/providers/microsoft.management/managementgroups/mg-1/providers/microsoft.authorization/policyassignments/prod-asb|
| Resource Id | Subscription Id | Subscription Name | Resource Group | Resource Type | Resource Name | Resource Qualifier | Non Compliant | Unknown | Not Started | Exempt | Conflicting | Error |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| /subscriptions/******************************** | ******************************** | PAC-DEV-001 | | subscriptions | | | 25 | 481 | 0 | 0 | 0 | 0 |
| /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 |
| /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 |
| /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 |
10 changes: 4 additions & 6 deletions Scripts/Helpers/Build-AssignmentPlan.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ function Build-AssignmentPlan {
# Process each assignment file
foreach ($assignmentFile in $assignmentFiles) {
$Json = Get-Content -Path $assignmentFile.FullName -Raw -ErrorAction Stop
Write-Information ""
# Write-Information ""
if ((Test-Json $Json)) {
Write-Information "Processing file '$($assignmentFile.FullName)'"
# Write-Information "Processing file '$($assignmentFile.FullName)'"
}
else {
Write-Error "Assignment JSON file '$($assignmentFile.FullName)' is not valid." -ErrorAction Stop
Expand Down Expand Up @@ -182,7 +182,7 @@ function Build-AssignmentPlan {
Write-AssignmentDetails -DisplayName $DisplayName -Scope $Scope -Prefix "Update($($IdentityStatus.changedIdentityStrings))" -IdentityStatus $IdentityStatus
}
else {
Write-AssignmentDetails -DisplayName $DisplayName -Scope $Scope -Prefix "Unchanged" -IdentityStatus $IdentityStatus
# Write-AssignmentDetails -DisplayName $DisplayName -Scope $Scope -Prefix "Unchanged" -IdentityStatus $IdentityStatus
}
}
else {
Expand Down Expand Up @@ -265,7 +265,6 @@ function Build-AssignmentPlan {

$strategy = $PacEnvironment.desiredState.strategy
if ($deleteCandidates.psbase.Count -gt 0) {
Write-Information "Cleanup removed Policy Assignments (delete)"
foreach ($id in $deleteCandidates.Keys) {
$deleteCandidate = $deleteCandidates.$id
$deleteCandidateProperties = Get-PolicyResourceProperties $deleteCandidate
Expand All @@ -290,7 +289,7 @@ function Build-AssignmentPlan {
if ($IdentityStatus.isUserAssigned) {
$isUserAssignedAny = $true
}
Write-AssignmentDetails -DisplayName $DisplayName -Scope $Scope -Prefix "" -IdentityStatus $IdentityStatus
Write-AssignmentDetails -DisplayName $DisplayName -Scope $Scope -Prefix "Delete" -IdentityStatus $IdentityStatus
$splat = @{
id = $id
name = $name
Expand All @@ -309,7 +308,6 @@ function Build-AssignmentPlan {
}
}

Write-Information ""
if ($isUserAssignedAny) {
Write-Warning "EPAC does not manage role assignments for Policy Assignments with user-assigned Managed Identities."
}
Expand Down
16 changes: 15 additions & 1 deletion Scripts/Helpers/Convert-PolicySetsToFlatList.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,21 @@ function Convert-PolicySetsToFlatList {
$flatPolicyEntry.effectValue = $effectDefault
$flatPolicyEntry.effectDefault = $effectDefault
}
$effectString = "$($effectDefault) ($($effectReason))"
$effectString = switch ($effectReason) {
"PolicySet Default" {
"$($effectDefault) (default: $($effectParameterName))"
break
}
"PolicySet No Default" {
# Very unnusul to have a policy set effect parameter with no default
"$($effectReason) ($($effectParameterName))"
break
}
default {
"$($effectDefault) ($($effectReason))"
break
}
}
}

$perPolicySet.effectString = $effectString
Expand Down
12 changes: 6 additions & 6 deletions Scripts/Helpers/Find-AzNonCompliantResources.ps1
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
function Find-AzNonCompliantResources {
[CmdletBinding()]
param (
[switch] $RemmediationOnly,
[switch] $RemediationOnly,
$PacEnvironment,
[switch] $OnlyCheckManagedAssignments,
[string[]] $PolicyDefinitionFilter,
Expand All @@ -19,8 +19,8 @@ function Find-AzNonCompliantResources {
if ($PolicyEffectFilter -and $ExcludeManualPolicyEffect) {
Write-Error "Parameter PolicyEffectFilter cannot be used with parameter ExcludeManualPolicyEffect" -ErrorAction Stop
}
elseif ($ExcludeManualPolicyEffect -and $RemmediationOnly) {
Write-Error "Parameter ExcludeManualPolicyEffect cannot be used with parameter RemmediationOnly" -ErrorAction Stop
elseif ($ExcludeManualPolicyEffect -and $RemediationOnly) {
Write-Error "Parameter ExcludeManualPolicyEffect cannot be used with parameter RemediationOnly" -ErrorAction Stop
}
elseif ($ExcludeManualPolicyEffect) {
$effectFilter = " and properties.policyDefinitionAction <> `"manual`""
Expand All @@ -29,7 +29,7 @@ function Find-AzNonCompliantResources {
if ($PolicyEffectFilter -and $PolicyEffectFilter.Count -ne 0) {
$effectFilter = " and ("
foreach ($filterValue in $PolicyEffectFilter) {
if ($RemmediationOnly) {
if ($RemediationOnly) {
if ($filterValue -in @("deployifnotexists", "modify")) {
$effectFilter += "properties.policyDefinitionAction == `"$filterValue`" or "
}
Expand All @@ -48,12 +48,12 @@ function Find-AzNonCompliantResources {
}
$effectFilter = $effectFilter.Substring(0, $effectFilter.Length - 4) + ")"
}
elseif ($RemmediationOnly) {
elseif ($RemediationOnly) {
$effectFilter = " and (properties.policyDefinitionAction == `"deployifnotexists`" or properties.policyDefinitionAction == `"modify`")"
}
}
$query = ""
if ($RemmediationOnly) {
if ($RemediationOnly) {
$query = "policyresources | where type == `"microsoft.policyinsights/policystates`" and properties.complianceState == `"NonCompliant`"$($effectFilter)"
}
else {
Expand Down
16 changes: 10 additions & 6 deletions Scripts/Helpers/Out-PolicySetsDocumentationToFile.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,13 @@ function Out-PolicySetsDocumentationToFile {
}

# deal with multi value cells
$inCellSeparator = ","
$inCellSeparator1 = ": "
$inCellSeparator2 = ","
$inCellSeparator3 = ","
if ($WindowsNewLineCells) {
$inCellSeparator = ",`n"
$inCellSeparator1 = ":`n "
$inCellSeparator2 = ",`n "
$inCellSeparator3 = ",`n"
}

$allRows.Clear()
Expand Down Expand Up @@ -143,16 +147,16 @@ function Out-PolicySetsDocumentationToFile {
$rowObj.displayName = $_.displayName
$rowObj.description = $_.description
if ($groupNamesList.Count -gt 0) {
$rowObj.groupNames = $groupNamesList -join $inCellSeparator
$rowObj.groupNames = $groupNamesList -join $inCellSeparator3
}
if ($policySetEffectStrings.Count -gt 0) {
$rowObj.policySets = $policySetEffectStrings -join $inCellSeparator
$rowObj.policySets = $policySetEffectStrings -join $inCellSeparator3
}
if ($isEffectParameterized -and $effectAllowedValues.Count -gt 1) {
$rowObj.allowedEffects = $effectAllowedValues.Keys -join $inCellSeparator
$rowObj.allowedEffects = "parameter$inCellSeparator1$($effectAllowedValues.Keys -join $inCellSeparator2)"
}
elseif ($effectAllowedOverrides.Count -gt 0) {
$rowObj.allowedEffects = $effectAllowedOverrides -join $inCellSeparator
$rowObj.allowedEffects = "override$inCellSeparator1$($effectAllowedOverrides -join $inCellSeparator2)"
}

# Per environment columns
Expand Down
2 changes: 1 addition & 1 deletion Scripts/Helpers/Switch-PacEnvironment.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function Switch-PacEnvironment {
else {
Write-Error " pacEnvironment '$PacEnvironmentSelector' in definition on lines $DefinitionStartingLine - $DefinitionEndingLine does not exist" -ErrorAction Stop
}
Set-AzCloudTenantSubscription `
$null = Set-AzCloudTenantSubscription `
-Cloud $pacEnvironment.cloud `
-TenantId $pacEnvironment.tenantId `
-Interactive $Interactive
Expand Down
4 changes: 2 additions & 2 deletions Scripts/Helpers/Write-AssignmentDetails.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ function Write-AssignmentDetails {

$shortScope = $Scope -replace "/providers/Microsoft.Management", ""
if ($Prefix -ne "") {
Write-Information " $($Prefix) '$($DisplayName)' at $($shortScope)"
Write-Information "$($Prefix) '$($DisplayName)' at $($shortScope)"
}
else {
Write-Information " '$($DisplayName)' at $($shortScope)"
Write-Information "'$($DisplayName)' at $($shortScope)"
}
if ($IdentityStatus.requiresRoleChanges) {
foreach ($role in $IdentityStatus.added) {
Expand Down
2 changes: 1 addition & 1 deletion Scripts/Operations/Create-AzRemediationTasks.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ $pacEnvironment = Select-PacEnvironment $PacEnvironmentSelector -DefinitionsRoot
$null = Set-AzCloudTenantSubscription -Cloud $pacEnvironment.cloud -TenantId $pacEnvironment.tenantId -Interactive $pacEnvironment.interactive

$rawNonCompliantList, $deployedPolicyResources, $scopeTable = Find-AzNonCompliantResources `
-RemmediationOnly `
-RemediationOnly `
-PacEnvironment $pacEnvironment `
-OnlyCheckManagedAssignments:$onlyCheckManagedAssignments `
-PolicyDefinitionFilter:$policyDefinitionFilter `
Expand Down
Loading

0 comments on commit e38aa00

Please sign in to comment.