Public/Copy-NLBaselineCAPolicies.ps1
|
function Copy-NLBaselineCAPolicies { <# .SYNOPSIS Copy Conditional Access policies for pilot testing .DESCRIPTION Creates copies of existing Conditional Access policies with a new prefix for pilot testing. Useful for testing policy changes without affecting production policies. .EXAMPLE Copy-NLBaselineCAPolicies -SourcePrefix "CA200" -DestinationPrefix "PILOT-CA200" #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$SourcePrefix, [Parameter(Mandatory = $true)] [string]$DestinationPrefix, [Parameter(Mandatory = $false)] [ValidateSet("enabled", "enabledForReportingButNotEnforced", "disabled")] [string]$NewState = "enabledForReportingButNotEnforced" ) try { # Check connection $context = Get-MgContext -ErrorAction SilentlyContinue if (-not $context -or -not $context.TenantId) { Write-Host "Not connected to Microsoft 365. Connecting..." -ForegroundColor Yellow Write-Host "" $connection = Connect-NLBaselineCA if (-not $connection) { Write-Error "Cannot connect to Microsoft 365" return } $context = Get-MgContext } Write-Host "========================================" -ForegroundColor Cyan Write-Host " COPY POLICIES FOR PILOT" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "" Write-Host "Source prefix: $SourcePrefix" -ForegroundColor Yellow Write-Host "Destination prefix: $DestinationPrefix" -ForegroundColor Yellow Write-Host "New state: $NewState" -ForegroundColor Yellow Write-Host "" # Get policies matching source prefix Write-Host "Retrieving policies with prefix '$SourcePrefix'..." -ForegroundColor Gray $policies = Get-AllConditionalAccessPolicies $sourcePolicies = $policies | Where-Object { $_.DisplayName -like "$SourcePrefix*" } if ($sourcePolicies.Count -eq 0) { Write-Error "No policies found with prefix '$SourcePrefix'" return } Write-Host "Found $($sourcePolicies.Count) policies to copy" -ForegroundColor Green Write-Host "" $copiedCount = 0 $errors = @() foreach ($policy in $sourcePolicies) { try { Write-Host "Copying: $($policy.displayName)" -ForegroundColor Yellow # Create new policy object $newPolicy = @{} # Copy all properties except read-only ones $policy.PSObject.Properties | ForEach-Object { $propName = $_.Name if ($propName -notmatch '^@odata\.' -and $propName -ne 'id' -and $propName -ne 'createdDateTime' -and $propName -ne 'modifiedDateTime' -and $propName -ne 'deletedDateTime' -and $propName -ne 'templateId') { $newPolicy[$propName] = $_.Value } } # Update display name with new prefix $newPolicy.displayName = $policy.displayName -replace "^$([regex]::Escape($SourcePrefix))", $DestinationPrefix # Set new state $newPolicy.state = $NewState # Create policy using REST API $body = $newPolicy | ConvertTo-Json -Depth 20 $invokeCmd = Get-Command Invoke-MgGraphRequest -ErrorAction SilentlyContinue if ($invokeCmd) { $newPolicyResult = Invoke-MgGraphRequest -Method POST ` -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" ` -Body $body ` -ContentType "application/json" ` -ErrorAction Stop Write-Host " Created: $($newPolicy.displayName)" -ForegroundColor Green $copiedCount++ } else { throw "Invoke-MgGraphRequest not available" } } catch { $errors += "Error copying $($policy.displayName): $_" Write-Host " Error: $_" -ForegroundColor Red } } Write-Host "" Write-Host "========================================" -ForegroundColor Green Write-Host " SUMMARY" -ForegroundColor Green Write-Host "========================================" -ForegroundColor Green Write-Host "Copied: $copiedCount policies" -ForegroundColor White if ($errors.Count -gt 0) { Write-Host "Errors: $($errors.Count)" -ForegroundColor Red foreach ($error in $errors) { Write-Host " - $error" -ForegroundColor Yellow } } Write-Host "" } catch { Write-Error "Error copying policies: $_" } } |