mirror of
https://github.com/Micke-K/IntuneManagement.git
synced 2026-09-28 10:55:38 +02:00
IntuneManagement 4.0.0-beta1
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
#ImportOrder 220
|
||||
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("TypeNotFound","", Justification = "")]
|
||||
class AppProtectionGroup : IntunePolicyGroupBase
|
||||
{
|
||||
AppProtectionGroup() : Base()
|
||||
{
|
||||
$this.Init()
|
||||
}
|
||||
|
||||
Init()
|
||||
{
|
||||
$this._ID = "AppProtection"
|
||||
$this._Name = "App protection policies"
|
||||
$this._Icon = "AppProtection"
|
||||
}
|
||||
}
|
||||
|
||||
#########################################################################################
|
||||
#
|
||||
# App Protection
|
||||
#
|
||||
#########################################################################################
|
||||
|
||||
# region App Protection
|
||||
class AppProtectionType : IntunePolicyTypeBase
|
||||
{
|
||||
AppProtectionType() : Base()
|
||||
{
|
||||
$this.Init()
|
||||
}
|
||||
|
||||
Init()
|
||||
{
|
||||
$this._PolicyGroup = (Get-SingletonObject "AppProtectionGroup")
|
||||
$this._PolicyName = "App protection policy"
|
||||
$this._ID = "AppProtection"
|
||||
$this._SubTypeColumn = "ManagementType=Management type"
|
||||
# Endpoint rejects a name $filter (verified live 2026-08-27) - searches filter client-side.
|
||||
$this._SupportsNameFilter = $false
|
||||
$this._API = "deviceAppManagement/managedAppPolicies"
|
||||
$this._Permissions = @("DeviceManagementApps.ReadWrite.All")
|
||||
$this._Dependencies = @("Applications")
|
||||
$this._ObjectClass = "AppProtectionPolicyObject"
|
||||
$this._ExpandAssignmentsList = $false
|
||||
# Assignments are fetched per platform collection - see
|
||||
# GetAssignmentsBaseURL below. _AssignmentsViaExpand stays $false:
|
||||
# once the URL targets a concrete subtype the plain navigation GET
|
||||
# works, and it returns just the assignments instead of the whole policy.
|
||||
$this._PropertiesToRemove = @('exemptAppLockerFiles')
|
||||
$this._PropertiesToRemoveForUpdate = @("protectedAppLockerFiles","version") # ToDo: !!! Add support for protectedAppLockerFiles?
|
||||
$this._VerifyObject = $true
|
||||
# CheckPolicy is a complete @odata.type matcher (the managedAppPolicies allowlist),
|
||||
# so a rejection is authoritative - do not let the folder-trust fallback rescue a
|
||||
# foreign object misplaced in this type's export folder.
|
||||
$this._StrictODataTypeCheck = $true
|
||||
$this._Icon = "AppConfiguration"
|
||||
|
||||
if($null -ne $this._PolicyGroup) {
|
||||
$this._PolicyGroup.AddPolicyType($this)
|
||||
}
|
||||
}
|
||||
|
||||
# managedAppPolicies is Collection(managedAppPolicy), and managedAppPolicy
|
||||
# declares no navigation properties - so both {API}/{id}/assignments and
|
||||
# {API}/{id}?$expand=assignments return 400 ("Could not find a property named
|
||||
# 'assignments' on type 'microsoft.graph.managedAppPolicy'"). Every concrete
|
||||
# subtype inherits `assignments`, so route through the per-platform collection
|
||||
# (_objectClass, set in the object's constructor via Get-AppConfigurationClass).
|
||||
# defaultManagedAppProtection is the exception - it has no assignments at all.
|
||||
[String]GetAssignmentsBaseURL([PSCustomObject]$PolicyObject)
|
||||
{
|
||||
if(-not $PolicyObject._objectClass) { return $this._API }
|
||||
if($PolicyObject._objectClass -eq "defaultManagedAppProtections") { return $null }
|
||||
|
||||
return "deviceAppManagement/$($PolicyObject._objectClass)"
|
||||
}
|
||||
|
||||
[Hashtable]PreImportCommand([PSCustomObject]$PolicyObject)
|
||||
{
|
||||
# apps is a navigation property set later via targetApps (PostImportCommand),
|
||||
# not an inline body property - strip it from the POST body.
|
||||
Remove-Property $PolicyObject.JsonObject "apps"
|
||||
Remove-Property $PolicyObject.JsonObject "apps@odata.context"
|
||||
|
||||
# The polymorphic managedAppPolicies collection (used for listing) rejects
|
||||
# POST, so import must target the per-platform collection. _objectClass is
|
||||
# the metadata-derived endpoint segment (e.g. iosManagedAppProtections),
|
||||
# set on the object at construction via Get-AppConfigurationClass.
|
||||
if($PolicyObject._objectClass)
|
||||
{
|
||||
return @{"API"="deviceAppManagement/$($PolicyObject._objectClass)"}
|
||||
}
|
||||
|
||||
return (@{})
|
||||
}
|
||||
|
||||
PostImportCommand([PSCustomObject]$PolicyObject, [PSCustomObject]$SourceObject)
|
||||
{
|
||||
if($SourceObject.Object.Apps) {
|
||||
# No "@odata.type" on the created object so reload new object
|
||||
#$newObject = (Invoke-MSGraphAPI "$($objectType.API)?`$filter=id eq '$($obj.Id)'").Value
|
||||
$newObject = Invoke-MSGraphAPI -Url "$($this.API)/$($PolicyObject.Id)" -TokenId $PolicyObject._TokenID
|
||||
if($newObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
$apps = [PSCustomObject]@{
|
||||
appGroupType = $PolicyObject.Object.appGroupType
|
||||
apps = @($SourceObject.Object.Apps)
|
||||
}
|
||||
$json = $apps | ConvertTo-Json -Depth 20
|
||||
|
||||
# Created object carries no @odata.type; use the source object's
|
||||
# metadata-derived endpoint segment (_objectClass).
|
||||
if($SourceObject._objectClass)
|
||||
{
|
||||
Invoke-MSGraphAPI -Url "deviceAppManagement/$($SourceObject._objectClass)/$($PolicyObject.Id)/targetApps" -Content $json -HttpMethod POST -TokenId $PolicyObject._TokenID | Out-Null
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# The policy was created; only the targetApps association failed. Keep
|
||||
# going but make the partial import visible instead of swallowing it.
|
||||
Write-LogError "Failed to assign target apps to imported App protection policy '$($PolicyObject.displayName)' ($($PolicyObject.Id)) via deviceAppManagement/$($SourceObject._objectClass)/$($PolicyObject.Id)/targetApps" $_.Exception
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Hashtable]PreImportAssignmentsCommand([PSCustomObject]$PolicyObject, [PSCustomObject]$SourceObject)
|
||||
{
|
||||
# /assign is bound to the concrete platform subtype; the polymorphic
|
||||
# managedAppPolicies collection returns 400 for the assign action.
|
||||
if($SourceObject._objectClass)
|
||||
{
|
||||
return @{"API"="deviceAppManagement/$($SourceObject._objectClass)/$($PolicyObject.Id)/assign"}
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
[Hashtable]PreUpdateCommand([PSCustomObject]$PolicyObject, [PSCustomObject]$ExistingObject)
|
||||
{
|
||||
# managedAppPolicies rejects PATCH, and apps is a navigation property set
|
||||
# via targetApps rather than inline. Re-post apps to the per-platform
|
||||
# endpoint, strip them from the PATCH body, then PATCH that endpoint.
|
||||
#
|
||||
# Routing note: an imported object's POST response carries no
|
||||
# @odata.type, so ITS _objectClass can be null - the update object came
|
||||
# from a file that always has the type, so prefer that one.
|
||||
if(-not $ExistingObject._objectClass -and $PolicyObject._objectClass)
|
||||
{
|
||||
$ExistingObject._objectClass = $PolicyObject._objectClass
|
||||
}
|
||||
|
||||
if($PolicyObject.JsonObject.apps -and $ExistingObject._objectClass)
|
||||
{
|
||||
try
|
||||
{
|
||||
$apps = [PSCustomObject]@{
|
||||
appGroupType = $PolicyObject.JsonObject.appGroupType
|
||||
apps = @($PolicyObject.JsonObject.apps)
|
||||
}
|
||||
$json = $apps | ConvertTo-Json -Depth 20
|
||||
Invoke-MSGraphAPI -Url "deviceAppManagement/$($ExistingObject._objectClass)/$($ExistingObject.Id)/targetApps" -Content $json -HttpMethod POST -TokenId $ExistingObject._TokenID | Out-Null
|
||||
}
|
||||
catch {
|
||||
# The policy PATCH still proceeds; surface the failed targetApps update.
|
||||
Write-LogError "Failed to update target apps for App protection policy '$($ExistingObject.displayName)' ($($ExistingObject.Id)) via deviceAppManagement/$($ExistingObject._objectClass)/$($ExistingObject.Id)/targetApps" $_.Exception
|
||||
}
|
||||
}
|
||||
Remove-Property $PolicyObject.JsonObject "apps"
|
||||
Remove-Property $PolicyObject.JsonObject "apps@odata.context"
|
||||
# assignments is a navigation property (managed via the /assign action),
|
||||
# not inline-PATCHable - PATCHing it 400s on the platform entity type.
|
||||
Remove-Property $PolicyObject.JsonObject "assignments"
|
||||
Remove-Property $PolicyObject.JsonObject "assignments@odata.context"
|
||||
|
||||
if($ExistingObject._objectClass)
|
||||
{
|
||||
return @{"API"="deviceAppManagement/$($ExistingObject._objectClass)/$($ExistingObject.Id)"}
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
[Boolean]CheckPolicy([PSCustomObject]$PolicyObject)
|
||||
{
|
||||
# App Protection owns the polymorphic deviceAppManagement/managedAppPolicies
|
||||
# collection: the per-platform *ManagedAppProtection variants (ios / android /
|
||||
# windows / default) plus the two Windows Information Protection policy types.
|
||||
# An explicit allowlist is required: file objects carry only @odata.type (no
|
||||
# top-level @odata.id), so this runs as the file->type discriminator. A previous
|
||||
# "accept everything except targetedManagedAppConfiguration" greedily claimed
|
||||
# unrelated policy types (Compliance, CA, etc.) when resolving from an export
|
||||
# folder. targetedManagedAppConfiguration is App Config, not App Protection
|
||||
# (see AppConfigurationManagedAppType.CheckPolicy).
|
||||
$odata = [string]$PolicyObject.'@odata.type'
|
||||
if($odata -match 'ManagedAppProtection$' -or
|
||||
$odata -eq '#microsoft.graph.mdmWindowsInformationProtectionPolicy' -or
|
||||
$odata -eq '#microsoft.graph.windowsInformationProtectionPolicy')
|
||||
{
|
||||
return $true
|
||||
}
|
||||
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
Class AppProtectionPolicyObject : IntunePolicyBase
|
||||
{
|
||||
Hidden [string]$_objectClass = $null
|
||||
Hidden [string]$_managemntType = $null
|
||||
|
||||
AppProtectionPolicyObject([PSCustomObject]$JsonObj) : Base($JsonObj) { $this.Init() }
|
||||
|
||||
AppProtectionPolicyObject() : Base()
|
||||
{
|
||||
$this.Init()
|
||||
}
|
||||
|
||||
Hidden Init()
|
||||
{
|
||||
$this._PolicyType = (Get-SingletonObject "AppProtectionType")
|
||||
|
||||
if($this.Object."@odata.type" -eq "#microsoft.graph.mdmWindowsInformationProtectionPolicy") {
|
||||
$this._managemntType = "With enrollment"
|
||||
}
|
||||
elseif($this.Object."@odata.type" -eq "#microsoft.graph.windowsInformationProtectionPolicy") {
|
||||
$this._managemntType = "Without enrollment"
|
||||
}
|
||||
else {
|
||||
$this._managemntType = "All app types"
|
||||
}
|
||||
|
||||
Add-ObjectProperty $this "ManagementType" { $this._managemntType }
|
||||
|
||||
Get-AppConfigurationClass $this
|
||||
|
||||
if($this.JsonObject."@odata.type" -eq "#microsoft.graph.iosManagedAppProtection") {
|
||||
$platformName = Get-LanguageString "AppProtection.iOSPlatformLabel"
|
||||
if($platformName) {
|
||||
#$this._PlatformName = $platformName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user