diff --git a/psmodules/Check-AllowedLocationPolicy.zip b/psmodules/Check-AllowedLocationPolicy.zip index 52329adc..989bc6cc 100644 Binary files a/psmodules/Check-AllowedLocationPolicy.zip and b/psmodules/Check-AllowedLocationPolicy.zip differ diff --git a/psmodules/GR-Common.zip b/psmodules/GR-Common.zip index f59ada06..0564b503 100644 Binary files a/psmodules/GR-Common.zip and b/psmodules/GR-Common.zip differ diff --git a/setup/IaC/guardrails.bicep b/setup/IaC/guardrails.bicep index 7b50c487..aae600f5 100644 --- a/setup/IaC/guardrails.bicep +++ b/setup/IaC/guardrails.bicep @@ -2,7 +2,7 @@ targetScope = 'resourceGroup' //Parameters and variables param AllowedLocationPolicyId string = 'e56962a6-4747-49cd-b67b-bf8b01975c4c' -param AllowedLocationInitiativeId string = 'N/A' +param AllowedLocationInitiativeId string = '/providers/microsoft.management/managementgroups/252afaf3-eb71-4f05-8da2-279c8b2466b7/providers/microsoft.authorization/policysetdefinitions/6c7429039715412f9438cb15' param automationAccountName string = 'guardrails-AC' param CBSSubscriptionName string param currentUserObjectId string = '' diff --git a/setup/IaC/modules/automationaccount.bicep b/setup/IaC/modules/automationaccount.bicep index 9b536b8a..0087607c 100644 --- a/setup/IaC/modules/automationaccount.bicep +++ b/setup/IaC/modules/automationaccount.bicep @@ -150,7 +150,7 @@ resource guardrailsAC 'Microsoft.Automation/automationAccounts@2021-06-22' = if properties: { contentLink: { uri: '${ModuleBaseURL}/GR-Common.zip' - version: '1.2.4' + version: '1.2.5' } } } @@ -168,7 +168,7 @@ resource guardrailsAC 'Microsoft.Automation/automationAccounts@2021-06-22' = if properties: { contentLink: { uri: '${ModuleBaseURL}/Check-AllowedLocationPolicy.zip' - version: '1.1.0' + version: '1.1.1' } } } diff --git a/setup/config.json b/setup/config.json index f31cb8ea..30407cb8 100644 --- a/setup/config.json +++ b/setup/config.json @@ -10,7 +10,7 @@ "SSCReadOnlyServicePrincipalNameAPPID": "00000000-0000-0000-0000-000000000000", "pbmmPolicyID": "4c4a5f27-de81-430b-b4e5-9cbd50595a87", "allowedLocationPolicyId": "e56962a6-4747-49cd-b67b-bf8b01975c4c", - "allowedLocationInitiativeId": "N/A", + "allowedLocationInitiativeId": "/providers/microsoft.management/managementgroups/252afaf3-eb71-4f05-8da2-279c8b2466b7/providers/microsoft.authorization/policysetdefinitions/6c7429039715412f9438cb15", "departmentNumber": "", "cbsSubscriptionName": "N/A", "securityLAWResourceId": "/subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxx/resourceGroups/xxxxx/providers/Microsoft.OperationalInsights/workspaces/xxxxxxx", diff --git a/src/GUARDRAIL 5 DATA LOCATION/Audit/Check-AllowedLocationPolicy.psd1 b/src/GUARDRAIL 5 DATA LOCATION/Audit/Check-AllowedLocationPolicy.psd1 index f664d499..ceb60867 100644 --- a/src/GUARDRAIL 5 DATA LOCATION/Audit/Check-AllowedLocationPolicy.psd1 +++ b/src/GUARDRAIL 5 DATA LOCATION/Audit/Check-AllowedLocationPolicy.psd1 @@ -14,7 +14,7 @@ RootModule = 'Check-AllowedLocationPolicy' # Version number of this module. -ModuleVersion = '1.1.0' +ModuleVersion = '1.1.1' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/src/GUARDRAIL 5 DATA LOCATION/Audit/Check-AllowedLocationPolicy.psm1 b/src/GUARDRAIL 5 DATA LOCATION/Audit/Check-AllowedLocationPolicy.psm1 index 2b9d42f5..5b4d4a1b 100644 --- a/src/GUARDRAIL 5 DATA LOCATION/Audit/Check-AllowedLocationPolicy.psm1 +++ b/src/GUARDRAIL 5 DATA LOCATION/Audit/Check-AllowedLocationPolicy.psm1 @@ -17,8 +17,16 @@ function Check-PolicyStatus { $CloudUsageProfiles = "3", # Passed as a string [string] $ModuleProfiles, # Passed as a string [switch] $EnableMultiCloudProfiles # New feature flag, default to false - ) + ) + [PSCustomObject] $tempObjectList = New-Object System.Collections.ArrayList + $TotalInitResources = 0 + $TotalPolicyResources = 0 + $InitNonCompliantResources = 0 + $InitCompliantResources = 0 + $PolicyNonCompliantResources = 0 + $PolicyCompliantResources = 0 + foreach ($obj in $objList) { Write-Verbose "Checking $objType : $($obj.Name)" @@ -29,27 +37,16 @@ function Check-PolicyStatus { $tempId=$obj.Id } - try { - try{ - $AssignedPolicyList = Get-AzPolicyAssignment -scope $tempId -PolicyDefinitionId $PolicyID - - } - catch{ - $Errorlist.Add("Failed to execute the 'Get-AzPolicyAssignment' command on policy list for scope '$($tempId)'--verify your permissions and the installion of the Az.Resources module; returned error message: $_" ) - Write-Error "Error: Failed to execute the 'Get-AzPolicyAssignment' command on policy list for scope '$($tempId)'--verify your permissions and the installion of the Az.Resources module; returned error message: $_" - } - try{ - $AssignedInitiatives = Get-AzPolicyAssignment -scope $tempId -PolicyDefinitionId $InitiativeID #Retrieve Initiatives - } - catch{ - $Errorlist.Add("Failed to execute the 'Get-AzPolicyAssignment' command on initiatives for scope '$($tempId)'--verify your permissions and the installion of the Az.Resources module; returned error message: $_" ) - Write-Error "Error: Failed to execute the 'Get-AzPolicyAssignment' command on initiatives for scope '$($tempId)'--verify your permissions and the installion of the Az.Resources module; returned error message: $_" - } + #Retrieving policies and initiatives + try{ + $AssignedPolicyList = Get-AzPolicyAssignment -scope $tempId -PolicyDefinitionId $PolicyID + $AssignedInitiatives = Get-AzPolicyAssignment -scope $tempId -PolicyDefinitionId $InitiativeID } - catch { - $Errorlist.Value.Add("Failed to execute the 'Get-AzPolicyAssignment' command for scope '$($tempId)'--verify your permissions and the installion of the Az.Resources module; returned error message: $_" ) - Write-Error "Error: Failed to execute the 'Get-AzPolicyAssignment' command for scope '$($tempId)'--verify your permissions and the installion of the Az.Resources module; returned error message: $_" + catch{ + $Errorlist.Add("Failed to retrieve policy or initiative assignments for scope '$($tempId)'--verify your permissions and the installion of the Az.Resources module; returned error message: $_" ) + Write-Error "Error: Failed to retrieve policy or initiative assignments for scope '$($tempId)'--verify your permissions and the installion of the Az.Resources module; returned error message: $_" } + If (($null -eq $AssignedPolicyList -and ($null -eq $AssignedInitiatives -or $AssignedInitiatives -eq "N/A")) -or ((-not ([string]::IsNullOrEmpty(($AssignedPolicyList.Properties.NotScopesScope)))) -or (-not ([string]::IsNullOrEmpty(($AssignedInitiatives.Properties.NotScopesScope)))))) { $Comment=$($msgTable.policyNotAssigned -f $objType) @@ -59,7 +56,6 @@ function Check-PolicyStatus { # Test for allowed locations in policies if not null $ComplianceStatus=$true # should be true unless we find a non-compliant location - $Comment=$msgTable.isCompliant if ($null -ne $AssignedPolicyList){ if (!([string]::IsNullOrEmpty($AllowedLocations))) @@ -85,9 +81,71 @@ function Check-PolicyStatus { } } } + } + } + + if($ComplianceStatus -eq $true){ + + if(!($null -eq $AssignedInitiatives -or $AssignedInitiatives -eq "N/A")){ + $InitiativeState = Get-AzPolicyState | Where-Object { $_.PolicySetDefinitionId -eq $InitiativeID } + $TotalInitResources = $InitiativeState.Count + $InitCompliantResources = ($InitiativeState | Where-Object {$_.IsCompliant -eq $true}).Count + $InitNonCompliantResources = ($InitiativeState | Where-Object {$_.IsCompliant -eq $false}).Count + } + if(!($null -eq $AssignedPolicyList)){ + $PolicyState = Get-AzPolicyState | Where-Object { $_.PolicySetDefinitionId -eq $PolicyID } + $TotalPolicyResources = $PolicyState.Count + $PolicyCompliantResources = ($PolicyState | Where-Object {$_.IsCompliant -eq $true}).Count + $PolicyNonCompliantResources = ($PolicyState | Where-Object {$_.IsCompliant -eq $false}).Count + } + + if (($TotalInitResources -gt 0 -and $TotalPolicyResources -eq 0) -or ($TotalPolicyResources -gt 0 -and $TotalInitResources -eq 0)) { + # Case 1: Only Initiative has resources, check initiative compliance + # Case 2: Only Policy has resources, check policy compliance + + if ($TotalInitResources -gt 0 -and $TotalInitResources -eq $InitNonCompliantResources) { + $ComplianceStatus = $false + $Comment = $msgTable.isNotCompliant + ' ' + $msgTable.allNonCompliantResources + } + elseif ($TotalPolicyResources -gt 0 -and $TotalPolicyResources -eq $PolicyNonCompliantResources) { + $ComplianceStatus = $false + $Comment = $msgTable.isNotCompliant + ' ' + $msgTable.allNonCompliantResources + } + elseif($InitNonCompliantResources -gt 0 -and ($InitNonCompliantResources -lt $TotalInitResources)){ + $ComplianceStatus = $false + $Comment = $msgTable.isNotCompliant + ' ' + $msgTable.hasNonComplianceResource -f $InitNonCompliantResources, $TotalInitResources + } + elseif($PolicyNonCompliantResources -gt 0 -and ($PolicyNonCompliantResources -lt $TotalPolicyResources)){ + $ComplianceStatus = $false + $Comment = $msgTable.isNotCompliant + ' ' + $msgTable.hasNonComplianceResource -f $PolicyNonCompliantResources, $TotalPolicyResources + } + else{ + $ComplianceStatus = $true + $Comment = $msgTable.isCompliant + ' ' + $msgTable.allCompliantResources + } } + elseif ($TotalInitResources -gt 0 -and $TotalPolicyResources -gt 0) { + # Case 3: Both Initiative and Policy have assigned resources, so check both + if ($TotalInitResources -eq $InitCompliantResources -and $TotalPolicyResources -eq $PolicyCompliantResources) { + $ComplianceStatus = $true + $Comment = $msgTable.isCompliant + ' ' + $msgTable.allCompliantResources + } + elseif($InitNonCompliantResources -gt 0 -and ($InitNonCompliantResources -lt $TotalInitResources)){ + $ComplianceStatus = $false + $Comment = $msgTable.isNotCompliant + ' ' + $msgTable.hasNonComplianceResource -f $InitNonCompliantResources, $TotalInitResources + } + elseif($PolicyNonCompliantResources -gt 0 -and ($PolicyNonCompliantResources -lt $TotalPolicyResources)){ + $ComplianceStatus = $false + $Comment = $msgTable.isNotCompliant + ' ' + $msgTable.hasNonComplianceResource -f $PolicyNonCompliantResources, $TotalPolicyResources + } + } + elseif($TotalInitResources -eq 0 -and $TotalPolicyResources -eq 0){ + $ComplianceStatus = $true + $Comment = $msgTable.isCompliant + ' ' + $msgTable.noResource + } } + if ($null -eq $obj.DisplayName) { $DisplayName=$obj.Name diff --git a/src/GuardRails-Localization/GR-ComplianceChecks-Msgs.psd1 b/src/GuardRails-Localization/GR-ComplianceChecks-Msgs.psd1 index 0a0b807d..f24cc780 100644 --- a/src/GuardRails-Localization/GR-ComplianceChecks-Msgs.psd1 +++ b/src/GuardRails-Localization/GR-ComplianceChecks-Msgs.psd1 @@ -191,7 +191,7 @@ grExemptionNotFound = Required Policy Definitions are not exempt. noResource = No applicable resources for the selected PBMM Initiative's policies to evaluate. allCompliantResources = All resources are compliant. allNonCompliantResources = All resources are non-compliant. -hasNonComplianceResounce = {0} out of the {1} applicable resources are non-compliant against the selected policies. Follow the Microsoft remediation recommendations. +hasNonComplianceResource = {0} out of the {1} applicable resources are non-compliant against the selected policies. Follow the Microsoft remediation recommendations. # GuardRail #7 diff --git a/src/GuardRails-Localization/fr-CA/GR-ComplianceChecks-Msgs.psd1 b/src/GuardRails-Localization/fr-CA/GR-ComplianceChecks-Msgs.psd1 index dedd600e..1cedb10f 100644 --- a/src/GuardRails-Localization/fr-CA/GR-ComplianceChecks-Msgs.psd1 +++ b/src/GuardRails-Localization/fr-CA/GR-ComplianceChecks-Msgs.psd1 @@ -192,7 +192,7 @@ grExemptionNotFound = Les définitions des politiques requises ne sont pas exemp noResource = Aucune ressource applicable à l'évaluation des politiques de l'initiative PBMM sélectionnée. allCompliantResources = Toutes les ressources sont conformes. allNonCompliantResources = Toutes les ressources ne sont pas conformes. -hasNonComplianceResounce = {0} des ressources {1} applicables ne sont pas conformes aux politiques sélectionnées. Suivez les recommandations de correction de Microsoft. +hasNonComplianceResource = {0} des ressources {1} applicables ne sont pas conformes aux politiques sélectionnées. Suivez les recommandations de correction de Microsoft. # GuardRail #7 diff --git a/src/Guardrails-Common/GR-Common.psd1 b/src/Guardrails-Common/GR-Common.psd1 index fc5f5407..c2ac2ce4 100644 --- a/src/Guardrails-Common/GR-Common.psd1 +++ b/src/Guardrails-Common/GR-Common.psd1 @@ -14,7 +14,7 @@ RootModule = 'GR-Common' # Version number of this module. -ModuleVersion = '1.2.4' +ModuleVersion = '1.2.5' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/src/Guardrails-Common/GR-Common.psm1 b/src/Guardrails-Common/GR-Common.psm1 index 286afb88..aad47753 100644 --- a/src/Guardrails-Common/GR-Common.psm1 +++ b/src/Guardrails-Common/GR-Common.psm1 @@ -1281,7 +1281,7 @@ function Check-PBMMPolicies { elseif($totalResource -gt 0 -and $countResourceNonCompliant -gt 0 -and ($countResourceNonCompliant -lt $totalResource)){ # There are some resources that are non-compliant $ComplianceStatus=$false - $Comment = $msgTable.isNotCompliant + ' ' + $Comment + ' '+ $msgTable.hasNonComplianceResounce -f $countResourceNonCompliant, $totalResource + $Comment = $msgTable.isNotCompliant + ' ' + $Comment + ' '+ $msgTable.hasNonComplianceResource -f $countResourceNonCompliant, $totalResource } else{ # All use cases are covered by now. Anything else?