Src/Private/Get-AbrIntuneEnrollmentRestrictions.ps1

function Get-AbrIntuneEnrollmentRestrictions {
    <#
    .SYNOPSIS
    Documents Intune Device Enrollment Restrictions and configuration.
    .DESCRIPTION
        Collects and reports on:
          - Device Type Restrictions (platform allow/block)
          - Device Limit Restrictions (max devices per user)
          - Enrollment Status Page (ESP) profiles
          - Autopilot deployment profiles
    .NOTES
        Version: 0.1.0
        Author: Pai Wei Sing
    #>

    [CmdletBinding()]
    param (
        [Parameter(Position = 0, Mandatory)]
        [string]$TenantId
    )

    begin {
        Write-PScriboMessage -Message "Collecting Intune Enrollment Restrictions for $TenantId."
        Show-AbrDebugExecutionTime -Start -TitleMessage 'Enrollment Restrictions'
    }

    process {
        Section -Style Heading2 'Enrollment Restrictions' {
            Paragraph "The following section documents Device Enrollment configuration for tenant $TenantId."
            BlankLine

            $TotalEnrollmentRestrictions = 0
            $TotalAutopilotProfiles      = 0
            $TotalESPProfiles            = 0

            #region Device Type Restrictions
            try {
                Write-Host " - Retrieving device type restrictions..."
                $TypeRestResp = Invoke-MgGraphRequest -Method GET `
                    -Uri "$($script:GraphEndpoint)/v1.0/deviceManagement/deviceEnrollmentConfigurations?$expand=assignments" `
                    -ErrorAction SilentlyContinue
                $AllRestrictions = $TypeRestResp.value

                $null = ($TotalEnrollmentRestrictions = @($AllRestrictions).Count)
                if ($AllRestrictions -and @($AllRestrictions).Count -gt 0) {

                    # Device Type Restrictions
                    $TypeRestrictions = $AllRestrictions | Where-Object { $_.'@odata.type' -like '*deviceEnrollmentPlatformRestrictionsConfiguration*' }
                    if ($TypeRestrictions) {
                        Section -Style Heading3 'Device Type Restrictions' {
                            BlankLine
                            foreach ($Restriction in ($TypeRestrictions | Sort-Object priority)) {
                                $assignResolved = Resolve-IntuneAssignments -Assignments $Restriction.assignments
                                $AssignedTo = if ($assignResolved.AssignmentSummary -ne 'Not assigned') { $assignResolved.AssignmentSummary } else { 'Default (All Users)' }

                                $RestObj = [System.Collections.ArrayList]::new()
                                $restInObj = [ordered] @{
                                    'Restriction Name'     = $Restriction.displayName
                                    'Priority'             = $Restriction.priority
                                    'Assignments'          = $AssignedTo
                                }

                                # Platform-level settings
                                $Platforms = @('androidRestriction', 'androidForWorkRestriction', 'iosRestriction',
                                    'macOSRestriction', 'windowsRestriction', 'windowsMobileRestriction')
                                foreach ($PlatKey in $Platforms) {
                                    if ($Restriction.$PlatKey) {
                                        $PlatLabel = $PlatKey -replace 'Restriction', '' -replace 'androidForWork', 'Android Work Profile' `
                                            -replace 'android', 'Android' -replace 'ios', 'iOS' -replace 'macOS', 'macOS' `
                                            -replace 'windows$', 'Windows' -replace 'windowsMobile', 'Windows Mobile'
                                        $PlatData = $Restriction.$PlatKey
                                        $restInObj["$PlatLabel - Platform Blocked"]   = $PlatData.platformBlocked
                                        $restInObj["$PlatLabel - Personal Blocked"]   = $PlatData.personalDeviceEnrollmentBlocked
                                        if ($PlatData.osMinimumVersion) { $restInObj["$PlatLabel - Min OS"] = $PlatData.osMinimumVersion }
                                        if ($PlatData.osMaximumVersion) { $restInObj["$PlatLabel - Max OS"] = $PlatData.osMaximumVersion }
                                    }
                                }

                                $RestObj.Add([pscustomobject](ConvertTo-HashToYN $restInObj)) | Out-Null
                                $RestTableParams = @{ Name = "Type Restriction - $($Restriction.displayName)"; List = $true; ColumnWidths = 45, 55 }
                                if ($Report.ShowTableCaptions) { $RestTableParams['Caption'] = "- $($RestTableParams.Name)" }
                                $RestObj | Table @RestTableParams
                                BlankLine
                            }
                        }
                    }

                    # Device Limit Restrictions
                    $LimitRestrictions = $AllRestrictions | Where-Object { $_.'@odata.type' -like '*deviceEnrollmentLimitConfiguration*' }
                    if ($LimitRestrictions) {
                        Section -Style Heading3 'Device Limit Restrictions' {
                            BlankLine
                            $LimObj = [System.Collections.ArrayList]::new()
                            foreach ($Lim in ($LimitRestrictions | Sort-Object priority)) {
                                $assignResolved = Resolve-IntuneAssignments -Assignments $Lim.assignments
                                $AssignedTo = if ($assignResolved.AssignmentSummary -ne 'Not assigned') { $assignResolved.AssignmentSummary } else { 'Default (All Users)' }

                                $limInObj = [ordered] @{
                                    'Restriction Name'  = $Lim.displayName
                                    'Priority'          = $Lim.priority
                                    'Device Limit'      = $Lim.limit
                                    'Assignments'       = $AssignedTo
                                }
                                $LimObj.Add([pscustomobject]$limInObj) | Out-Null
                            }
                            $LimTableParams = @{ Name = "Device Limit Restrictions - $TenantId"; ColumnWidths = 35, 15, 20, 30 }
                            if ($Report.ShowTableCaptions) { $LimTableParams['Caption'] = "- $($LimTableParams.Name)" }
                            $LimObj | Table @LimTableParams
                        }
                    }

                    # Enrollment Status Page
                    $ESPProfiles = $AllRestrictions | Where-Object { $_.'@odata.type' -like '*windows10EnrollmentCompletionPageConfiguration*' }
                    $TotalESPProfiles = if ($ESPProfiles) { @($ESPProfiles).Count } else { 0 }
                    if ($ESPProfiles) {
                        Section -Style Heading3 'Enrollment Status Page (ESP)' {
                            BlankLine
                            $EspObj = [System.Collections.ArrayList]::new()
                            foreach ($ESP in ($ESPProfiles | Sort-Object priority)) {
                                $assignResolved = Resolve-IntuneAssignments -Assignments $ESP.assignments
                                $AssignedTo = if ($assignResolved.AssignmentSummary -ne 'Not assigned') { $assignResolved.AssignmentSummary } else { 'Default (All Devices)' }

                                $espInObj = [ordered] @{
                                    'ESP Profile Name'                    = $ESP.displayName
                                    'Priority'                            = $ESP.priority
                                    'Show Progress to End User'           = $ESP.showInstallationProgress
                                    'Block Device Until Provisioning'     = $ESP.blockDeviceSetupRetryByUser
                                    'Allow Reset if Installation Fails'   = $ESP.allowDeviceResetOnInstallFailure
                                    'Allow Use of Device Before Profile'  = $ESP.allowDeviceUseOnInstallFailure
                                    'Tracking Error Timeout (minutes)'    = if ($ESP.installProgressTimeoutInMinutes) { $ESP.installProgressTimeoutInMinutes } else { '--' }
                                    'Assignments'                         = $AssignedTo
                                }
                                $EspObj.Add([pscustomobject](ConvertTo-HashToYN $espInObj)) | Out-Null
                            }
                            $EspTableParams = @{ Name = "Enrollment Status Page Profiles - $TenantId"; List = $true; ColumnWidths = 50, 50 }
                            if ($Report.ShowTableCaptions) { $EspTableParams['Caption'] = "- $($EspTableParams.Name)" }
                            $EspObj | Table @EspTableParams
                        }
                    }

                    if (Get-IntuneBackupSectionEnabled -SectionKey 'EnrollmentRestrictions') { $script:BackupData['EnrollmentRestrictions'] = $AllRestrictions }
                    if (Get-IntuneExcelSheetEnabled -SheetKey 'EnrollmentRestrictions') {
                        $AllRestrictionsExcel = $AllRestrictions | ForEach-Object {
                            [pscustomobject]@{
                                'Name'      = $_.displayName
                                'Type'      = $_.'@odata.type' -replace '#microsoft.graph.', ''
                                'Priority'  = $_.priority
                            }
                        }
                        $script:ExcelSheets['Enrollment Restrictions'] = $AllRestrictionsExcel
                    }

                } else {
                    Paragraph "No Enrollment Restrictions found in tenant $TenantId."
                }

            } catch {
                    if (Test-AbrGraphForbidden -ErrorRecord $_) {
                        Write-AbrPermissionError -Section 'Enrollment Restrictions' -RequiredRole 'Intune Service Administrator or Global Administrator'
                    } else {
                        Write-AbrSectionError -Section 'Enrollment Restrictions' -Message "$($_.Exception.Message)"
                    }
                }
            #endregion

            #region Windows Autopilot Deployment Profiles
            try {
                Write-Host " - Retrieving Windows Autopilot profiles..."
                # /beta required -- windowsAutopilotDeploymentProfiles is not supported in v1.0
                $AutopilotResp = Invoke-MgGraphRequest -Method GET `
                    -Uri "$($script:GraphEndpoint)/beta/deviceManagement/windowsAutopilotDeploymentProfiles?$expand=assignments" `
                    -ErrorAction SilentlyContinue
                $AutopilotProfiles = $AutopilotResp.value

                $TotalAutopilotProfiles = if ($AutopilotProfiles) { @($AutopilotProfiles).Count } else { 0 }
                if ($TotalAutopilotProfiles -gt 0) {
                    Section -Style Heading3 'Autopilot Deployment Profiles' {
                        BlankLine
                        $APObj = [System.Collections.ArrayList]::new()
                        foreach ($APProfile in ($AutopilotProfiles | Sort-Object displayName)) {
                            $assignResolved = Resolve-IntuneAssignments -Assignments $APProfile.assignments -CheckMemberCount:$script:CheckEmptyGroups
                        $AssignedTo = $assignResolved.AssignmentSummary
                            $apInObj = [ordered] @{
                                'Profile Name'          = $APProfile.displayName
                                'Join Type'             = if ($APProfile.hybridAzureADJoinSkipConnectivityCheck -ne $null) { 'Hybrid Azure AD' } else { 'Azure AD' }
                                'Deployment Mode'       = $APProfile.deploymentMode
                                'Out of Box Experience' = if ($APProfile.outOfBoxExperienceSetting) { $APProfile.outOfBoxExperienceSetting.deviceUsageType } else { '--' }
                                'Skip Keyboard'         = $APProfile.deviceNameTemplate
                                'Assignments'           = $AssignedTo
                                'Last Modified'         = if ($APProfile.lastModifiedDateTime) { ([datetime]$APProfile.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' }
                            }
                            $APObj.Add([pscustomobject]$apInObj) | Out-Null
                        }

                        $null = (& {
                            if ($HealthCheck.Intune.EnrollmentRestrictions) {
                                $null = ($APObj | Where-Object { $_.'Assignments' -eq 'Not assigned' } | Set-Style -Style Warning | Out-Null)
                            }
                        })

                        $APTableParams = @{ Name = "Autopilot Deployment Profiles - $TenantId"; ColumnWidths = 22, 14, 14, 14, 12, 14, 10 }
                        if ($Report.ShowTableCaptions) { $APTableParams['Caption'] = "- $($APTableParams.Name)" }
                        $APObj | Table @APTableParams

                        if (Get-IntuneExcelSheetEnabled -SheetKey 'AutopilotProfiles') {
                            $script:ExcelSheets['Autopilot Profiles'] = $APObj
                        }
                        if (Get-IntuneBackupSectionEnabled -SectionKey 'AutopilotProfiles') { $script:BackupData['AutopilotProfiles'] = $AutopilotProfiles }
                    }
                }
            } catch {
                    if (Test-AbrGraphForbidden -ErrorRecord $_) {
                        Write-AbrPermissionError -Section 'Autopilot Deployment Profiles' -RequiredRole 'Intune Service Administrator or Global Administrator'
                    } else {
                        Write-AbrSectionError -Section 'Autopilot Deployment Profiles' -Message "$($_.Exception.Message)"
                    }
                }
            #endregion

            #region ACSC E8 Assessment
            if ($script:IncludeACSCe8) {
                BlankLine
                Paragraph "ACSC Essential Eight Maturity Level Assessment -- Enrollment Restrictions:"
                BlankLine
                try {
                    $_v = @{
                        TotalEnrollmentRestrictions = $TotalEnrollmentRestrictions
                        TotalAutopilotProfiles      = $TotalAutopilotProfiles
                        TotalESPProfiles            = $TotalESPProfiles
                    }
                    $E8Checks = Build-AbrIntuneComplianceChecks -Definitions (Get-AbrIntuneE8Checks -Section 'EnrollmentRestrictions') -Framework E8 -CallerVariables $_v
                    New-AbrIntuneE8AssessmentTable -Checks $E8Checks -Name 'Enrollment Restrictions' -TenantId $TenantId
                    if ($E8Checks) { $null = $script:E8AllChecks.AddRange([object[]](@($E8Checks | Select-Object @{N='Section';E={'EnrollmentRestrictions'}}, ML, Control, Status, Detail))) }
                } catch { Write-AbrSectionError -Section 'E8 Enrollment Assessment' -Message "$($_.Exception.Message)" }
            }
            #endregion

            #region CIS Assessment
            if ($script:IncludeCISBaseline) {
                BlankLine
                Paragraph "CIS Microsoft 365 Foundations Benchmark Assessment -- Enrollment Restrictions:"
                BlankLine
                try {
                    $_v = @{
                        TotalEnrollmentRestrictions = $TotalEnrollmentRestrictions
                        TotalESPProfiles            = $TotalESPProfiles
                    }
                    $CISChecks = Build-AbrIntuneComplianceChecks -Definitions (Get-AbrIntuneCISChecks -Section 'EnrollmentRestrictions') -Framework CIS -CallerVariables $_v
                    New-AbrIntuneCISAssessmentTable -Checks $CISChecks -Name 'Enrollment Restrictions' -TenantId $TenantId
                    if ($CISChecks) { $null = $script:CISAllChecks.AddRange([object[]](@($CISChecks | Select-Object @{N='Section';E={'EnrollmentRestrictions'}}, CISControl, Level, Status, Detail))) }
                } catch { Write-AbrSectionError -Section 'CIS Enrollment Assessment' -Message "$($_.Exception.Message)" }
            }
            #endregion
        }
    }

    end { Show-AbrDebugExecutionTime -End -TitleMessage 'Enrollment Restrictions' }
}