Files
IntuneManagement/Classes/IntuneComplianceClasses.ps1

378 lines
13 KiB
PowerShell

#ImportOrder 220
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("TypeNotFound","", Justification = "")]
class ComplianceGroup : IntunePolicyGroupBase
{
ComplianceGroup() : Base()
{
$this.Init()
}
Init()
{
$this._ID = "Compliance"
$this._Name = "Compliance"
$this._Icon = "CompliancePolicies"
}
}
#########################################################################################
#
# Device Compliance
#
#########################################################################################
# region Device Compliance
class DeviceComplianceType : IntunePolicyTypeBase
{
DeviceComplianceType() : Base()
{
$this.Init()
}
Init()
{
$this._PolicyGroup = (Get-SingletonObject "ComplianceGroup")
$this._PolicyName = "Compliance Policy"
$this._ID = "CompliancePolicies"
$this._API = "deviceManagement/deviceCompliancePolicies"
# This endpoint answers HTTP 400 to startswith() on displayName
# (verified 2026-08-27; 'displayName eq' works, prefix search does not),
# so name searches filter client-side instead.
$this._SupportsNameFilter = $false
$this._Permissions = @("DeviceManagementConfiguration.ReadWrite.All")
$this._Expand = "scheduledActionsForRule(`$expand=scheduledActionConfigurations)"
# "Locations" (v3's deprecated Intune managementConditions type) is not a
# PolicyType here, so listing it resolved to nothing on import.
$this._Dependencies = @("Notifications","ComplianceScripts")
$this._ObjectClass = "DeviceComplianceObject"
if($null -ne $this._PolicyGroup) {
$this._PolicyGroup.AddPolicyType($this)
}
}
PostExportCommand([PSCustomObject]$PolicyObject, [String]$PathToFile)
{
foreach($scheduledActionsForRule in $PolicyObject.JsonObject.scheduledActionsForRule)
{
foreach($scheduledActionConfiguration in $scheduledActionsForRule.scheduledActionConfigurations)
{
foreach($notificationMessageCCGroup in $scheduledActionConfiguration.notificationMessageCCList)
{
Add-GraphMigrationObject $notificationMessageCCGroup "groups" "Group" ([IO.Path]::GetDirectoryName($PathToFile)) $PolicyObject._TokenId
}
}
}
}
[Hashtable]PreUpdateCommand([PSCustomObject]$PolicyObject, [PSCustomObject]$SourceObject)
{
$api = "deviceManagement/deviceCompliancePolicies/$($PolicyObject.Id)/scheduleActionsForRules"
$tmpObj = [PSCustomObject]@{
deviceComplianceScheduledActionForRules = $PolicyObject.JsonObject.scheduledActionsForRule
}
$json = ConvertTo-Json $tmpObj -Depth 20
Invoke-MSGraphAPI -Url $api -Content $json -HttpMethod "POST" -TokenId $PolicyObject._TokenId | Out-Null
Remove-Property $PolicyObject.JsonObject "scheduledActionsForRule"
return (@{})
}
}
Class DeviceComplianceObject : IntunePolicyBase
{
DeviceComplianceObject([PSCustomObject]$JsonObj) : Base($JsonObj) { $this.Init() }
DeviceComplianceObject() : Base()
{
$this.Init()
}
Hidden Init()
{
$this._PolicyType = (Get-SingletonObject "DeviceComplianceType")
}
}
#########################################################################################
#
# Device Compliance V2
#
#########################################################################################
Class DeviceComplianceV2Type : IntunePolicyTypeBase
{
DeviceComplianceV2Type() : Base()
{
$this.Init()
}
Init()
{
$this._PolicyGroup = (Get-SingletonObject "ComplianceGroup")
# Its own name so a mixed Compliance list tells V1 from V2 without a
# separate "Policy base" column.
$this._PolicyName = "Compliance Policy (Settings Catalog)"
$this._PolicyBaseName = "Compliance Policy V2"
$this._APITitle = "Compliance Policy (Linux)"
$this._ID = "CompliancePoliciesV2"
$this._API = "deviceManagement/compliancePolicies"
$this._PropertiesToRemove = @('settingCount')
$this._Permissions = @("DeviceManagementConfiguration.ReadWrite.All")
$this._NameProperty = "Name"
$this._Expand = "settings"
$this._ObjectClass = "DeviceComplianceV2Object"
$this._Icon = "CompliancePolicies"
if($null -ne $this._PolicyGroup) {
$this._PolicyGroup.AddPolicyType($this)
}
}
[Hashtable]PreUpdateCommand([PSCustomObject]$PolicyObject, [PSCustomObject]$SourceObject)
{
# V2 compliance runs on the settings-catalog engine: updates must PUT
# the full body (including settings); PATCH with settings is rejected.
return @{ "Method" = "PUT" }
}
}
Class DeviceComplianceV2Object : IntunePolicyBase
{
DeviceComplianceV2Object([PSCustomObject]$JsonObj) : Base($JsonObj) { $this.Init() }
DeviceComplianceV2Object() : Base()
{
$this.Init()
}
Hidden Init()
{
$this._PolicyType = (Get-SingletonObject "DeviceComplianceV2Type")
}
}
#########################################################################################
#
# Compliance Scripts
#
#########################################################################################
Class ComplianceScriptsType : IntunePolicyTypeBase
{
ComplianceScriptsType() : Base()
{
([ComplianceScriptsType]$this).Init()
}
Init()
{
$this._PolicyGroup = (Get-SingletonObject "ComplianceGroup")
$this._APITitle = "Compliance Scripts"
$this._PolicyName = "Compliance Script"
$this._ID = "ComplianceScripts"
$this._API = "deviceManagement/deviceComplianceScripts"
$this._Permissions = @("DeviceManagementConfiguration.ReadWrite.All")
$this._ObjectClass = "ComplianceScriptObject"
$this._Icon = "Scripts"
# Graph rejects PATCHing the read-only version back ("Invalid property
# name: Version").
$this._PropertiesToRemoveForUpdate = @('version')
# Custom compliance scripts are REFERENCED by compliance policies, not
# assigned to devices - the portal has no Assignments blade and Graph's
# /assign action rejects the request (400 "Action parameters do not
# contain parameter 'deviceHealthScriptAssignments'").
$this._SupportsAssignments = $false
if($null -ne $this._PolicyGroup) {
$this._PolicyGroup.AddPolicyType($this)
}
}
}
Class ComplianceScriptObject : IntunePolicyBase
{
ComplianceScriptObject([PSCustomObject]$JsonObj) : Base($JsonObj) { $this.Init() }
ComplianceScriptObject() : Base()
{
$this.Init()
}
Hidden Init()
{
$this._PlatformName = Get-LanguageString "Platform.windows10AndLater"
$this._PolicyType = (Get-SingletonObject "ComplianceScriptsType")
}
}
#########################################################################################
#
# Compliance Scripts - Linux
#
#########################################################################################
Class ComplianceScriptsLinuxType : ReusableSettingsTypeBase
{
ComplianceScriptsLinuxType() : Base()
{
$this.Init()
}
Init()
{
$this._PolicyGroup = (Get-SingletonObject "ComplianceGroup")
$this._APITitle = "Compliance Scripts (Linux)"
$this._PolicyName = "Compliance Script"
$this._ID = "ComplianceScriptsScriptsLinux"
$this._QueryList = "?`$filter=settingDefinitionId eq 'linux_customcompliance_discoveryscript_reusablesetting'"
# Reusable settings carry no roleScopeTagIds in the Graph schema.
$this._ScopeTagProperty = ""
$this._ObjectClass = "ComplianceScriptLinuxObject"
$this._Icon = "Scripts"
$this._Folder = "ReusableSettings"
$this._PolicyTypeOrder = 140
$this._ExpandAssignmentsList = $false
$this._SupportsAssignments = $false
if($null -ne $this._PolicyGroup) {
$this._PolicyGroup.AddPolicyType($this)
}
}
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
{
if($PolicyObject.'@odata.type' -ne "#microsoft.graph.deviceManagementReusablePolicySetting") { return $false }
if($PolicyObject.settingDefinitionId -eq 'linux_customcompliance_discoveryscript_reusablesetting') {
return $true
}
return $false
}
}
Class ComplianceScriptLinuxObject : ReusableSettingsObjectBase
{
ComplianceScriptLinuxObject([PSCustomObject]$JsonObj) : Base($JsonObj) { $this.Init() }
ComplianceScriptLinuxObject() : Base()
{
$this.Init()
}
Hidden Init()
{
$this._PolicyType = (Get-SingletonObject "ComplianceScriptsLinuxType")
$this._PlatformName = Get-LanguageString "Platform.linux" -IgnoreMissing
}
}
#########################################################################################
#
# Compliance Notifications
#
#########################################################################################
Class NotificationsType : IntunePolicyTypeBase
{
NotificationsType() : Base()
{
$this.Init()
}
Init()
{
$this._PolicyGroup = (Get-SingletonObject "ComplianceGroup")
$this._PolicyName = "Notifications"
$this._ID = "Notifications"
$this._HasPlatform = $false
$this._API = "deviceManagement/notificationMessageTemplates"
#$this._QueryList = "?`$filter=displayName ne 'EnrollmentNotificationInternalMEO'"
$this._Permissions = @("DeviceManagementServiceConfig.ReadWrite.All")
$this._ObjectClass = "NotificationObject"
$this._ImportOrder = 40
$this._Expand = "localizedNotificationMessages"
$this._ExpandAssignmentsList = $false
# notificationMessageTemplate has no `assignments` navigation property at
# all (its only nav is localizedNotificationMessages), so both the nav GET
# and ?$expand=assignments return 400. Notification templates are targeted
# from compliance policies, not assigned - don't ask for assignments.
$this._SupportsAssignments = $false
# notificationMessageTemplate has no description property in Graph.
$this._HasDescription = $false
# localizedNotificationMessages is a navigation property - PATCHing it
# inline is rejected; messages are managed on their own sub-endpoint.
$this._PropertiesToRemoveForUpdate = @('localizedNotificationMessages','defaultLocale')
if($null -ne $this._PolicyGroup) {
$this._PolicyGroup.AddPolicyType($this)
}
}
[Hashtable]PreImportCommand([PSCustomObject]$PolicyObject)
{
Remove-Property $PolicyObject.JsonObject "defaultLocale"
Remove-Property $PolicyObject.JsonObject "localizedNotificationMessages"
Remove-Property $PolicyObject.JsonObject "localizedNotificationMessages@odata.context"
return $null
}
PostImportCommand([PSCustomObject]$PolicyObject, [PSCustomObject]$SourceObject)
{
$this.UpdateNotificationMessages($PolicyObject, $SourceObject.JsonObject.localizedNotificationMessages)
}
Hidden UpdateNotificationMessages($PolicyObject, $localizedNotificationMessages)
{
if(-not $localizedNotificationMessages) {
return
}
$updated = $false
foreach($localizedNotificationMessage in $localizedNotificationMessages)
{
Remove-GraphPropertiesForImport $this $localizedNotificationMessage
$response = Invoke-MSGraphAPI -Url "$($this.API)/$($PolicyObject.Id)/localizedNotificationMessages" -Body ($localizedNotificationMessage | ConvertTo-Json -Depth 20) -Method "POST" -FullResponseObject
if($response.Success) {
Write-log "Notification message '$($localizedNotificationMessage.subject)' ($($localizedNotificationMessage.locale)) added successfully"
$updated = $true
}
else {
Write-log "Failed to add notification message: '$($localizedNotificationMessage.subject)' ($($localizedNotificationMessage.locale))" 3
}
}
if($updated) {
[void]$PolicyObject.Get()
}
}
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
{
if($PolicyObject.'displayName' -eq "EnrollmentNotificationInternalMEO") { return $false } # Skip built in
return (([IntunePolicyTypeBase]$this).CheckPolicy($PolicyObject))
}
}
Class NotificationObject : IntunePolicyBase
{
NotificationObject([PSCustomObject]$JsonObj) : Base($JsonObj) { $this.Init() }
NotificationObject() : Base()
{
$this.Init()
}
Hidden Init()
{
$this._PolicyType = (Get-SingletonObject "NotificationsType")
}
}