Src/Private/Get-AbrIntuneWindowsUpdates.ps1
|
function Get-AbrIntuneWindowsUpdates { <# .SYNOPSIS Documents Windows Update for Business policies — Feature, Quality, and Driver update profiles. .DESCRIPTION Collects and reports on: - Windows Feature Update Profiles (beta/deviceManagement/windowsFeatureUpdateProfiles) - Windows Quality Update Profiles (beta/deviceManagement/windowsQualityUpdateProfiles) - Windows Driver Update Profiles (beta/deviceManagement/windowsDriverUpdateProfiles) .NOTES Version: 0.1.0 Added: v0.2.51 — addresses CRITICAL gaps from gap tracker #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory)] [string]$TenantId ) begin { Write-PScriboMessage -Message "Collecting Windows Update profiles for $TenantId." Show-AbrDebugExecutionTime -Start -TitleMessage 'Windows Updates' } process { #region Windows Feature Update Profiles try { Write-Host " - Retrieving Windows Feature Update Profiles..." $FeatureResp = $null try { $FeatureResp = Invoke-MgGraphRequest -Method GET ` -Uri "$($script:GraphEndpoint)/beta/deviceManagement/windowsFeatureUpdateProfiles?`$expand=assignments" ` -ErrorAction Stop } catch { Write-AbrDebugLog "windowsFeatureUpdateProfiles unavailable: $($_.Exception.Message)" 'WARN' 'WindowsUpdates' } if ($FeatureResp -and $FeatureResp.value -and @($FeatureResp.value).Count -gt 0) { Section -Style Heading2 'Windows Feature Update Profiles' { Paragraph "Feature Update profiles control which Windows version devices upgrade to. The following documents all profiles configured in tenant $TenantId." BlankLine $FeatObj = [System.Collections.ArrayList]::new() foreach ($Prof in ($FeatureResp.value | Sort-Object displayName)) { $assignResolved = Resolve-IntuneAssignments -Assignments $Prof.assignments -CheckMemberCount:$script:CheckEmptyGroups $rolloutLabel = if ($Prof.rolloutSettings) { $rs = $Prof.rolloutSettings $start = if ($rs -is [System.Collections.IDictionary]) { $rs['offerStartDateTimeInUTC'] } else { $rs.offerStartDateTimeInUTC } if ($start) { "From: $(([datetime]$start).ToString('yyyy-MM-dd'))" } else { 'Immediate' } } else { 'Immediate' } $featRow = [ordered] @{ 'Profile Name' = $Prof.displayName 'Feature Version' = if ($Prof.featureUpdateVersion) { $Prof.featureUpdateVersion } else { '--' } 'Rollout' = $rolloutLabel 'Deferral (days)' = if ($null -ne $Prof.deferralPeriodInDays) { "$($Prof.deferralPeriodInDays)" } else { '--' } 'Included Groups' = $assignResolved.IncludedGroups 'Excluded Groups' = $assignResolved.ExcludedGroups 'Last Modified' = if ($Prof.lastModifiedDateTime) { ([datetime]$Prof.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' } } $FeatObj.Add([pscustomobject]$featRow) | Out-Null } $FeatParams = @{ Name = "Feature Update Profiles - $TenantId"; ColumnWidths = 22, 14, 14, 10, 18, 14, 8 } if ($Report.ShowTableCaptions) { $FeatParams['Caption'] = "- $($FeatParams.Name)" } $FeatObj | Table @FeatParams } } } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'Feature Update Profiles' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'Feature Update Profiles' -Message "$($_.Exception.Message)" } } #endregion #region Windows Quality Update Profiles (Expedite) try { Write-Host " - Retrieving Windows Quality Update Profiles..." $QualityResp = $null try { $QualityResp = Invoke-MgGraphRequest -Method GET ` -Uri "$($script:GraphEndpoint)/beta/deviceManagement/windowsQualityUpdateProfiles?`$expand=assignments" ` -ErrorAction Stop } catch { Write-AbrDebugLog "windowsQualityUpdateProfiles unavailable: $($_.Exception.Message)" 'WARN' 'WindowsUpdates' } if ($QualityResp -and $QualityResp.value -and @($QualityResp.value).Count -gt 0) { Section -Style Heading2 'Windows Quality Update Profiles (Expedite)' { Paragraph "Quality Update profiles use expedite policies to push deadline-driven security updates. The following documents all profiles configured in tenant $TenantId." BlankLine $QualObj = [System.Collections.ArrayList]::new() foreach ($Prof in ($QualityResp.value | Sort-Object displayName)) { $assignResolved = Resolve-IntuneAssignments -Assignments $Prof.assignments -CheckMemberCount:$script:CheckEmptyGroups $qualRow = [ordered] @{ 'Profile Name' = $Prof.displayName 'Expedite' = if ($null -ne $Prof.expeditedUpdateSettings) { 'Yes' } else { 'No' } 'Days Until Forced Reboot' = if ($Prof.expeditedUpdateSettings) { $eu = $Prof.expeditedUpdateSettings $d = if ($eu -is [System.Collections.IDictionary]) { $eu['daysUntilForcedReboot'] } else { $eu.daysUntilForcedReboot } if ($null -ne $d) { "$d" } else { '--' } } else { '--' } 'Included Groups' = $assignResolved.IncludedGroups 'Excluded Groups' = $assignResolved.ExcludedGroups 'Last Modified' = if ($Prof.lastModifiedDateTime) { ([datetime]$Prof.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' } } $QualObj.Add([pscustomobject]$qualRow) | Out-Null } $QualParams = @{ Name = "Quality Update Profiles - $TenantId"; ColumnWidths = 24, 10, 18, 20, 18, 10 } if ($Report.ShowTableCaptions) { $QualParams['Caption'] = "- $($QualParams.Name)" } $QualObj | Table @QualParams } } } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'Quality Update Profiles' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'Quality Update Profiles' -Message "$($_.Exception.Message)" } } #endregion #region Windows Driver Update Profiles try { Write-Host " - Retrieving Windows Driver Update Profiles..." $DriverResp = $null try { $DriverResp = Invoke-MgGraphRequest -Method GET ` -Uri "$($script:GraphEndpoint)/beta/deviceManagement/windowsDriverUpdateProfiles?`$expand=assignments" ` -ErrorAction Stop } catch { Write-AbrDebugLog "windowsDriverUpdateProfiles unavailable: $($_.Exception.Message)" 'WARN' 'WindowsUpdates' } if ($DriverResp -and $DriverResp.value -and @($DriverResp.value).Count -gt 0) { Section -Style Heading2 'Windows Driver Update Profiles' { Paragraph "Driver Update profiles control automatic vs manual driver approval policies. The following documents all profiles configured in tenant $TenantId." BlankLine $DrvObj = [System.Collections.ArrayList]::new() foreach ($Prof in ($DriverResp.value | Sort-Object displayName)) { $assignResolved = Resolve-IntuneAssignments -Assignments $Prof.assignments -CheckMemberCount:$script:CheckEmptyGroups $approvalLabel = switch ($Prof.approvalType) { 'automatic' { 'Automatic' } 'manual' { 'Manual' } default { if ($Prof.approvalType) { $Prof.approvalType } else { '--' } } } $drvRow = [ordered] @{ 'Profile Name' = $Prof.displayName 'Approval Type' = $approvalLabel 'Deployment Delay' = if ($null -ne $Prof.deploymentDeferralInDays) { "$($Prof.deploymentDeferralInDays) days" } else { '--' } 'Included Groups' = $assignResolved.IncludedGroups 'Excluded Groups' = $assignResolved.ExcludedGroups 'Last Modified' = if ($Prof.lastModifiedDateTime) { ([datetime]$Prof.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' } } $DrvObj.Add([pscustomobject]$drvRow) | Out-Null } $DrvParams = @{ Name = "Driver Update Profiles - $TenantId"; ColumnWidths = 25, 14, 15, 20, 18, 8 } if ($Report.ShowTableCaptions) { $DrvParams['Caption'] = "- $($DrvParams.Name)" } $DrvObj | Table @DrvParams } } } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'Driver Update Profiles' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'Driver Update Profiles' -Message "$($_.Exception.Message)" } } #endregion } end { Show-AbrDebugExecutionTime -End -TitleMessage 'Windows Updates' } } |