Public/Set-NLBaselineCABreakGlassGroup.ps1

function Set-NLBaselineCABreakGlassGroup {
    <#
    .SYNOPSIS
    Manage break glass exclusion group for all Conditional Access policies
     
    .DESCRIPTION
    Adds or removes a break glass exclusion group from all Conditional Access policies.
    This ensures emergency access accounts are always excluded from policies.
     
    .EXAMPLE
    Set-NLBaselineCABreakGlassGroup -GroupName "CABreakGlassExclude" -Action Add
    #>

    
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$GroupName,
        
        [Parameter(Mandatory = $true)]
        [ValidateSet("Add", "Remove")]
        [string]$Action
    )
    
    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 " BREAK GLASS GROUP MANAGEMENT" -ForegroundColor Cyan
        Write-Host "========================================" -ForegroundColor Cyan
        Write-Host ""
        
        # Find the group
        Write-Host "Searching for group: $GroupName" -ForegroundColor Yellow
        $group = Get-MgGroup -Filter "displayName eq '$GroupName'" -ErrorAction SilentlyContinue | Select-Object -First 1
        
        if (-not $group) {
            Write-Error "Group '$GroupName' not found. Please create the group first."
            return
        }
        
        Write-Host "Found group: $($group.DisplayName) (ID: $($group.Id))" -ForegroundColor Green
        Write-Host ""
        
        # Get all policies
        Write-Host "Retrieving all Conditional Access policies..." -ForegroundColor Yellow
        $policies = Get-AllConditionalAccessPolicies
        
        Write-Host "Found $($policies.Count) policies" -ForegroundColor Green
        Write-Host ""
        
        $updatedCount = 0
        $skippedCount = 0
        $errors = @()
        
        foreach ($policy in $policies) {
            try {
                $needsUpdate = $false
                $policyUpdate = @{}
                
                # Ensure conditions structure exists
                if (-not $policy.conditions) {
                    $policyUpdate.conditions = @{
                        "@odata.type" = "#microsoft.graph.conditionalAccessConditionSet"
                        users = @{
                            "@odata.type" = "#microsoft.graph.conditionalAccessUsers"
                            includeUsers = @("All")
                            excludeUsers = @()
                            excludeGroups = @()
                        }
                    }
                    $needsUpdate = $true
                }
                else {
                    $policyUpdate.conditions = $policy.conditions
                }
                
                # Ensure users structure exists
                if (-not $policyUpdate.conditions.users) {
                    $policyUpdate.conditions.users = @{
                        "@odata.type" = "#microsoft.graph.conditionalAccessUsers"
                        includeUsers = @("All")
                        excludeUsers = @()
                        excludeGroups = @()
                    }
                    $needsUpdate = $true
                }
                
                # Ensure excludeGroups array exists
                if (-not $policyUpdate.conditions.users.excludeGroups) {
                    $policyUpdate.conditions.users.excludeGroups = @()
                    $needsUpdate = $true
                }
                
                # Check if group is already in exclude list
                $groupInList = $policyUpdate.conditions.users.excludeGroups -contains $group.Id
                
                if ($Action -eq "Add" -and -not $groupInList) {
                    # Add group to exclude list
                    if ($policyUpdate.conditions.users.excludeGroups.Count -eq 0) {
                        $policyUpdate.conditions.users.excludeGroups = @($group.Id)
                    }
                    else {
                        $policyUpdate.conditions.users.excludeGroups = $policyUpdate.conditions.users.excludeGroups + $group.Id
                    }
                    $needsUpdate = $true
                    Write-Host " Adding to: $($policy.displayName)" -ForegroundColor Gray
                }
                elseif ($Action -eq "Remove" -and $groupInList) {
                    # Remove group from exclude list
                    $policyUpdate.conditions.users.excludeGroups = $policyUpdate.conditions.users.excludeGroups | Where-Object { $_ -ne $group.Id }
                    $needsUpdate = $true
                    Write-Host " Removing from: $($policy.displayName)" -ForegroundColor Gray
                }
                else {
                    $skippedCount++
                    continue
                }
                
                if ($needsUpdate) {
                    # Update policy using REST API
                    $body = @{
                        conditions = $policyUpdate.conditions
                    } | ConvertTo-Json -Depth 10
                    
                    $invokeCmd = Get-Command Invoke-MgGraphRequest -ErrorAction SilentlyContinue
                    if ($invokeCmd) {
                        Invoke-MgGraphRequest -Method PATCH `
                            -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies/$($policy.Id)" `
                            -Body $body `
                            -ContentType "application/json" `
                            -ErrorAction Stop
                        
                        $updatedCount++
                    }
                    else {
                        throw "Invoke-MgGraphRequest not available"
                    }
                }
            }
            catch {
                $errors += "Error updating $($policy.displayName): $_"
                Write-Host " Error: $($policy.displayName) - $_" -ForegroundColor Red
            }
        }
        
        Write-Host ""
        Write-Host "========================================" -ForegroundColor Green
        Write-Host " SUMMARY" -ForegroundColor Green
        Write-Host "========================================" -ForegroundColor Green
        Write-Host "Updated: $updatedCount policies" -ForegroundColor White
        Write-Host "Skipped: $skippedCount policies (already configured)" -ForegroundColor Gray
        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 managing break glass group: $_"
    }
}