Files
IntuneManagement/Classes/IntuneEnrollmentClasses.ps1

692 lines
31 KiB
PowerShell

#ImportOrder 220
#########################################################################################
#
# Script Group
#
#########################################################################################
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("TypeNotFound","", Justification = "")]
class DeviceEnrollmentGroup : IntunePolicyGroupBase
{
DeviceEnrollmentGroup() : Base()
{
$this.Init()
}
Init()
{
$this._ID = "DeviceEnrollments"
$this._Name = "Device enrollment"
$this._Icon = "WindowsEnrollments"
}
}
#########################################################################################
#
# Autopilot
#
#########################################################################################
# region Autopilot
class AutopilotType : IntunePolicyTypeBase
{
AutopilotType() : Base()
{
$this.Init()
}
Init()
{
$this._PolicyGroup = (Get-SingletonObject "DeviceEnrollmentGroup")
$this._PolicyName = "Autopilot"
$this._ID = "Autopilot"
# Platform default: the endpoint serves exactly one platform and the
# objects carry no platforms/platformType field, so the column would
# otherwise be blank (windowsAutopilotDeploymentProfiles is
# Windows-only).
$this._PlatformName = Get-LanguageString "Platform.windows" -IgnoreMissing
$this._API = "deviceManagement/windowsAutopilotDeploymentProfiles"
$this._CopyDefaultName = "%Name% Copy"
$this._Permissions = @("DeviceManagementServiceConfig.ReadWrite.All")
$this._ObjectClass = "AutopilotObject"
$this._PropertiesToRemoveForUpdate = @('managementServiceAppId')
if($null -ne $this._PolicyGroup) {
$this._PolicyGroup.AddPolicyType($this)
}
}
[Hashtable]PreDeleteCommand([IntunePolicyBase]$PolicyObject)
{
Write-Log "Delete AutoPilot profile assignments"
foreach($assignment in $PolicyObject.Assignments)
{
if($assignment.Source -ne "direct") { continue }
$api = "$($PolicyObject.PolicyType.API)/$($PolicyObject.Id)/assignments/$($assignment.Id)"
$repsone = Invoke-MSGraphAPI -Url $api -HttpMethod "DELETE" -TokenId $PolicyObject._TokenId -FullResponseObject
if($repsone.Success)
{
Write-LogDebug "Assignemnt with Id $($assignment.Id) deleted successfully"
}
}
return $null
}
[Hashtable]PreImportAssignmentsCommand([PSCustomObject]$PolicyObject, [PSCustomObject]$SourceObject)
{
return (Add-GraphAssignmentsToObject $PolicyObject $SourceObject)
}
}
Class AutopilotObject : IntunePolicyBase
{
AutopilotObject([PSCustomObject]$JsonObj) : Base($JsonObj) { $this.Init() }
AutopilotObject() : Base()
{
$this.Init()
$this._PlatformName = Get-LanguageString "Platform.windows" -IgnoreMissing
}
Hidden Init()
{
$this._PolicyType = (Get-SingletonObject "AutopilotType")
}
}
#########################################################################################
#
# Device Enrollment
#
#########################################################################################
# region Device Enrollment
# DeviceEnrollmentType is the SHARED BASE for everything served by
# /deviceManagement/deviceEnrollmentConfigurations. The Graph endpoint returns
# eight subtypes of an abstract base type (per the schema):
# deviceEnrollmentLimitConfiguration ('limit' / 'defaultLimit')
# deviceEnrollmentPlatformRestrictionConfiguration ('singlePlatformRestriction')
# deviceEnrollmentPlatformRestrictionsConfiguration ('platformRestrictions' / 'defaultPlatformRestrictions')
# deviceEnrollmentWindowsHelloForBusinessConfiguration('windowsHelloForBusiness' / 'defaultWindowsHelloForBusiness')
# windows10EnrollmentCompletionPageConfiguration ('windows10EnrollmentCompletionPageConfiguration' / 'defaultWindows10EnrollmentCompletionPageConfiguration')
# deviceComanagementAuthorityConfiguration ('deviceComanagementAuthorityConfiguration')
# deviceEnrollmentNotificationConfiguration ('enrollmentNotificationsConfiguration')
# windowsRestoreDeviceEnrollmentConfiguration ('windowsRestore')
#
# Each logical bucket gets its own thin subtype below. The base only carries
# import/export/replace behavior — it is NOT registered as a policy type itself
# (no _PolicyGroup), so $script:IntuneTypes only contains the concrete buckets.
#
# Server-side filtering by `deviceEnrollmentConfigurationType eq '...'` is value-exact
# and excludes the 'default*' variants, so subtypes filter client-side via CheckPolicy
# on @odata.type. With identical _API/_QueryList across siblings, Get-GraphPolicies
# coalesces them into ONE batch sub-request and fans rows out to the matching subtype.
class DeviceEnrollmentType : IntunePolicyTypeBase
{
# Abstract: only concrete subtypes (EnrollmentStatusPageType, EnrollmentLimitType, ...)
# may be instantiated. Auto-discovery loops in Invoke-IntuneEventAppInitialized and
# the UI extensions consult Test-ClassIsAbstract on each candidate and skip those
# declaring this static marker, so $script:IntuneTypes only contains concrete buckets.
static [bool] $IsAbstract = $true
DeviceEnrollmentType() : Base()
{
([DeviceEnrollmentType]$this).Init()
}
Init()
{
# Everything in this Init is shared across every concrete bucket. Subtypes only
# override _ID, _APITitle, _PolicyName, _Folder, _QueryList, _PlatformName (when
# platform-specific), and CheckPolicy. Subtypes do NOT need to call this Init
# explicitly — the constructor chain already runs it via : Base() → DeviceEnrollmentType()
# body's ([DeviceEnrollmentType]$this).Init().
$this._API = "deviceManagement/deviceEnrollmentConfigurations"
# Endpoint rejects a name $filter (verified live 2026-08-27) - searches filter client-side.
$this._SupportsNameFilter = $false
$this._Permissions = @("DeviceManagementServiceConfig.ReadWrite.All")
$this._SkipRemoveProperties = @('Id')
$this._PropertiesToRemoveForUpdate = @('priority')
$this._Dependencies = @('Applications')
$this._AssignmentsType = "enrollmentConfigurationAssignments"
$this._Icon = "EnrollmentStatusPage"
$this._PolicyGroup = (Get-SingletonObject "DeviceEnrollmentGroup")
$this._ObjectClass = "DeviceEnrollmentObject"
$this._VerifyObject = $true
# _ExpandAssignmentsList stays at its default ($true) so the list URL appends
# &$expand=assignments. The Intune portal does this on every enrollment-config
# subtype, and Graph accepts it here, so we get assignments inline and skip the
# follow-up /assignments round-trip in Add-GraphPolicyAssignments.
# No _QueryList here — each subtype owns its filter. Combining filters across
# subtypes via OR was unreliable (Graph's batch endpoint dropped most matches).
}
[Hashtable]PreImportCommand([PSCustomObject]$PolicyObject)
{
if($PolicyObject.Object.Priority -eq 0)
{
$ret = @{}
$ret.Add("API","$($PolicyObject.PolicyType.API)/$($PolicyObject.Id)")
$ret.Add("Method","PATCH") # Default profile always exists so update them
$ret
}
else
{
Remove-Property $PolicyObject.Object "Id"
}
return $null
}
[Hashtable]PreImportAssignmentsCommand([PSCustomObject]$PolicyObject, [PSCustomObject]$SourceObject)
{
if($SourceObject.Object.Priority -eq 0) { return @{ "Import" = $false } }
return $null
}
[Hashtable]PreDeleteCommand([IntunePolicyBase]$PolicyObject)
{
if($PolicyObject.Object.Priority -eq 0) { return @{ "Delete" = $false } }
return $null
}
[Hashtable]PreReplaceCommand([IntunePolicyBase]$PolicyObject)
{
if($PolicyObject.Object.Priority -eq 0) { return @{ "Delete" = $false } }
return $null
}
PostReplaceCommand([IntunePolicyBase]$PolicyObject, [IntunePolicyBase]$SourceObject)
{
Set-EnrollmentRestrictionsPriority $PolicyObject $SourceObject
}
}
# Shared Object class for every DeviceEnrollment subtype. PolicyName, Folder and
# Platform routing all flow from the subtype's TYPE class (_PolicyName / _Folder /
# _PlatformName), not per-instance switches on @odata.type:
# * IntunePolicyTypeBase.GetObject sets policyObject._PolicyType = $this (the calling
# subtype) after construction, so $obj.PolicyType.Folder / .PolicyName resolve to
# the right subtype's values.
# * IntunePolicyBase.Platform getter falls back to _PolicyType._PlatformName when the
# instance doesn't set its own — that's how Windows-only buckets (ESP, WHfB,
# CoMgmt, WindowsRestore) report Platform=Windows.
# The constructor is intentionally empty: IntunePolicyBase's : Base($JsonObj) chain
# already runs the Add-ObjectProperty setup. Anything we'd add to a subclass Init here
# is per-subtype concern and lives on the subtype TYPE.
Class DeviceEnrollmentObject : IntunePolicyBase
{
DeviceEnrollmentObject([PSCustomObject]$JsonObj) : Base($JsonObj) { }
DeviceEnrollmentObject() : Base() { }
[String]GetFileName([String]$Path)
{
# Default policies (priority=0) have a localized boilerplate displayName
# ("All users and all devices") that collides across subtypes — both
# DefaultLimit and DefaultPlatformRestrictions land on the same name and
# one overwrites the other. Their id-suffix is unique per subtype
# (DefaultLimit / DefaultPlatformRestrictions / DefaultWindowsHelloForBusiness /
# DefaultWindows10EnrollmentCompletionPageConfiguration), so we use that.
# Non-default policies have id format <randomGuid>_<configTypeSuffix> where
# the suffix is identical for every policy of a given subtype, so we use
# displayName instead.
# We use TWO signals — priority OR a TenantId-prefixed id — because each
# has a failure mode on its own:
# * priority alone: depends on Graph exposing 'priority' on every payload
# and on it staying =0 for default policies (mostly true but not
# guaranteed across endpoints / future schema changes).
# * TenantId prefix alone: requires $this.TenantId to be populated by the
# time GetFileName runs; it isn't always (file-load paths, certain
# bulk-export code paths skip the TenantId-set step).
# Combining them is robust: a row that's a default in EITHER sense uses the
# id-suffix, everything else uses displayName.
$isDefault = ($this.Object.priority -eq 0) -or `
($this.TenantId -and $this.Id -and $this.Id.StartsWith($this.TenantId + "_"))
if($isDefault) {
$parts = $this.Id -split '_', 2
$name = if($parts.Count -ge 2) { $parts[1] } else { $null }
}
else {
$name = $this.Object.displayName
}
if(-not $name) { $name = $this.Id }
# Same id-suffix rule as IntunePolicyBase.GetFileName, which this override
# replaced wholesale and therefore silently dropped: both the user-facing
# AddIDToExportFile setting AND the bulk-export collision flag were ignored
# here, so two non-default enrollment policies of the same subtype sharing a
# displayName still wrote the same file and one overwrote the other - the
# collision was DETECTED and then not acted on.
#
# A default policy takes its name from the id suffix already, which is unique
# per subtype, so the flag will not normally fire for one; the rule is applied
# unconditionally anyway rather than only in the else-branch, so an id-suffix
# name that does somehow collide is still disambiguated.
$forceId = (Get-SettingValue "AddIDToExportFile") -eq $true -or $this._NeedsIdInFilename -eq $true
if($forceId -and $this.Id -and $this.PolicyType.SkipAddIDOnFileName -ne $true -and $name -ne $this.Id) {
$name = ($name + "_" + $this.Id)
}
$fileName = "$((Remove-InvalidFileNameChars $name)).json"
if($Path) { $fileName = [IO.Path]::Combine($Path, $fileName) }
return $fileName
}
}
# Concrete bucket conventions:
# * Constructor delegates to : Base() (= DeviceEnrollmentType) which runs the shared
# Init via the constructor chain. Subtype Init does NOT call the base Init
# explicitly — that would run the base Init twice.
# * Subtype Init only sets bucket-specific fields: _ID, _APITitle, _PolicyName,
# _Folder, _QueryList, optionally _PlatformName, then registers via AddPolicyType.
# * CheckPolicy stays as a defensive client-side filter; @odata.type is the primary
# discriminator with deviceEnrollmentConfigurationType as a fallback.
class EnrollmentStatusPageType : DeviceEnrollmentType
{
EnrollmentStatusPageType() : Base() { ([EnrollmentStatusPageType]$this).Init() }
Init()
{
$this._ID = "EnrollmentStatusPage"
$this._APITitle = "Enrollment Status Page"
$this._PolicyName = "Enrollment Status Page"
$this._Folder = "EnrollmentStatusPage"
$this._PlatformName = Get-LanguageString "Platform.windows" -IgnoreMissing
# Single eq is enough: empirically Graph returns both default and non-default
# ESPs for this filter. (Adding 'defaultWindows10…' as a second clause causes
# a 400 — that enum value is in the schema but rejected by the live filter parser.)
$this._QueryList = "?`$filter=deviceEnrollmentConfigurationType eq 'windows10EnrollmentCompletionPageConfiguration'"
if($null -ne $this._PolicyGroup) { $this._PolicyGroup.AddPolicyType($this) }
}
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
{
if ($PolicyObject.'@odata.type' -eq '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration') { return $true }
return ($PolicyObject.deviceEnrollmentConfigurationType -eq 'windows10EnrollmentCompletionPageConfiguration')
}
}
class EnrollmentRestrictionsPageType : DeviceEnrollmentType
{
EnrollmentRestrictionsPageType() : Base() { ([EnrollmentRestrictionsPageType]$this).Init() }
Init()
{
$this._ID = "EnrollmentRestrictions"
$this._APITitle = "Enrollment Restrictions"
$this._PolicyName = "Device platform restrictions"
$this._Folder = "EnrollmentRestrictions"
# Cross-platform (covers iOS / Android / Windows etc.) — no _PlatformName.
# Single eq clause empirically returns BOTH per-platform Block Android-style
# configs (@odata.type singular) AND the default combined platform restrictions
# (@odata.type plural, id-suffix _DefaultPlatformRestrictions). 'limit' lives
# on EnrollmentLimitType because stacking a second eq clause on the same
# property in batch mode caused Graph's batch endpoint to drop most matches.
$this._QueryList = "?`$filter=deviceEnrollmentConfigurationType eq 'singlePlatformRestriction'"
if($null -ne $this._PolicyGroup) { $this._PolicyGroup.AddPolicyType($this) }
}
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
{
if ($PolicyObject.'@odata.type' -in @(
'#microsoft.graph.deviceEnrollmentPlatformRestrictionConfiguration',
'#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration')) { return $true }
return ($PolicyObject.deviceEnrollmentConfigurationType -in @(
'singlePlatformRestriction',
'platformRestrictions',
'defaultPlatformRestrictions'))
}
}
class EnrollmentLimitType : DeviceEnrollmentType
{
EnrollmentLimitType() : Base() { ([EnrollmentLimitType]$this).Init() }
Init()
{
$this._ID = "EnrollmentLimit"
$this._HasPlatform = $false
$this._APITitle = "Enrollment Limit"
$this._PolicyName = "Device limit restrictions"
# Same folder as platform restrictions — matches the OLD baseline export where
# EnrollmentRestrictions/ bundled limit + platform restriction policies together.
$this._Folder = "EnrollmentRestrictions"
$this._QueryList = "?`$filter=deviceEnrollmentConfigurationType eq 'limit'"
if($null -ne $this._PolicyGroup) { $this._PolicyGroup.AddPolicyType($this) }
}
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
{
if ($PolicyObject.'@odata.type' -eq '#microsoft.graph.deviceEnrollmentLimitConfiguration') { return $true }
return ($PolicyObject.deviceEnrollmentConfigurationType -in @('limit', 'defaultLimit'))
}
}
class WindowsHelloForBusinessType : DeviceEnrollmentType
{
WindowsHelloForBusinessType() : Base() { ([WindowsHelloForBusinessType]$this).Init() }
Init()
{
$this._ID = "WindowsHelloForBusiness"
$this._APITitle = "Windows Hello for Business"
$this._PolicyName = "Windows Hello for Business"
$this._Folder = "WindowsHelloForBusiness"
$this._PlatformName = Get-LanguageString "Platform.windows" -IgnoreMissing
$this._QueryList = "?`$filter=deviceEnrollmentConfigurationType eq 'windowsHelloForBusiness'"
if($null -ne $this._PolicyGroup) { $this._PolicyGroup.AddPolicyType($this) }
}
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
{
if ($PolicyObject.'@odata.type' -eq '#microsoft.graph.deviceEnrollmentWindowsHelloForBusinessConfiguration') { return $true }
return ($PolicyObject.deviceEnrollmentConfigurationType -eq 'windowsHelloForBusiness')
}
}
class CoManagementSettingsType : DeviceEnrollmentType
{
CoManagementSettingsType() : Base() { ([CoManagementSettingsType]$this).Init() }
Init()
{
$this._ID = "CoManagementSettings"
$this._APITitle = "Co-Management Settings"
$this._PolicyName = "Co-Management Settings"
$this._Folder = "CoManagementSettings"
$this._PlatformName = Get-LanguageString "Platform.windows" -IgnoreMissing
$this._QueryList = "?`$filter=deviceEnrollmentConfigurationType eq 'deviceComanagementAuthorityConfiguration'"
if($null -ne $this._PolicyGroup) { $this._PolicyGroup.AddPolicyType($this) }
}
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
{
if ($PolicyObject.'@odata.type' -eq '#microsoft.graph.deviceComanagementAuthorityConfiguration') { return $true }
return ($PolicyObject.deviceEnrollmentConfigurationType -eq 'deviceComanagementAuthorityConfiguration')
}
}
class WindowsRestoreType : DeviceEnrollmentType
{
WindowsRestoreType() : Base() { ([WindowsRestoreType]$this).Init() }
Init()
{
$this._ID = "WindowsRestore"
$this._APITitle = "Windows Restore"
$this._PolicyName = "Windows Restore"
$this._Folder = "WindowsRestore"
$this._PlatformName = Get-LanguageString "Platform.windows" -IgnoreMissing
$this._QueryList = "?`$filter=deviceEnrollmentConfigurationType eq 'windowsRestore'"
if($null -ne $this._PolicyGroup) { $this._PolicyGroup.AddPolicyType($this) }
}
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
{
if ($PolicyObject.'@odata.type' -eq '#microsoft.graph.windowsRestoreDeviceEnrollmentConfiguration') { return $true }
return ($PolicyObject.deviceEnrollmentConfigurationType -eq 'windowsRestore')
}
}
#########################################################################################
#
# Enrollment Notification
#
#########################################################################################
# region Enrollment Notification
# Note: Email and Push notifications are defined in the Notifications class in the Compliance class file.
# This bucket follows the same shape as the other DeviceEnrollment subtypes:
# no _QueryList (so the URL coalesces with siblings in Get-GraphPolicies), client-side
# filter via CheckPolicy on @odata.type, shared DeviceEnrollmentObject.
class EnrollmentNotificationType : DeviceEnrollmentType
{
EnrollmentNotificationType() : Base() { ([EnrollmentNotificationType]$this).Init() }
Init()
{
$this._ID = "EnrollmentNotification"
$this._HasPlatform = $false
$this._APITitle = "Enrollment notifications"
$this._PolicyName = "Enrollment notification"
$this._Folder = "EnrollmentNotifications"
# Cross-platform (email + push notifications target any enrolled device).
$this._QueryList = "?`$filter=deviceEnrollmentConfigurationType eq 'enrollmentNotificationsConfiguration'"
if($null -ne $this._PolicyGroup) { $this._PolicyGroup.AddPolicyType($this) }
}
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
{
if ($PolicyObject.'@odata.type' -eq '#microsoft.graph.deviceEnrollmentNotificationConfiguration') { return $true }
return ($PolicyObject.deviceEnrollmentConfigurationType -eq 'enrollmentNotificationsConfiguration')
}
# ToDo: Add support for importing, exporting, copying Notifications between environment eg
# notificationTemplates property has a string list of actual notification template policies Email_<GUID of Notification Template>
}
#########################################################################################
#
# Generic functions
#
#########################################################################################
function Set-EnrollmentRestrictionsPriority
{
param($PolicyObject, $SourceObj)
if($PolicyObject.Object.Priority -eq 0) { return }
$api = "$($PolicyObject.PolicyType.API)/$($PolicyObject.Id)/setpriority"
$priority = [PSCustomObject]@{
priority = $SourceObj.Object.Priority
}
$json = $priority | ConvertTo-Json -Depth 20
Write-Log "Update priority for $($PolicyObject.Name) to $($PolicyObject.Object.Priority)"
Invoke-MSGraphAPI -Url $api -HttpMethod "POST" -Content $json -TokenId $PolicyObject._TokenId
}
#########################################################################################
#
# Android Device Owner Enrollment Profiles
#
#########################################################################################
#
# Profile used to enrol corporate-owned Android devices (dedicated devices,
# fully-managed, AOSP, Teams devices) via QR code or token. Listed flat at
# /deviceManagement/androidDeviceOwnerEnrollmentProfiles — not part of the
# deviceEnrollmentConfigurations multi-subtype tree.
# region AndroidDeviceOwnerEnrollmentProfilesType
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("TypeNotFound","", Justification = "")]
class AndroidDeviceOwnerEnrollmentProfilesType : IntunePolicyTypeBase
{
AndroidDeviceOwnerEnrollmentProfilesType() : Base()
{
$this.Init()
}
Init()
{
$this._PolicyGroup = (Get-SingletonObject "DeviceEnrollmentGroup")
$this._PolicyName = "Android Enterprise — corporate"
$this._ID = "AndroidDeviceOwnerEnrollmentProfiles"
$this._API = "deviceManagement/androidDeviceOwnerEnrollmentProfiles"
# AndroidCOWP icon (Corporate-Owned With Profile) is the closest
# existing match for the Device Owner enrolment surface.
$this._Icon = "AndroidCOWP"
$this._Permissions = @("DeviceManagementServiceConfig.ReadWrite.All")
# Server-generated bits that come back on GET but Graph rejects on
# POST/PATCH. enrolledDeviceCount + token{*} + qrCode* are derived;
# accountId is set from the calling tenant.
$this._PropertiesToRemove = @('accountId','enrolledDeviceCount','enrollmentTokenUsageCount','qrCodeContent','qrCodeImage','tokenCreationDateTime','tokenExpirationDateTime','tokenValue')
$this._PropertiesToRemoveForUpdate = @('accountId','enrolledDeviceCount','enrollmentTokenUsageCount','qrCodeContent','qrCodeImage','tokenCreationDateTime','tokenExpirationDateTime','tokenValue','enrollmentMode','enrollmentTokenType')
# Profile, not policy — no group assignments.
$this._SupportsAssignments = $false
# Graph returns HTTP 400 on `androidDeviceOwnerEnrollmentProfiles?$expand=assignments`,
# even though SupportsAssignments=$false; the list-URL builder still
# appends the expand unless this is explicitly suppressed.
$this._ExpandAssignmentsList = $false
$this._ObjectClass = "AndroidDeviceOwnerEnrollmentProfileObject"
if($null -ne $this._PolicyGroup) {
$this._PolicyGroup.AddPolicyType($this)
}
}
}
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("TypeNotFound","", Justification = "")]
class AndroidDeviceOwnerEnrollmentProfileObject : IntunePolicyBase
{
AndroidDeviceOwnerEnrollmentProfileObject([PSCustomObject]$JsonObj) : Base($JsonObj) { $this.Init() }
AndroidDeviceOwnerEnrollmentProfileObject() : Base()
{
$this.Init()
}
Hidden Init()
{
$this._PolicyType = (Get-SingletonObject "AndroidDeviceOwnerEnrollmentProfilesType")
# Language pack uses Platform.androidForWork for AOSP/Android Enterprise
# surfaces; fall back to a literal if the key is missing in en-US.
$this._PlatformName = Get-LanguageString "Platform.androidForWork" -IgnoreMissing
if(-not $this._PlatformName) { $this._PlatformName = "Android Enterprise" }
}
}
#########################################################################################
#
# Android For Work Enrollment Profiles
#
#########################################################################################
#
# Profile used to enrol personal Android devices into a managed Work Profile
# (BYOD). Endpoint at /deviceManagement/androidForWorkEnrollmentProfiles. No
# scope tag support, no assignments — purely token + QR for the end user.
# region AndroidForWorkEnrollmentProfilesType
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("TypeNotFound","", Justification = "")]
class AndroidForWorkEnrollmentProfilesType : IntunePolicyTypeBase
{
AndroidForWorkEnrollmentProfilesType() : Base()
{
$this.Init()
}
Init()
{
$this._PolicyGroup = (Get-SingletonObject "DeviceEnrollmentGroup")
$this._PolicyName = "Android Enterprise — work profile"
$this._ID = "AndroidForWorkEnrollmentProfiles"
$this._API = "deviceManagement/androidForWorkEnrollmentProfiles"
# AndroidGooglePlay icon — work-profile enrolment is the personal-device
# / Play-store-managed surface, so the GP icon reads better than the
# corporate AndroidCOWP one used for the Device Owner type.
$this._Icon = "AndroidGooglePlay"
$this._Permissions = @("DeviceManagementServiceConfig.ReadWrite.All")
# Schema has no roleScopeTagIds, so disable the scope-tag column /
# detail-view widget for this type. Leaving the default ("roleScopeTagIds")
# would surface an empty UI and a 400 on save.
$this._ScopeTagProperty = $null
# Server-generated fields Graph rejects on POST/PATCH.
$this._PropertiesToRemove = @('accountId','enrolledDeviceCount','qrCodeContent','qrCodeImage','tokenValue','tokenExpirationDateTime')
$this._PropertiesToRemoveForUpdate = @('accountId','enrolledDeviceCount','qrCodeContent','qrCodeImage','tokenValue','tokenExpirationDateTime')
$this._SupportsAssignments = $false
# Graph returns HTTP 400 on `androidForWorkEnrollmentProfiles?$expand=assignments`.
$this._ExpandAssignmentsList = $false
$this._ObjectClass = "AndroidForWorkEnrollmentProfileObject"
if($null -ne $this._PolicyGroup) {
$this._PolicyGroup.AddPolicyType($this)
}
}
}
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("TypeNotFound","", Justification = "")]
class AndroidForWorkEnrollmentProfileObject : IntunePolicyBase
{
AndroidForWorkEnrollmentProfileObject([PSCustomObject]$JsonObj) : Base($JsonObj) { $this.Init() }
AndroidForWorkEnrollmentProfileObject() : Base()
{
$this.Init()
}
Hidden Init()
{
$this._PolicyType = (Get-SingletonObject "AndroidForWorkEnrollmentProfilesType")
$this._PlatformName = Get-LanguageString "Platform.androidForWork" -IgnoreMissing
if(-not $this._PlatformName) { $this._PlatformName = "Android Enterprise" }
}
}
#########################################################################################
#
# Settings Catalog
#
#########################################################################################
# region Settings Catalog
class EnrollmentSettingsCatalogType : SettingsCatalogTypeBase
{
EnrollmentSettingsCatalogType() : Base()
{
([EnrollmentSettingsCatalogType]$this).Init()
}
Init()
{
$this._PolicyGroup = (Get-SingletonObject "DeviceEnrollmentGroup")
$this._APITitle = "Enrollment Policies (Settings Catalog)"
$this._ID = "EnrollmentSettingsCatalog"
# Startup default only - Invoke-IntuneSettingsCatalogAuthenticated rebuilds
# this from _FamilyTypes once Graph reports the live template list.
# windowsOsRecoveryPolicies is NOT listed here: it falls to SettingsCatalog's
# catch-all spec, so claiming it would only fetch rows CheckPolicy rejects.
$this._QueryList = "?`$filter=templateReference/templateFamily eq 'enrollmentConfiguration'"
$this._Icon = "EnrollmentStatusPage"
if($null -ne $this._PolicyGroup) {
$this._PolicyGroup.AddPolicyType($this)
}
$this._PolicyTypeOrder = 160
}
}
<#
class AutopilotDevicePreparationSettingsCatalogType : SettingsCatalogTypeBase
{
AutopilotDevicePreparationSettingsCatalogType() : Base()
{
$this.Init()
}
Init()
{
$this._PolicyGroup = (Get-SingletonObject "DeviceEnrollmentGroup")
$this._ID = "AutopilotDevicePreparationSettingsCatalog"
$this._APITitle = "Autopilot Device Preparation (Settings Catalog)"
#$this._QueryList = "?`$filter=(technologies has 'enrollment') and (platforms eq 'windows10') and (TemplateReference/templateId eq '80d33118-b7b4-40d8-b15f-81be745e053f_1') and (Templatereference/templateFamily eq 'enrollmentConfiguration')"
$this._QueryList = "?`$filter=(technologies has 'enrollment') and (platforms eq 'windows10') and (Templatereference/templateFamily eq 'enrollmentConfiguration')"
$this._Folder = "SettingsCatalog"
if($null -ne $this._PolicyGroup) {
$this._PolicyGroup.AddPolicyType($this)
}
$this._PolicyTypeOrder = 100
}
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
{
if($PolicyObject.'@odata.type' -ne "#microsoft.graph.deviceManagementConfigurationPolicy") { return $false }
if($PolicyObject.templateReference.templateFamily -and $PolicyObject.templateReference.templateFamily -eq 'enrollmentConfiguration') {
return $true
}
return $false
}
}
#>
#endregion