#requires -Version 7.0 <# .SYNOPSIS Converts an existing IntuneManagement export folder into a baseline YAML manifest. .DESCRIPTION Scans a toolkit export directory, infers policy types from folder names, extracts display names from JSON files, and emits a baseline YAML skeleton with empty assignment blocks ready for editing. .EXAMPLE ./Scripts/ConvertTo-IntuneBaseline.ps1 -ExportPath ./Exports/2025-01-15 -OutputPath ./Baselines/mybaseline.yaml #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$ExportPath, [Parameter(Mandatory = $true)] [string]$OutputPath, [string]$BaselineName = "ConvertedBaseline" ) $ErrorActionPreference = "Stop" #region Dependency check $yamlModule = Get-Module -ListAvailable -Name powershell-yaml | Select-Object -First 1 if(-not $yamlModule) { Write-Warning "powershell-yaml module not found. Installing..." Install-Module powershell-yaml -Scope CurrentUser -Force } Import-Module powershell-yaml -Force #endregion $exportPathResolved = Resolve-Path $ExportPath | Select-Object -ExpandProperty Path $outputPathResolved = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($OutputPath) if(-not (Test-Path $exportPathResolved)) { throw "Export path not found: $ExportPath" } # Folder-to-type whitelist (matches toolkit export folders and baseline types) $folderTypeMap = @{ "DeviceConfiguration" = "DeviceConfiguration" "SettingsCatalog" = "SettingsCatalog" "CompliancePolicies" = "CompliancePolicies" "CompliancePoliciesV2" = "CompliancePoliciesV2" "AdministrativeTemplates" = "AdministrativeTemplates" "EndpointSecurity" = "EndpointSecurity" "DeviceManagementIntents" = "DeviceManagementIntents" "AppProtection" = "AppProtection" "AppConfigurationManagedDevice" = "AppConfigurationManagedDevice" "PlatformScripts" = "PlatformScripts" "MacScripts" = "MacScripts" "DeviceHealthScripts" = "DeviceHealthScripts" "MacCustomAttributes" = "MacCustomAttributes" "EnrollmentRestrictions" = "EnrollmentRestrictions" "EnrollmentStatusPage" = "EnrollmentStatusPage" "Autopilot" = "Autopilot" "TermsAndConditions" = "TermsAndConditions" "PolicySets" = "PolicySets" "UpdatePolicies" = "UpdatePolicies" "FeatureUpdates" = "FeatureUpdates" "QualityUpdates" = "QualityUpdates" "Applications" = "Applications" } $policies = @() foreach($folder in Get-ChildItem -Path $exportPathResolved -Directory) { $folderName = $folder.Name if(-not $folderTypeMap.ContainsKey($folderName)) { Write-Verbose "Skipping unrecognized folder: $folderName" continue } $typeName = $folderTypeMap[$folderName] $nameProp = if($typeName -eq "SettingsCatalog" -or $typeName -eq "CompliancePoliciesV2") { "name" } else { "displayName" } $jsonFiles = Get-ChildItem -Path $folder.FullName -Filter "*.json" foreach($file in $jsonFiles) { # Skip *_Settings.json companion files if($file.BaseName -like "*_Settings") { continue } try { $json = Get-Content $file.FullName -Raw | ConvertFrom-Json -Depth 10 $displayName = $json.$nameProp if(-not $displayName) { $displayName = $json.displayName } if(-not $displayName) { $displayName = $file.BaseName } } catch { Write-Warning "Could not parse $($file.FullName); using filename as display name." $displayName = $file.BaseName } $relativePath = "." + $file.FullName.Substring($exportPathResolved.Length).Replace("\", "/") $policies += [ordered]@{ sourcePath = $relativePath type = $typeName assignments = @() } Write-Host "Mapped: [$typeName] $displayName -> $relativePath" } } if($policies.Count -eq 0) { throw "No convertible policies found in $exportPathResolved" } $baseline = [ordered]@{ baseline = [ordered]@{ name = $BaselineName conflictResolution = "Skip" whatIf = $false tenantMutation = [ordered]@{ search = "" replace = "" } groups = @() policies = $policies } } $yaml = ConvertTo-Yaml -Data $baseline $yaml | Set-Content -Path $outputPathResolved -Encoding UTF8 Write-Host "`nBaseline skeleton written to: $outputPathResolved" -ForegroundColor Green Write-Host "Policies found: $($policies.Count)" -ForegroundColor Green Write-Host "Next steps:" -ForegroundColor Cyan Write-Host " 1. Edit the YAML to add group names and assignments." Write-Host " 2. Run Deploy-IntuneBaseline.ps1 against a target tenant."