Workloads/Get-DeviceManagementData.ps1

# Get-DeviceManagementData.ps1
# Collects Intune managed devices, compliance, configuration policies,
# app protection policies, Autopilot, and Defender onboarding signal.
# Part of the M365-QuickAssess module -- not exported.

function Get-DeviceManagementData
{
    param
    (
        $Assessment
    )

    Write-Log "Collecting device management data"

    # -------------------------------------------------------------------
    # Entra Registered / Joined Devices
    # -------------------------------------------------------------------
    try
    {
        $entraDevices      = Get-MgDevice -All -ErrorAction Stop
        $entraDeviceCount  = $entraDevices.Count
        $hybridJoinedCount = ( $entraDevices | Where-Object { $_.TrustType -eq "ServerAD" } ).Count
        $entraJoinedCount  = ( $entraDevices | Where-Object { $_.TrustType -eq "AzureAD" } ).Count

        $Assessment.DeviceManagement.EntraDeviceCount        = $entraDeviceCount
        $Assessment.DeviceManagement.HasHybridJoinedDevices  = ( $hybridJoinedCount -gt 0 )
        $Assessment.DeviceManagement.HybridJoinedDeviceCount = $hybridJoinedCount
        $Assessment.DeviceManagement.HasEntraJoinedDevices   = ( $entraJoinedCount -gt 0 )
        $Assessment.DeviceManagement.EntraJoinedDeviceCount  = $entraJoinedCount

        if ( $hybridJoinedCount -gt 0 )
        {
            $Assessment.Findings += New-Finding `
                -Type           "HybridJoinedDevices" `
                -Summary        "$hybridJoinedCount hybrid Entra joined devices detected" `
                -Category       "DeviceManagement" `
                -Severity       "Medium" `
                -Impact         "Hybrid joined devices are tied to on-premises Active Directory. Migration may require re-joining devices to the target tenant." `
                -Recommendation "Review hybrid join strategy and plan device re-enrollment or re-join for the target tenant."
        }
    }
    catch
    {
        Write-Log "Entra device collection failed: $( $_.Exception.Message )" "ERROR"
    }

    # -------------------------------------------------------------------
    # Intune License Check
    # -------------------------------------------------------------------
    $intuneAvailable = $false

    try
    {
        $null = Get-MgDeviceManagementManagedDevice -Top 1 -ErrorAction Stop
        $intuneAvailable = $true
    }
    catch
    {
        $intuneAvailable = $false
        Write-Log "Intune not available -- insufficient license or permissions. Skipping Intune collection." "WARN"

    }

    # -------------------------------------------------------------------
    # Intune Managed Devices
    # -------------------------------------------------------------------
    if ( $intuneAvailable -eq $true )
    {
        try
        {
            $devices        = Get-MgDeviceManagementManagedDevice -All -ErrorAction Stop
            $managedCount   = $devices.Count
            $compliantCount = ( $devices | Where-Object { $_.ComplianceState -eq "compliant" } ).Count

            $windowsCount = ( $devices | Where-Object { $_.OperatingSystem -eq "Windows" } ).Count
            $iosCount     = ( $devices | Where-Object { $_.OperatingSystem -eq "iOS" } ).Count
            $androidCount = ( $devices | Where-Object { $_.OperatingSystem -eq "Android" } ).Count
            $macCount     = ( $devices | Where-Object { $_.OperatingSystem -eq "macOS" } ).Count

            $Assessment.DeviceManagement.IntuneConfigured        = ( $managedCount -gt 0 )
            $Assessment.DeviceManagement.MDMConfigured           = ( $managedCount -gt 0 )
            $Assessment.DeviceManagement.ManagedDeviceCount      = $managedCount
            $Assessment.DeviceManagement.HasManagedDevices       = ( $managedCount -gt 0 )
            $Assessment.DeviceManagement.CompliantDeviceCount    = $compliantCount
            $Assessment.DeviceManagement.HasCompliantDevices     = ( $compliantCount -gt 0 )
            $Assessment.DeviceManagement.WindowsDeviceCount      = $windowsCount
            $Assessment.DeviceManagement.iOSDeviceCount          = $iosCount
            $Assessment.DeviceManagement.AndroidDeviceCount      = $androidCount
            $Assessment.DeviceManagement.macOSDeviceCount        = $macCount

            Write-Log "Intune: ManagedDevices=$managedCount Compliant=$compliantCount Windows=$windowsCount iOS=$iosCount Android=$androidCount macOS=$macCount"

            if ( $managedCount -gt 0 )
            {
                $compliancePercent = [math]::Round( ( $compliantCount / $managedCount ) * 100, 0 )

                if ( $compliancePercent -lt 70 )
                {
                    $Assessment.Findings += New-Finding `
                        -Type           "LowDeviceCompliance" `
                        -Summary        "Only $compliancePercent% of managed devices are compliant" `
                        -Category       "DeviceManagement" `
                        -Severity       "Medium" `
                        -Impact         "Low compliance rates may indicate outdated policies or unenrolled devices that need attention before migration." `
                        -Recommendation "Review non-compliant devices and resolve compliance policy gaps before migration."
                }
            }
        }
        catch
        {
            Write-Log "Intune managed device collection failed: $( $_.Exception.Message )" "ERROR"

            $Assessment.DeviceManagement.IntuneConfigured   = $false
            $Assessment.DeviceManagement.MDMConfigured      = $false
            $Assessment.DeviceManagement.ManagedDeviceCount = $null

            $Assessment.Findings += New-Finding `
                -Type           "IntuneNotAvailable" `
                -Summary        "Intune device management data could not be collected -- insufficient license or permissions" `
                -Category       "DeviceManagement" `
                -Severity       "Info" `
                -Impact         "Device compliance, configuration policies, and app protection policies cannot be assessed." `
                -Recommendation "Verify Intune licensing and permissions before migration."
        }

        # -------------------------------------------------------------------
        # Configuration Policies
        # -------------------------------------------------------------------
        try
        {
            $configPolicies    = Get-MgDeviceManagementDeviceConfiguration -All -ErrorAction Stop
            $configPolicyCount = ( $configPolicies | Measure-Object ).Count

            $Assessment.DeviceManagement.ConfigurationPolicyCount = $configPolicyCount
            $Assessment.DeviceManagement.DeviceProfileCount       = $configPolicyCount

            Write-Log "Configuration Policies: $configPolicyCount"
        }
        catch
        {
            Write-Log "Configuration policy collection failed: $( $_.Exception.Message )" "WARN"
        }

        # -------------------------------------------------------------------
        # Compliance Policies
        # -------------------------------------------------------------------
        try
        {
            $compliancePolicies    = Get-MgDeviceManagementDeviceCompliancePolicy -All -ErrorAction Stop
            $compliancePolicyCount = ( $compliancePolicies | Measure-Object ).Count

            $Assessment.DeviceManagement.CompliancePolicyCount = $compliancePolicyCount

            Write-Log "Compliance Policies: $compliancePolicyCount"
        }
        catch
        {
            Write-Log "Compliance policy collection failed: $( $_.Exception.Message )" "WARN"
        }

        # -------------------------------------------------------------------
        # App Protection Policies
        # -------------------------------------------------------------------
        try
        {
            $appPolicies     = Get-MgDeviceAppManagementManagedAppPolicy -All -ErrorAction Stop
            $managedAppCount = ( $appPolicies | Measure-Object ).Count

            $appProtectionPolicies    = $appPolicies | Where-Object {
                $_.AdditionalProperties.'@odata.type' -match "ManagedAppProtection"
            }
            $appProtectionPolicyCount = ( $appProtectionPolicies | Measure-Object ).Count

            $Assessment.DeviceManagement.ManagedAppCount          = $managedAppCount
            $Assessment.DeviceManagement.AppProtectionPolicyCount = $appProtectionPolicyCount

            Write-Log "App Protection Policies: $appProtectionPolicyCount (Total Managed App Policies: $managedAppCount)"
        }
        catch
        {
            Write-Log "App protection policy collection failed: $( $_.Exception.Message )" "WARN"
        }

        # -------------------------------------------------------------------
        # Windows Autopilot
        # -------------------------------------------------------------------
        try
        {
            Write-Log "Checking Windows Autopilot"

            $ap    = Invoke-MgGraphRequest `
                -Method GET `
                -Uri    "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities" `
                -ErrorAction Stop

            $allAp = @()

            if ( $ap.value ) { $allAp += $ap.value }

            while ( $ap.'@odata.nextLink' )
            {
                $ap = Invoke-MgGraphRequest -Method GET -Uri $ap.'@odata.nextLink'
                if ( $ap.value ) { $allAp += $ap.value }
            }

            $apCount = $allAp.Count

            $Assessment.DeviceManagement.HasAutopilot         = ( $apCount -gt 0 )
            $Assessment.DeviceManagement.AutopilotDeviceCount = $apCount

            Write-Log "Autopilot devices: $apCount"

            if ( $apCount -gt 0 )
            {
                $Assessment.Findings += New-Finding `
                    -Type           "AutopilotDetected" `
                    -Summary        "$apCount Autopilot devices detected" `
                    -Category       "DeviceManagement" `
                    -Severity       "Medium" `
                    -Impact         "Autopilot devices are registered to the source tenant. Re-registration will be required in the target tenant." `
                    -Recommendation "Export Autopilot device hashes and plan re-registration in the target tenant as part of migration."
            }
        }
        catch
        {
            Write-Log "Autopilot collection failed: $( $_.Exception.Message )" "WARN"
            $Assessment.DeviceManagement.HasAutopilot         = $false
            $Assessment.DeviceManagement.AutopilotDeviceCount = 0
        }

        # -------------------------------------------------------------------
        # Defender Onboarding Signal
        # -------------------------------------------------------------------
        try
        {
            Write-Log "Evaluating Defender onboarding signal"

            $defenderCount = ( $devices | Where-Object {
                $_.PartnerReportedThreatState -ne "unknown" -and
                $null -ne $_.PartnerReportedThreatState
            } ).Count

            if ( $defenderCount -eq 0 )
            {
                $defenderCount = ( $devices | Where-Object { $null -ne $_.WindowsProtectionState } ).Count
            }

            $Assessment.DeviceManagement.HasDefenderOnboardedDevices  = ( $defenderCount -gt 0 )
            $Assessment.DeviceManagement.DefenderOnboardedDeviceCount = $defenderCount

            Write-Log "Defender onboarded devices: $defenderCount"
        }
        catch
        {
            Write-Log "Defender onboarding signal failed: $( $_.Exception.Message )" "WARN"
        }
    }
}