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
        }
    }
}