Private/New-ExcludeGroup.ps1
|
function New-ExcludeGroup { <# .SYNOPSIS Create or get an Entra ID security group for policy exclusions .DESCRIPTION Creates a security group in Entra ID if it doesn't exist, or returns the existing group #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$GroupName ) try { # Check if group already exists $existingGroup = $null try { $existingGroup = Get-MgGroup -Filter "DisplayName eq '$GroupName'" -Top 1 -ErrorAction SilentlyContinue } catch { # Use REST API fallback $invokeCmd = Get-Command Invoke-MgGraphRequest -ErrorAction SilentlyContinue if ($invokeCmd) { $filter = [System.Web.HttpUtility]::UrlEncode("displayName eq '$GroupName'") $response = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/groups?`$filter=$filter&`$top=1" -ErrorAction Stop if ($response.value -and $response.value.Count -gt 0) { $existingGroup = $response.value[0] } } } if ($existingGroup) { $groupId = if ($existingGroup.Id) { $existingGroup.Id } else { $existingGroup.id } Write-Host " Group already exists: $GroupName (ID: $groupId)" -ForegroundColor Gray return $existingGroup } # Create new security group Write-Host " Creating group: $GroupName" -ForegroundColor Yellow $newGroup = $null try { # Try cmdlet first $newGroup = New-MgGroup -DisplayName $GroupName ` -MailNickName ($GroupName.Replace(' ', '_').Replace('-', '_')) ` -MailEnabled:$False ` -SecurityEnabled ` -IsAssignableToRole:$False ` -ErrorAction Stop } catch { # Use REST API fallback (handles assembly conflicts and permission errors) $invokeCmd = Get-Command Invoke-MgGraphRequest -ErrorAction SilentlyContinue if ($invokeCmd) { $body = @{ displayName = $GroupName mailNickname = ($GroupName.Replace(' ', '_').Replace('-', '_')) mailEnabled = $false securityEnabled = $true groupTypes = @() } | ConvertTo-Json try { $newGroup = Invoke-MgGraphRequest -Method POST ` -Uri "https://graph.microsoft.com/v1.0/groups" ` -Body $body ` -ContentType "application/json" ` -ErrorAction Stop } catch { # Try to parse error response as JSON, but handle non-JSON errors gracefully $errorResponse = $null $errorMessage = $_.ErrorDetails.Message if ($errorMessage) { # Check if error message looks like JSON (starts with { or [) if ($errorMessage.Trim().StartsWith('{') -or $errorMessage.Trim().StartsWith('[')) { try { $errorResponse = $errorMessage | ConvertFrom-Json -ErrorAction Stop } catch { # Not valid JSON, ignore } } # Check for permission errors in plain text too if ($errorMessage -match "403" -or $errorMessage -match "Authorization_RequestDenied" -or $errorMessage -match "Insufficient") { throw "Insufficient permissions. App Registration needs 'Group.ReadWrite.All' or 'Group.Create' permission." } } # If we successfully parsed JSON and it's an authorization error if ($errorResponse -and $errorResponse.error -and $errorResponse.error.code -eq "Authorization_RequestDenied") { throw "Insufficient permissions. App Registration needs 'Group.ReadWrite.All' or 'Group.Create' permission." } # Re-throw original error if not a permission issue throw $_ } } else { throw "Cannot create group: $_" } } $groupId = if ($newGroup.Id) { $newGroup.Id } else { $newGroup.id } Write-Host " Group created: $GroupName (ID: $groupId)" -ForegroundColor Green return $newGroup } catch { $errorMsg = $_.Exception.Message $fullError = $_.ToString() # Check for JSON parsing errors (these are usually permission errors in disguise) if ($errorMsg -match "Conversion from JSON failed" -or $errorMsg -match "Unexpected character") { Write-Warning "Failed to create group $GroupName : Likely insufficient permissions (JSON parsing error indicates API permission issue)" throw "Insufficient permissions to create groups. Please add 'Group.ReadWrite.All' or 'Group.Create' permission to your App Registration." } # Check for permission errors elseif ($errorMsg -match "403" -or $errorMsg -match "Authorization_RequestDenied" -or $errorMsg -match "Insufficient" -or $fullError -match "403" -or $fullError -match "Authorization_RequestDenied") { Write-Warning "Failed to create group $GroupName : Insufficient permissions. The App Registration needs 'Group.ReadWrite.All' or 'Group.Create' permission." throw "Insufficient permissions to create groups. Please add 'Group.ReadWrite.All' or 'Group.Create' permission to your App Registration." } else { Write-Warning "Failed to create group $GroupName : $errorMsg" throw $_ } } } |