Public/Import-AppProtectionPolicyToIntune.ps1

<#
.SYNOPSIS
    Imports App Protection Policies (MAM) to Intune for iOS and Android.
.DESCRIPTION
    Creates secure App Protection Policies for iOS and Android with data protection and access requirements.
.EXAMPLE
    Import-AppProtectionPolicyToIntune -Platform iOS
#>

function Import-AppProtectionPolicyToIntune {
    [CmdletBinding()]
    param(
        [ValidateSet('iOS', 'Android', 'All')]
        [string]$Platform = 'All',
        [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 App Protection Policies (MAM) to Intune`n" -ForegroundColor Cyan

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

    $policies = @()

    if ($Platform -eq 'iOS' -or $Platform -eq 'All') {
        $policies += @{
            Platform = 'iOS'
            Body = @{
                "@odata.type" = "#microsoft.graph.iosManagedAppProtection"
                displayName = "NLBaseline - iOS App Protection Policy"
                description = "Secure iOS App Protection Policy for Dutch Baseline"
                periodOfflineBeforeAccessCheck = "PT720H"
                periodOnlineBeforeAccessCheck = "PT30M"
                allowedInboundDataTransferSources = "none"
                allowedOutboundDataTransferDestinations = "managedApps"
                organizationalCredentialsRequired = $true
                allowedOutboundClipboardSharingLevel = "managedAppsWithPasteIn"
                dataBackupBlocked = $true
                deviceComplianceRequired = $true
                managedBrowserToOpenLinksRequired = $true
                saveAsBlocked = $true
                periodOfflineBeforeWipeIsEnforced = "P90D"
                pinRequired = $true
                maximumPinRetries = 5
                simplePinBlocked = $true
                minimumPinLength = 6
                pinCharacterSet = "numeric"
                periodBeforePinReset = "P0D"
                allowedDataStorageLocations = @("oneDriveForBusiness")
                contactSyncBlocked = $true
                printBlocked = $true
                fingerprintBlocked = $true
                disableAppPinIfDevicePinIsSet = $false
                minimumRequiredOsVersion = "15.0"
                minimumWarningOsVersion = "15.0"
                minimumRequiredAppVersion = $null
                minimumWarningAppVersion = $null
                managedBrowser = "microsoftEdge"
                isAssigned = $false
            }
        }
    }

    if ($Platform -eq 'Android' -or $Platform -eq 'All') {
        $policies += @{
            Platform = 'Android'
            Body = @{
                "@odata.type" = "#microsoft.graph.androidManagedAppProtection"
                displayName = "NLBaseline - Android App Protection Policy"
                description = "Secure Android App Protection Policy for Dutch Baseline"
                periodOfflineBeforeAccessCheck = "PT720H"
                periodOnlineBeforeAccessCheck = "PT30M"
                allowedInboundDataTransferSources = "none"
                allowedOutboundDataTransferDestinations = "managedApps"
                organizationalCredentialsRequired = $true
                allowedOutboundClipboardSharingLevel = "managedAppsWithPasteIn"
                dataBackupBlocked = $true
                deviceComplianceRequired = $true
                managedBrowserToOpenLinksRequired = $true
                saveAsBlocked = $true
                periodOfflineBeforeWipeIsEnforced = "P90D"
                pinRequired = $true
                maximumPinRetries = 5
                simplePinBlocked = $true
                minimumPinLength = 6
                pinCharacterSet = "numeric"
                periodBeforePinReset = "P0D"
                allowedDataStorageLocations = @("oneDriveForBusiness")
                contactSyncBlocked = $true
                printBlocked = $true
                fingerprintBlocked = $true
                disableAppPinIfDevicePinIsSet = $false
                minimumRequiredOsVersion = "8.0"
                minimumWarningOsVersion = "8.0"
                minimumRequiredAppVersion = $null
                minimumWarningAppVersion = $null
                managedBrowser = "microsoftEdge"
                isAssigned = $false
            }
        }
    }

    $created = @()
    $failed = @()

    foreach ($pol in $policies) {
        if ($DryRun) {
            Write-Host "[DryRun] Would create: $($pol.Platform) App Protection Policy" -ForegroundColor Cyan
            $created += $pol.Platform
            continue
        }

        try {
            # Check if policy with same displayName already exists and remove it
            $removed = Remove-IntunePolicyByDisplayName -DisplayName $pol.Body.displayName -PolicyType "AppProtection"
            if ($removed) {
                Write-Host "Removed existing policy: $($pol.Body.displayName)" -ForegroundColor Yellow
            }
            
            $res = Invoke-IntuneGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/deviceAppManagement/managedAppPolicies" -Body ($pol.Body | ConvertTo-Json -Depth 20)
            $created += $pol.Platform
            Write-Host "Created: $($pol.Platform) App Protection Policy (id: $($res.id))" -ForegroundColor Green
        }
        catch {
            # If Graph API fails with 403 (permission error), deploy as Intune Script instead
            if ($_.Exception.Message -like "*403*" -or $_.Exception.Message -like "*Forbidden*" -or $_.Exception.Message -like "*permission*") {
                Write-Warning "Graph API permission denied for $($pol.Platform) App Protection Policy. Deploying as Intune Script..."
                try {
                    # Create PowerShell script that configures App Protection Policy settings
                    $scriptContent = @"
# NLBaseline - $($pol.Platform) App Protection Policy Configuration
# This script configures App Protection Policy settings for $($pol.Platform) devices

`$ErrorActionPreference = "Stop"

# App Protection Policy Settings
Write-Host "Configuring $($pol.Platform) App Protection Policy settings..." -ForegroundColor Cyan

# Note: App Protection Policies require Graph API permissions
# This script documents the required settings:
# - PIN Required: $($pol.Body.pinRequired)
# - Minimum PIN Length: $($pol.Body.minimumPinLength)
# - Data Backup Blocked: $($pol.Body.dataBackupBlocked)
# - Save As Blocked: $($pol.Body.saveAsBlocked)
# - Print Blocked: $($pol.Body.printBlocked)
# - Managed Browser Required: $($pol.Body.managedBrowserToOpenLinksRequired)

Write-Host "$($pol.Platform) App Protection Policy settings documented" -ForegroundColor Green
Write-Host "Note: Configure App Protection Policies manually in Intune portal:" -ForegroundColor Yellow
Write-Host " Apps > App protection policies > Create policy > $($pol.Platform)" -ForegroundColor Gray
"@

                    
                    # Deploy as Intune Device Management Script
                    $scriptBody = @{
                        "@odata.type" = "#microsoft.graph.deviceManagementScript"
                        displayName = "NLBaseline - $($pol.Platform) App Protection Policy Config"
                        description = "App Protection Policy configuration for $($pol.Platform) - Deployed as script due to Graph API permission limitations"
                        scriptContent = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($scriptContent))
                        runAsAccount = "system"
                        enforceSignatureCheck = $false
                        runAs32Bit = $false
                        fileName = "NLBaseline-AppProtection-$($pol.Platform).ps1"
                    }
                    
                    $scriptRes = Invoke-IntuneGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/deviceManagement/deviceManagementScripts" -Body ($scriptBody | ConvertTo-Json -Depth 20)
                    $created += "$($pol.Platform) (as Script)"
                    Write-Host "Deployed: $($pol.Platform) App Protection Policy as Intune Script (id: $($scriptRes.id))" -ForegroundColor Green
                }
                catch {
                    $failed += "$($pol.Platform): $_"
                    Write-Warning "Failed to deploy $($pol.Platform) App Protection Policy as script: $_"
                }
            }
            else {
                $failed += "$($pol.Platform): $_"
                Write-Warning "Failed to create $($pol.Platform) App Protection Policy: $_"
            }
        }
    }

    Write-Host "`nImport complete. Created: $($created.Count), Failed: $($failed.Count)" -ForegroundColor Cyan
}