tests/Test-Assessment.21860.ps1
|
<# .SYNOPSIS Tests if all Entra Logs are configured with Diagnostic Settings. .DESCRIPTION This test validates that all required Microsoft Entra log categories have at least one diagnostic setting configured with that category enabled. .NOTES Test ID: 21860 Category: Monitoring Pillar: Identity Required API: ARM REST - providers/microsoft.aadiam/diagnosticsettings #> function Test-Assessment-21860 { [ZtTest( Category = 'Monitoring', ImplementationCost = 'Medium', Pillar = 'Identity', RiskLevel = 'High', Service = ('Azure'), SfiPillar = 'Monitor and detect cyberthreats', TenantType = ('Workforce', 'External'), TestId = 21860, Title = 'Diagnostic settings are configured for all Microsoft Entra logs', UserImpact = 'Low' )] [CmdletBinding()] param() #region Data Collection Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose $activity = 'Checking Microsoft Entra diagnostic settings configuration' # Check if connected to Azure Write-ZtProgress -Activity $activity -Status 'Checking Azure connection' $azContext = Get-AzContext -ErrorAction SilentlyContinue if (-not $azContext) { Write-PSFMessage 'Not connected to Azure.' -Level Warning Add-ZtTestResultDetail -SkippedBecause NotConnectedAzure return } # Only applicable to AzureCloud environment if ($azContext.Environment.Name -ne 'AzureCloud') { Write-PSFMessage 'This test is only applicable to the AzureCloud environment.' -Tag Test -Level VeryVerbose Add-ZtTestResultDetail -SkippedBecause NotSupported return } Write-ZtProgress -Activity $activity -Status 'Querying Entra diagnostic settings' # Use ARM REST API for tenant-level Entra diagnostic settings. # Azure Resource Graph does not index microsoft.aadiam resources, so Invoke-ZtAzureRequest is used. $diagnosticSettings = @() try { $response = Invoke-ZtAzureRequest -Path '/providers/microsoft.aadiam/diagnosticsettings?api-version=2017-04-01-preview' -FullResponse if ($response.StatusCode -eq 403) { Write-PSFMessage 'The signed-in user does not have access to Entra diagnostic settings.' -Level Verbose Add-ZtTestResultDetail -SkippedBecause NoAzureAccess return } if ($response.StatusCode -ge 400) { $errorMessage = "Entra diagnostic settings query failed with status code $($response.StatusCode)." if ($response.Content) { $errorMessage = "$errorMessage Response: $($response.Content)" } throw $errorMessage } $diagnosticSettings = @(($response.Content | ConvertFrom-Json).value) Write-PSFMessage "Found $($diagnosticSettings.Count) diagnostic setting(s)" -Tag Test -Level VeryVerbose } catch { # Only catches actual exceptions (network errors, throttling, etc.), not HTTP status codes throw } #endregion Data Collection #region Assessment Logic $logsToCheck = @( 'AuditLogs', 'SignInLogs', 'NonInteractiveUserSignInLogs', 'ServicePrincipalSignInLogs', 'ManagedIdentitySignInLogs', 'ProvisioningLogs', 'ADFSSignInLogs', 'RiskyUsers', 'UserRiskEvents', 'NetworkAccessTrafficLogs', 'RiskyServicePrincipals', 'ServicePrincipalRiskEvents', 'EnrichedOffice365AuditLogs', 'MicrosoftGraphActivityLogs', 'RemoteNetworkHealthLogs' ) # Collect all log categories that are enabled in at least one diagnostic setting $enabledLogs = @( $diagnosticSettings | ForEach-Object { $_.properties.logs } | Where-Object { $_.enabled -eq $true } | Select-Object -ExpandProperty category -Unique ) $missingLogs = @($logsToCheck | Where-Object { $_ -notin $enabledLogs }) $passed = $missingLogs.Count -eq 0 if ($passed) { $testResultMarkdown = "✅ All Entra Logs are configured with Diagnostic Settings.`n`n%TestResult%" } else { $testResultMarkdown = "❌ Some Entra Logs are not configured with Diagnostic settings.`n`n%TestResult%" } #endregion Assessment Logic #region Report Generation $mdInfo = '' $reportTitle = 'Microsoft Entra Log Archiving' $portalLink = 'https://portal.azure.com/#view/Microsoft_AAD_IAM/DiagnosticSettingsMenuBlade' $tableRows = '' foreach ($log in $logsToCheck | Sort-Object) { if ($log -in $enabledLogs) { $settingNames = @( $diagnosticSettings | Where-Object { $_.properties.logs | Where-Object { $_.category -eq $log -and $_.enabled -eq $true } } | ForEach-Object { Get-SafeMarkdown $_.name } ) $tableRows += "| $log | $($settingNames -join ', ') |`n" } else { $tableRows += "| $log | none |`n" } } $formatTemplate = @' ## [{0}]({1}) | Log name | Diagnostic settings | | :--- | :--- | {2} '@ $mdInfo = $formatTemplate -f $reportTitle, $portalLink, $tableRows $testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo #endregion Report Generation $params = @{ TestId = '21860' Title = 'Diagnostic settings are configured for all Microsoft Entra logs' Status = $passed Result = $testResultMarkdown } Add-ZtTestResultDetail @params } |