Src/Private/Get-AbrExoMobileDevices.ps1
|
function Get-AbrExoMobileDevices { <# .SYNOPSIS Documents Exchange Online mobile device access policies (ActiveSync), device partnerships, and mobile device mailbox policies. .NOTES Version: 0.1.0 Author: Pai Wei Sing #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory)] [string]$TenantId ) begin { Write-PScriboMessage -Message "Collecting Exchange Online Mobile Device configuration for $TenantId." Show-AbrDebugExecutionTime -Start -TitleMessage 'MobileDevices' } process { Section -Style Heading2 'Device Access Policies' { Paragraph "The following section documents mobile device (ActiveSync/EAS) access policies and device partnerships for tenant $TenantId." BlankLine #region Mobile Device Access Settings (tenant-level) try { Write-Host " - Retrieving mobile device access settings..." # Get-MobileDeviceAccessSettings is not available in EXO v3 REST mode. # Use Get-ActiveSyncOrganizationSettings instead (available in all modes). $EasOrgSettings = Get-ActiveSyncOrganizationSettings -ErrorAction Stop $AccessObj = [System.Collections.ArrayList]::new() $accessInObj = [ordered] @{ 'Default Access Level' = $EasOrgSettings.DefaultAccessLevel 'OTA Update Enabled' = $EasOrgSettings.OtaNotificationMailInserted 'User Agent Filter Enabled' = $EasOrgSettings.UserAgentFilterEnabled 'Allow Non-Provisionable Devices' = $EasOrgSettings.AllowNonProvisionableDevices } $AccessObj.Add([pscustomobject](ConvertTo-HashToYN $accessInObj)) | Out-Null $null = (& { if ($HealthCheck.ExchangeOnline.Mailboxes) { $null = ($AccessObj | Where-Object { $_.'Default Access Level' -eq 'Block' } | Set-Style -Style Warning | Out-Null) $null = ($AccessObj | Where-Object { $_.'Allow Non-Provisionable Devices' -eq 'Yes' } | Set-Style -Style Warning | Out-Null) } }) $AccessTableParams = @{ Name = "Mobile Device Access Settings - $TenantId"; List = $true; ColumnWidths = 45, 55 } if ($Report.ShowTableCaptions) { $AccessTableParams['Caption'] = "- $($AccessTableParams.Name)" } $AccessObj | Table @AccessTableParams } catch { Write-ExoError 'MobileDevices' "Unable to retrieve mobile device access settings: $($_.Exception.Message)" Paragraph "Mobile device organisation settings could not be retrieved: $($_.Exception.Message)" } #endregion #region Mobile Device Mailbox Policies try { Write-Host " - Retrieving mobile device mailbox policies..." $MdmPolicies = Get-MobileDeviceMailboxPolicy -ErrorAction Stop | Sort-Object IsDefault -Descending if ($MdmPolicies -and @($MdmPolicies).Count -gt 0) { Section -Style Heading3 'Mobile Device Mailbox Policies' { Paragraph "The following $(@($MdmPolicies).Count) mobile device mailbox policy/policies are configured in tenant $TenantId." BlankLine $MdmObj = [System.Collections.ArrayList]::new() foreach ($Policy in $MdmPolicies) { $mdmInObj = [ordered] @{ 'Policy Name' = $Policy.Name 'Default Policy' = $Policy.IsDefault 'Password Required' = $Policy.PasswordEnabled 'Min Password Length' = if ($Policy.MinPasswordLength) { $Policy.MinPasswordLength } else { 'Not Set' } 'Require Encryption' = $Policy.RequireDeviceEncryption 'Allow Non-Provisionable Devices'= $Policy.AllowNonProvisionableDevices 'Allow Simple Password' = $Policy.AllowSimplePassword 'Max Inactivity Lock (min)' = if ($Policy.MaxInactivityTimeLock) { $Policy.MaxInactivityTimeLock } else { 'Not Set' } 'Max Password Attempts' = if ($Policy.MaxPasswordFailedAttempts) { $Policy.MaxPasswordFailedAttempts } else { 'Not Set' } 'Remote Wipe Supported' = $Policy.AllowRemoteWipe } $MdmObj.Add([pscustomobject](ConvertTo-HashToYN $mdmInObj)) | Out-Null } $null = (& { if ($HealthCheck.ExchangeOnline.Mailboxes) { $null = ($MdmObj | Where-Object { $_.'Password Required' -eq 'No' } | Set-Style -Style Warning | Out-Null) $null = ($MdmObj | Where-Object { $_.'Require Encryption' -eq 'No' } | Set-Style -Style Warning | Out-Null) $null = ($MdmObj | Where-Object { $_.'Allow Non-Provisionable Devices' -eq 'Yes' } | Set-Style -Style Warning | Out-Null) } }) $MdmTableParams = @{ Name = "Mobile Device Mailbox Policies - $TenantId"; List = $false; ColumnWidths = 14, 8, 10, 8, 10, 12, 10, 10, 10, 8 } if ($Report.ShowTableCaptions) { $MdmTableParams['Caption'] = "- $($MdmTableParams.Name)" } if ($MdmObj.Count -gt 0) { $MdmObj | Table @MdmTableParams } $script:ExcelSheets['Mobile Device Policies'] = $MdmObj } } } catch { Write-ExoError 'MobileDevices' "Unable to retrieve mobile device mailbox policies: $($_.Exception.Message)" Paragraph "Unable to retrieve mobile device mailbox policies: $($_.Exception.Message)" } #endregion #region Mobile Device Access Rules (block/allow by device type) try { Write-Host " - Retrieving mobile device access rules..." # Try Get-ActiveSyncDeviceAccessRule (available in all EXO connection modes) $AccessRules = Get-ActiveSyncDeviceAccessRule -ErrorAction Stop | Sort-Object Name if ($AccessRules -and @($AccessRules).Count -gt 0) { Section -Style Heading3 'Mobile Device Access Rules' { Paragraph "The following $(@($AccessRules).Count) mobile device access rule(s) control which device types can connect to Exchange Online." BlankLine $RuleObj = [System.Collections.ArrayList]::new() foreach ($Rule in $AccessRules) { $ruleInObj = [ordered] @{ 'Rule Name' = $Rule.Name 'Characteristic' = $Rule.Characteristic 'Query String' = $Rule.QueryString 'Access Level' = $Rule.AccessLevel } $RuleObj.Add([pscustomobject]$ruleInObj) | Out-Null } $null = (& { if ($HealthCheck.ExchangeOnline.Mailboxes) { $null = ($RuleObj | Where-Object { $_.'Access Level' -eq 'Block' } | Set-Style -Style Warning | Out-Null) $null = ($RuleObj | Where-Object { $_.'Access Level' -eq 'Quarantine' } | Set-Style -Style Warning | Out-Null) } }) $RuleTableParams = @{ Name = "Mobile Device Access Rules - $TenantId"; List = $false; ColumnWidths = 28, 20, 32, 20 } if ($Report.ShowTableCaptions) { $RuleTableParams['Caption'] = "- $($RuleTableParams.Name)" } if ($RuleObj.Count -gt 0) { $RuleObj | Table @RuleTableParams } $script:ExcelSheets['Mobile Device Rules'] = $RuleObj } } else { Paragraph "No mobile device access rules are configured. The default access level from organisation settings applies to all devices." } } catch { Write-ExoError 'MobileDevices' "Unable to retrieve mobile device access rules: $($_.Exception.Message)" Paragraph "Mobile device access rules could not be retrieved. Note: device-based access controls may be managed via Microsoft Intune/Entra Conditional Access policies." } #endregion #region Device Partnerships (InfoLevel 2) if ($InfoLevel.MobileDevices -ge 2) { try { Write-Host " - Retrieving mobile device partnerships..." $Devices = Get-MobileDevice -ResultSize Unlimited -ErrorAction Stop | Sort-Object UserDisplayName, FriendlyName if ($Devices -and @($Devices).Count -gt 0) { Section -Style Heading3 'Mobile Device Partnerships' { Paragraph "The following $(@($Devices).Count) mobile device partnership(s) are registered in tenant $TenantId." BlankLine $DevObj = [System.Collections.ArrayList]::new() foreach ($Dev in $Devices) { # Get device stats safely $LastSync = '--' $Status = '--' try { $Stats = Get-MobileDeviceStatistics -Mailbox $Dev.UserDisplayName -Identity $Dev.Identity -ErrorAction SilentlyContinue if ($Stats) { $LastSync = if ($Stats.LastSyncAttemptTime) { $Stats.LastSyncAttemptTime.ToString('yyyy-MM-dd') } else { 'Never' } $Status = $Stats.Status } } catch {} $devInObj = [ordered] @{ 'User' = $Dev.UserDisplayName 'Device Name' = $Dev.FriendlyName 'Device Type' = $Dev.DeviceType 'OS' = $Dev.DeviceOS 'Model' = $Dev.DeviceModel 'Access State' = $Dev.DeviceAccessState 'Last Sync' = $LastSync 'Status' = $Status } $DevObj.Add([pscustomobject]$devInObj) | Out-Null } $null = (& { if ($HealthCheck.ExchangeOnline.Mailboxes) { $null = ($DevObj | Where-Object { $_.'Access State' -eq 'Blocked' } | Set-Style -Style Critical | Out-Null) $null = ($DevObj | Where-Object { $_.'Access State' -eq 'Quarantined' } | Set-Style -Style Warning | Out-Null) # Flag devices not synced in 90+ days $null = ($DevObj | Where-Object { $_.'Last Sync' -ne '--' -and $_.'Last Sync' -ne 'Never' -and (New-TimeSpan -Start ([datetime]::Parse($_.'Last Sync')) -End (Get-Date)).Days -gt 90 } | Set-Style -Style Warning | Out-Null) } }) $DevTableParams = @{ Name = "Mobile Device Partnerships - $TenantId"; List = $false; ColumnWidths = 14, 14, 12, 12, 12, 12, 12, 12 } if ($Report.ShowTableCaptions) { $DevTableParams['Caption'] = "- $($DevTableParams.Name)" } if ($DevObj.Count -gt 0) { $DevObj | Table @DevTableParams } $script:ExcelSheets['Mobile Devices'] = $DevObj } } else { Paragraph "No mobile device partnerships found in tenant $TenantId." } } catch { Write-ExoError 'MobileDevices' "Unable to retrieve mobile device partnerships: $($_.Exception.Message)" Paragraph "Unable to retrieve mobile device partnership data: $($_.Exception.Message)" } } #endregion } } end { Show-AbrDebugExecutionTime -End -TitleMessage 'MobileDevices' } } |