Public/Import-IntunePolicyFromJSON.ps1
|
<#
.SYNOPSIS Imports Intune Policy directly from exported JSON file. .DESCRIPTION Imports pre-exported Intune policy JSON files (Settings Catalog or Compliance policies) directly to Intune. .EXAMPLE Import-IntunePolicyFromJSON -PolicyType "HardeningPolicies" -PolicyName "Microsoft Defender" Import-IntunePolicyFromJSON -PolicyType "Compliance" -PolicyName "Harden Windows Security Compliance" #> function Import-IntunePolicyFromJSON { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateSet("HardeningPolicies", "Compliance")] [string]$PolicyType, [Parameter(Mandatory = $true)] [string]$PolicyName, [switch]$DryRun ) $ErrorActionPreference = "Stop" $workspacePath = Get-WorkspacePath if (-not $workspacePath) { Write-Error "Workspace not configured. Run Initialize-NLBaseline first." return } $config = Get-Config -WorkspacePath $workspacePath if (-not $config -or [string]::IsNullOrEmpty($config.AppRegistration.ClientId) -or [string]::IsNullOrEmpty($config.AppRegistration.ClientSecret) -or [string]::IsNullOrEmpty($config.AppRegistration.TenantId)) { Write-Error "App Registration not configured in config.json." return } Write-Host "`nImporting Intune Policy from JSON: $PolicyName`n" -ForegroundColor Cyan $modulePath = $PSScriptRoot -replace 'Public$', '' $jsonPath = Join-Path -Path $modulePath -ChildPath "Resources\IntuneFiles\$PolicyType\$PolicyName.json" if (-not (Test-Path $jsonPath)) { Write-Error "Policy JSON not found: $jsonPath" Write-Host "`nAvailable policies:" -ForegroundColor Yellow $available = Get-ChildItem -Path (Split-Path $jsonPath -Parent) -Filter "*.json" | Select-Object -ExpandProperty BaseName foreach ($p in $available) { Write-Host " - $p" -ForegroundColor White } return } $jsonContent = Get-Content -Path $jsonPath -Raw | ConvertFrom-Json if ($DryRun) { Write-Host "[DryRun] Would import policy: $PolicyName" -ForegroundColor Cyan Write-Host "Policy type: $PolicyType" -ForegroundColor Gray Write-Host "JSON file: $jsonPath" -ForegroundColor Gray if ($jsonContent.displayName) { Write-Host "Display name: $($jsonContent.displayName)" -ForegroundColor Gray } if ($jsonContent.name) { Write-Host "Name: $($jsonContent.name)" -ForegroundColor Gray } return } if (-not $DryRun) { $connected = Connect-Intune -Config $config if (-not $connected) { Write-Error "Failed to connect to Microsoft Graph." return } } try { # Remove metadata fields that shouldn't be in creation request $body = $jsonContent | ConvertTo-Json -Depth 20 | ConvertFrom-Json $body.PSObject.Properties.Remove('@odata.context') $body.PSObject.Properties.Remove('id') $body.PSObject.Properties.Remove('createdDateTime') $body.PSObject.Properties.Remove('lastModifiedDateTime') $body.PSObject.Properties.Remove('version') # Update display name to include NLBaseline prefix if ($body.displayName) { if (-not $body.displayName.StartsWith("NLBaseline - ")) { $body.displayName = "NLBaseline - $($body.displayName)" } } elseif ($body.name) { $body.displayName = "NLBaseline - $($body.name)" } if ($PolicyType -eq "Compliance") { # Compliance policy $uri = "https://graph.microsoft.com/v1.0/deviceManagement/deviceCompliancePolicies" } else { # Settings Catalog policy (Hardening Policies) $uri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies" } $res = Invoke-IntuneGraphRequest -Method POST -Uri $uri -Body ($body | ConvertTo-Json -Depth 20) Write-Host "Created policy: $($res.displayName -or $res.name) (id: $($res.id))" -ForegroundColor Green } catch { Write-Error "Failed to import policy: $_" if ($_.Exception.Response) { $reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream()) $responseBody = $reader.ReadToEnd() Write-Host "Response: $responseBody" -ForegroundColor Red } } } |