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:
@@ -1,11 +1,57 @@
|
||||
$script:coreModulePath = Join-Path (Split-Path -Parent $PSScriptRoot) "Core.psm1"
|
||||
if (Test-Path $script:coreModulePath)
|
||||
{
|
||||
Import-Module $script:coreModulePath -Force
|
||||
}
|
||||
|
||||
function Get-DefaultIntunePolicyObjectTypes
|
||||
{
|
||||
@(
|
||||
"ScopeTags",
|
||||
"AssignmentFilters",
|
||||
"ReusableSettings",
|
||||
"RoleDefinitions",
|
||||
"Notifications",
|
||||
"DeviceHealthScripts",
|
||||
"ComplianceScripts",
|
||||
"PowerShellScripts",
|
||||
"MacScripts",
|
||||
"MacCustomAttributes",
|
||||
"ADMXFiles",
|
||||
"IntuneBranding",
|
||||
"AzureBranding",
|
||||
"TermsAndConditions",
|
||||
"TermsOfUse",
|
||||
"EnrollmentStatusPage",
|
||||
"EnrollmentRestrictions",
|
||||
"AppleEnrollmentTypes",
|
||||
"AutoPilot",
|
||||
"AndroidOEMConfig",
|
||||
"DeviceCategories",
|
||||
"AuthenticationStrengths",
|
||||
"AuthenticationContext",
|
||||
"NamedLocations",
|
||||
"ConditionalAccess",
|
||||
"CoManagementSettings",
|
||||
"Applications",
|
||||
"AppProtection",
|
||||
"AppConfigurationManagedApp",
|
||||
"AppConfigurationManagedDevice",
|
||||
"UpdatePolicies",
|
||||
"FeatureUpdates",
|
||||
"QualityUpdates",
|
||||
"DriverUpdateProfiles",
|
||||
"HardwareConfigurations",
|
||||
"InventoryPolicies",
|
||||
"W365ProvisioningPolicies",
|
||||
"W365UserSettings",
|
||||
"AdministrativeTemplates",
|
||||
"DeviceConfiguration",
|
||||
"SettingsCatalog",
|
||||
"AdministrativeTemplates",
|
||||
"CompliancePolicies",
|
||||
"CompliancePoliciesV2",
|
||||
"EndpointSecurity",
|
||||
"DeviceManagementIntents",
|
||||
"PolicySets"
|
||||
)
|
||||
}
|
||||
@@ -29,7 +75,8 @@ function Resolve-HeadlessSettingsPath
|
||||
return $SettingsFile
|
||||
}
|
||||
|
||||
Join-Path ([IO.Path]::GetTempPath()) "IntuneManagement.Settings.json"
|
||||
# Default to the persistent data folder (same location used by Initialize-IntuneAuth)
|
||||
Join-Path (Get-CloudApiDataFolder) "Settings.json"
|
||||
}
|
||||
|
||||
function New-TemporaryBatchFile
|
||||
@@ -48,7 +95,7 @@ function Test-AuthParameters
|
||||
[string]$Certificate
|
||||
)
|
||||
|
||||
if($AuthMode -eq "Browser")
|
||||
if($AuthMode -eq "Browser" -or $AuthMode -eq "DeviceCode")
|
||||
{
|
||||
return
|
||||
}
|
||||
@@ -77,7 +124,7 @@ function Invoke-IntuneHeadlessBatch
|
||||
|
||||
[string]$Certificate,
|
||||
|
||||
[ValidateSet("AppOnly","Browser")]
|
||||
[ValidateSet("AppOnly","Browser","DeviceCode")]
|
||||
[string]$AuthMode = "AppOnly",
|
||||
|
||||
[string]$RedirectUri,
|
||||
@@ -90,11 +137,50 @@ function Invoke-IntuneHeadlessBatch
|
||||
[string]$BatchFile
|
||||
)
|
||||
|
||||
if($AuthMode -eq "Browser" -and -not $AppId)
|
||||
if(($AuthMode -eq "Browser" -or $AuthMode -eq "DeviceCode") -and -not $AppId)
|
||||
{
|
||||
$AppId = Get-DefaultBrowserAppId
|
||||
}
|
||||
|
||||
# Pre-load settings to fill missing AppId/Secret before auth validation
|
||||
$settingsPath = Resolve-HeadlessSettingsPath $SettingsFile
|
||||
if($AuthMode -eq "AppOnly" -and (Test-Path $settingsPath) -and (-not $AppId -or -not $Secret -and -not $Certificate))
|
||||
{
|
||||
try
|
||||
{
|
||||
$raw = Get-Content -Path $settingsPath -Raw -ErrorAction Stop
|
||||
$settingsObj = ConvertFrom-Json $raw -AsHashtable -ErrorAction Stop
|
||||
if($settingsObj -and $settingsObj.ContainsKey($TenantId))
|
||||
{
|
||||
$tenantNode = $settingsObj[$TenantId]
|
||||
if(-not $AppId -and $tenantNode.ContainsKey("GraphAzureAppId"))
|
||||
{
|
||||
$AppId = $tenantNode["GraphAzureAppId"]
|
||||
}
|
||||
if(-not $Secret -and $tenantNode.ContainsKey("GraphAzureAppSecret"))
|
||||
{
|
||||
$Secret = $tenantNode["GraphAzureAppSecret"]
|
||||
}
|
||||
if(-not $Certificate -and $tenantNode.ContainsKey("GraphAzureAppCert"))
|
||||
{
|
||||
$Certificate = $tenantNode["GraphAzureAppCert"]
|
||||
}
|
||||
}
|
||||
|
||||
# macOS Keychain fallback for secret
|
||||
if(-not $Secret -and $IsMacOS -and $AppId)
|
||||
{
|
||||
try
|
||||
{
|
||||
$keychainSecret = security find-generic-password -a "IntuneManagement" -s "IntuneMgmt-$AppId" -w 2>$null
|
||||
if($keychainSecret) { $Secret = $keychainSecret }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
Test-AuthParameters -AuthMode $AuthMode -AppId $AppId -Secret $Secret -Certificate $Certificate
|
||||
|
||||
$projectRoot = Get-IntuneManagementProjectRoot
|
||||
@@ -105,8 +191,6 @@ function Invoke-IntuneHeadlessBatch
|
||||
throw "Could not find IntuneManagement.Runtime.psd1 in $projectRoot"
|
||||
}
|
||||
|
||||
$settingsPath = Resolve-HeadlessSettingsPath $SettingsFile
|
||||
|
||||
$deleteBatchFile = $false
|
||||
if(-not $BatchFile)
|
||||
{
|
||||
@@ -167,7 +251,7 @@ function Export-IntunePolicies
|
||||
|
||||
[string]$Certificate,
|
||||
|
||||
[ValidateSet("AppOnly","Browser")]
|
||||
[ValidateSet("AppOnly","Browser","DeviceCode")]
|
||||
[string]$AuthMode = "AppOnly",
|
||||
|
||||
[string]$RedirectUri,
|
||||
@@ -181,6 +265,10 @@ function Export-IntunePolicies
|
||||
|
||||
[string]$NameFilter = "",
|
||||
|
||||
[string]$NameSearchPattern = "",
|
||||
|
||||
[string]$NameReplacePattern = "",
|
||||
|
||||
[string[]]$ObjectTypes = (Get-DefaultIntunePolicyObjectTypes),
|
||||
|
||||
[switch]$IncludeAssignments,
|
||||
@@ -192,6 +280,8 @@ function Export-IntunePolicies
|
||||
BulkExport = @(
|
||||
[PSCustomObject]@{ Name = "txtExportPath"; Value = $ExportPath },
|
||||
[PSCustomObject]@{ Name = "txtExportNameFilter"; Value = $NameFilter },
|
||||
[PSCustomObject]@{ Name = "txtExportNameSearchPattern"; Value = $NameSearchPattern },
|
||||
[PSCustomObject]@{ Name = "txtExportNameReplacePattern"; Value = $NameReplacePattern },
|
||||
[PSCustomObject]@{ Name = "chkAddObjectType"; Value = $true },
|
||||
[PSCustomObject]@{ Name = "chkExportAssignments"; Value = $IncludeAssignments.IsPresent },
|
||||
[PSCustomObject]@{ Name = "chkAddCompanyName"; Value = $AddCompanyName.IsPresent },
|
||||
@@ -224,7 +314,7 @@ function Import-IntunePolicies
|
||||
|
||||
[string]$Certificate,
|
||||
|
||||
[ValidateSet("AppOnly","Browser")]
|
||||
[ValidateSet("AppOnly","Browser","DeviceCode")]
|
||||
[string]$AuthMode = "AppOnly",
|
||||
|
||||
[string]$RedirectUri,
|
||||
@@ -238,6 +328,10 @@ function Import-IntunePolicies
|
||||
|
||||
[string]$NameFilter = "",
|
||||
|
||||
[string]$NameSearchPattern = "",
|
||||
|
||||
[string]$NameReplacePattern = "",
|
||||
|
||||
[ValidateSet("alwaysImport","skipIfExist","replace","replace_with_assignments","update")]
|
||||
[string]$ImportType = "alwaysImport",
|
||||
|
||||
@@ -254,6 +348,8 @@ function Import-IntunePolicies
|
||||
BulkImport = @(
|
||||
[PSCustomObject]@{ Name = "txtImportPath"; Value = $ImportPath },
|
||||
[PSCustomObject]@{ Name = "txtImportNameFilter"; Value = $NameFilter },
|
||||
[PSCustomObject]@{ Name = "txtImportNameSearchPattern"; Value = $NameSearchPattern },
|
||||
[PSCustomObject]@{ Name = "txtImportNameReplacePattern"; Value = $NameReplacePattern },
|
||||
[PSCustomObject]@{ Name = "chkAddObjectType"; Value = $true },
|
||||
[PSCustomObject]@{ Name = "chkImportScopes"; Value = $IncludeScopeTags.IsPresent },
|
||||
[PSCustomObject]@{ Name = "chkImportAssignments"; Value = $IncludeAssignments.IsPresent },
|
||||
@@ -292,7 +388,7 @@ function Invoke-IntunePolicyAction
|
||||
|
||||
[string]$Certificate,
|
||||
|
||||
[ValidateSet("AppOnly","Browser")]
|
||||
[ValidateSet("AppOnly","Browser","DeviceCode")]
|
||||
[string]$AuthMode = "AppOnly",
|
||||
|
||||
[string]$RedirectUri,
|
||||
@@ -303,6 +399,10 @@ function Invoke-IntunePolicyAction
|
||||
|
||||
[string]$NameFilter = "",
|
||||
|
||||
[string]$NameSearchPattern = "",
|
||||
|
||||
[string]$NameReplacePattern = "",
|
||||
|
||||
[string[]]$ObjectTypes = (Get-DefaultIntunePolicyObjectTypes),
|
||||
|
||||
[string]$ExportPath,
|
||||
@@ -337,6 +437,8 @@ function Invoke-IntunePolicyAction
|
||||
-SettingsFile $SettingsFile `
|
||||
-BatchFile $BatchFile `
|
||||
-NameFilter $NameFilter `
|
||||
-NameSearchPattern $NameSearchPattern `
|
||||
-NameReplacePattern $NameReplacePattern `
|
||||
-ObjectTypes $ObjectTypes `
|
||||
-IncludeAssignments:$IncludeAssignments `
|
||||
-AddCompanyName:$AddCompanyName
|
||||
@@ -355,6 +457,8 @@ function Invoke-IntunePolicyAction
|
||||
-SettingsFile $SettingsFile `
|
||||
-BatchFile $BatchFile `
|
||||
-NameFilter $NameFilter `
|
||||
-NameSearchPattern $NameSearchPattern `
|
||||
-NameReplacePattern $NameReplacePattern `
|
||||
-ImportType $ImportType `
|
||||
-ObjectTypes $ObjectTypes `
|
||||
-IncludeAssignments:$IncludeAssignments `
|
||||
|
||||
Reference in New Issue
Block a user