Public/Import-CSPPolicyToIntune.ps1

<#
.SYNOPSIS
    Imports Configuration Service Provider (CSP) policy to Intune.
.DESCRIPTION
    Creates Intune policy using Configuration Service Provider OMA-URI settings.
    CSP policies allow deep configuration of Windows settings via MDM.
.EXAMPLE
    Import-CSPPolicyToIntune -OMAUri "./Device/Vendor/MSFT/Policy/Config/DeviceGuard/EnableVirtualizationBasedSecurity" -Value "1" -SettingType Integer
#>

function Import-CSPPolicyToIntune {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$OMAUri,
        
        [Parameter(Mandatory = $true)]
        [string]$Value,
        
        [Parameter(Mandatory = $false)]
        [ValidateSet("String", "Integer", "Boolean", "Base64")]
        [string]$SettingType = "String",
        
        [Parameter(Mandatory = $false)]
        [string]$DisplayName,
        
        [Parameter(Mandatory = $false)]
        [string]$Description,
        
        [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
    }

    if (-not $DisplayName) {
        $DisplayName = "CSP Policy - $($OMAUri.Split('/')[-1])"
    }

    if (-not $Description) {
        $Description = "Configuration Service Provider policy via OMA-URI"
    }

    Write-Host "`nImporting CSP Policy to Intune`n" -ForegroundColor Cyan
    Write-Host "OMA-URI: $OMAUri" -ForegroundColor White
    Write-Host "Value: $Value" -ForegroundColor White
    Write-Host "Type: $SettingType" -ForegroundColor White

    if ($DryRun) {
        Write-Host "[DryRun] Would create CSP Policy in Intune" -ForegroundColor Cyan
        return
    }

    $connected = Connect-Intune -Config $config
    if (-not $connected) {
        Write-Error "Failed to connect to Microsoft Graph."
        return
    }

    try {
        # Determine OData type based on setting type
        $odataType = switch ($SettingType) {
            "Integer" { "#microsoft.graph.omaSettingInteger" }
            "Boolean" { "#microsoft.graph.omaSettingBoolean" }
            "Base64" { "#microsoft.graph.omaSettingBase64" }
            default { "#microsoft.graph.omaSettingString" }
        }

        # Convert value based on type
        $convertedValue = switch ($SettingType) {
            "Integer" { [int]$Value }
            "Boolean" { [bool]::Parse($Value) }
            default { $Value }
        }

        $omaSetting = @{
            "@odata.type" = $odataType
            displayName = $DisplayName
            description = $Description
            omaUri = $OMAUri
        }

        if ($SettingType -eq "Base64") {
            $omaSetting["value"] = $Value
            $omaSetting["fileName"] = "policy.bin"
        }
        else {
            $omaSetting["value"] = $convertedValue
        }

        $policyDisplayName = "NLBaseline - $DisplayName"
        
        # Check if policy with same displayName already exists and remove it
        $removed = Remove-IntunePolicyByDisplayName -DisplayName $policyDisplayName -PolicyType "Configuration"
        if ($removed) {
            Write-Host "Removed existing policy: $policyDisplayName" -ForegroundColor Yellow
        }

        $body = @{
            "@odata.type" = "#microsoft.graph.windows10CustomConfiguration"
            displayName = $policyDisplayName
            description = $Description
            omaSettings = @($omaSetting)
        }

        $res = Invoke-IntuneGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/deviceManagement/deviceConfigurations" -Body ($body | ConvertTo-Json -Depth 20)
        Write-Host "Created CSP Policy: $($res.displayName) (id: $($res.id))" -ForegroundColor Green
    }
    catch {
        Write-Error "Failed to create CSP Policy: $_"
        if ($_.Exception.Response) {
            $reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream())
            $responseBody = $reader.ReadToEnd()
            Write-Host "Response: $responseBody" -ForegroundColor Red
        }
    }
}