feat(toolkit): complete macOS Intune Toolkit v1

Core enhancements:
- Expanded default export/import scope to ~45 object types including DeviceManagementIntents
- Added -AllPages pagination support across Graph queries for large tenants
- Invoke-GraphRequest now throws on 4xx/5xx instead of silently returning null
- Added macOS Keychain fallback for secret retrieval in headless auth flow
- Added NameSearchPattern/NameReplacePattern mutation support through export/import forms

New toolkit scripts:
- Bulk-AppAssignment.ps1: bulk-assign apps to groups/All Users/All Devices
- Bulk-AssignmentManager.ps1: add/remove assignments for any policy type with correct @odata.type
- Backup-Restore-Assignments.ps1: JSON backup with cross-tenant group resolution
- Export-AssignmentsToCsv.ps1: CSV/Markdown documentation output
- Bulk-RenamePolicies.ps1: regex search/replace and prefix mutations
- Bulk-DeviceOperations.ps1: delete/retire/wipe/lock/sync with -WhatIf safeguards
- Start-IntuneManagementTui.ps1: interactive terminal UI for headless operations
- Create-IntuneManagementApp.ps1: helper for app registration setup

Updated existing scripts:
- Export-Policies.ps1 / Import-Policies.ps1: wired mutation params through
- Start-HeadlessIntune.ps1: integrated TUI and new parameter forwarding
This commit is contained in:
2026-04-14 15:11:09 +02:00
parent 0ddd21ab14
commit e13d14edcb
18 changed files with 3649 additions and 69 deletions

View File

@@ -6,6 +6,13 @@ Headless runtime helpers for macOS Intune Management.
This module provides the non-UI runtime used by the CLI entrypoints.
#>
# Microsoft.Graph.Authentication registers an alias Invoke-GraphRequest -> Invoke-MgGraphRequest.
# Remove it so our local function in MSGraph.psm1 is used instead.
if (Get-Alias Invoke-GraphRequest -ErrorAction SilentlyContinue)
{
Remove-Item Alias:\Invoke-GraphRequest -Force -ErrorAction SilentlyContinue
}
function Get-ModuleVersion
{
'4.0.0'
@@ -20,6 +27,42 @@ function Invoke-AppDoEvents
{
}
function Expand-FileName
{
param([string]$Path)
if(-not $Path) { return $Path }
$expanded = [Environment]::ExpandEnvironmentVariables($Path)
if($expanded -like "~/*" -or $expanded -eq "~")
{
$expanded = $expanded -replace "^~", $HOME
}
return $expanded
}
function Remove-InvalidFileNameChars
{
param([string]$Name)
if([string]::IsNullOrEmpty($Name)) { return $Name }
$invalid = [IO.Path]::GetInvalidFileNameChars()
foreach($char in $invalid)
{
$Name = $Name.Replace($char, '_')
}
# Also replace path separator if present (relevant on Unix)
$Name = $Name.Replace('/', '_')
$Name
}
function Remove-Property
{
param($Object, [string]$PropertyName)
if(-not $Object -or [string]::IsNullOrEmpty($PropertyName)) { return }
if($Object.PSObject.Properties[$PropertyName])
{
$Object.PSObject.Properties.Remove($PropertyName)
}
}
function Start-CoreApp
{
param($View)
@@ -388,25 +431,44 @@ function New-HeadlessControl
[string]$Type = "TextBox"
)
[PSCustomObject]@{
$control = [PSCustomObject]@{
Name = $Name
Type = $Type
Focusable = ($Type -ne "DataGrid")
Visibility = "Visible"
IsEnabled = $true
Text = ""
IsChecked = $false
SelectedValue = $null
SelectedIndex = -1
SelectedItem = $null
SelectedItems = @()
ItemsSource = @()
Items = @()
Columns = @()
Content = ""
Parent = $null
DataContext = $null
}
switch($Type)
{
"TextBox" {
$control | Add-Member -NotePropertyName Text -NotePropertyValue ""
}
"CheckBox" {
$control | Add-Member -NotePropertyName IsChecked -NotePropertyValue $false
}
"ComboBox" {
$control | Add-Member -NotePropertyName SelectedValue -NotePropertyValue $null
$control | Add-Member -NotePropertyName SelectedIndex -NotePropertyValue -1
$control | Add-Member -NotePropertyName SelectedItem -NotePropertyValue $null
$control | Add-Member -NotePropertyName SelectedItems -NotePropertyValue @()
$control | Add-Member -NotePropertyName ItemsSource -NotePropertyValue @()
$control | Add-Member -NotePropertyName Items -NotePropertyValue @()
}
"Label" {
$control | Add-Member -NotePropertyName Content -NotePropertyValue ""
}
"DataGrid" {
$control | Add-Member -NotePropertyName ItemsSource -NotePropertyValue @()
$control | Add-Member -NotePropertyName Columns -NotePropertyValue @()
$control | Add-Member -NotePropertyName SelectedItems -NotePropertyValue @()
$control | Add-Member -NotePropertyName SelectedItem -NotePropertyValue $null
}
}
$control
}
function New-HeadlessForm