Public/New-IntuneAppGroup.ps1
|
<# .SYNOPSIS Creates Intune app assignment groups ("Available" and "Required") in Microsoft Entra ID. .DESCRIPTION The New-IntuneAppGroup function creates two security groups in Microsoft Entra ID for each application name: one for "Available" and one for "Required" Intune assignments. Groups are named 'Intune-AG-<Name>-<Intent>' (app groups) or 'Intune-ACG-<Name>-<Intent>' (app collection groups, with -Collection). The name is converted to PascalCase with spaces removed, for example 'company portal' becomes 'CompanyPortal'. The mail nickname is the group name with characters that Entra ID does not allow in a mail nickname removed. A group that already exists (same display name) is skipped with a warning. The created group objects are written to the pipeline. Requires the Microsoft Entra PowerShell module (Microsoft.Entra or Microsoft.Entra.Groups) and an authenticated session (Connect-Entra) with permission to create groups, for example the Group.ReadWrite.All scope. Supports -WhatIf and -Confirm. .PARAMETER Name One or more application names. Two groups ("Available" and "Required") are created for each name. .PARAMETER Collection Create app collection groups ('Intune-ACG-...') instead of app groups ('Intune-AG-...'). .INPUTS None This function does not accept pipeline input. .OUTPUTS System.Object The group objects returned by New-EntraGroup. .EXAMPLE New-IntuneAppGroup -Name 'App1', 'App2' Creates Intune-AG-App1-Available, Intune-AG-App1-Required, Intune-AG-App2-Available and Intune-AG-App2-Required. .EXAMPLE New-IntuneAppGroup -Collection -Name 'office apps' -WhatIf Shows that Intune-ACG-OfficeApps-Available and Intune-ACG-OfficeApps-Required would be created, without creating them. .NOTES Author: Nigel Tatschner Company: TheCodeSaiyan .LINK https://learn.microsoft.com/powershell/module/microsoft.entra.groups/new-entragroup #> function New-IntuneAppGroup { [CmdletBinding(SupportsShouldProcess = $true)] [OutputType([object])] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string[]] $Name, [switch] $Collection ) $TelemetryArgs = @{ ModuleName = $MyInvocation.MyCommand.Module.Name ModuleVersion = [string]$MyInvocation.MyCommand.Module.Version CommandName = $MyInvocation.MyCommand.Name ExecutionID = [guid]::NewGuid().ToString() } Invoke-TelemetryCollection @TelemetryArgs -Stage Start -ClearTimer $missingCommands = @('Get-EntraGroup', 'New-EntraGroup' | Where-Object { -not (Get-Command -Name $_ -ErrorAction SilentlyContinue) }) if ($missingCommands.Count -gt 0) { $exception = [System.Management.Automation.CommandNotFoundException]::new( "New-IntuneAppGroup needs $($missingCommands -join ' and ') from the Microsoft Entra PowerShell module. " + "Install it with 'Install-Module Microsoft.Entra.Groups -Scope CurrentUser' (or 'Microsoft.Entra'), then run 'Connect-Entra -Scopes Group.ReadWrite.All'.") $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, 'EntraModuleNotFound', [System.Management.Automation.ErrorCategory]::ObjectNotFound, $null) Invoke-TelemetryCollection @TelemetryArgs -Stage End -Failed $true -Exception $errorRecord $PSCmdlet.ThrowTerminatingError($errorRecord) } $groupType = if ($Collection) { 'ACG' } else { 'AG' } $groupKind = if ($Collection) { 'App Collection Group' } else { 'App Group' } $totalIterations = $Name.Count * 2 $currentIteration = 0 $lastError = $null try { foreach ($appName in $Name) { $words = @($appName -split '\s+' | Where-Object { $_ }) $appName = ($words | ForEach-Object { $_.Substring(0, 1).ToUpper() + $_.Substring(1) }) -join '' if (-not $appName) { $currentIteration += 2 Write-Error -Message 'An application name cannot be blank or whitespace only.' -Category InvalidArgument -ErrorId 'BlankName' continue } $description = "Intune $groupKind for `"$appName`", this is an" foreach ($intent in @('Available', 'Required')) { $currentIteration++ Write-Progress -Activity 'Creating Intune Groups' -Status "Processing $appName ($intent)" -PercentComplete (($currentIteration / $totalIterations) * 100) $displayName = "Intune-$groupType-$appName-$intent" if (-not $PSCmdlet.ShouldProcess($displayName, 'Create Entra ID security group')) { continue } try { # Single quotes are doubled so the name is a valid OData string literal $filter = "DisplayName eq '$($displayName -replace "'", "''")'" if (Get-EntraGroup -Filter $filter -ErrorAction Stop) { Write-Warning "Group `"$displayName`" already exists." continue } $groupParams = @{ DisplayName = $displayName # Entra ID mail nicknames cannot contain spaces, non-ASCII characters or @ ( ) \ [ ] " ; : < > , MailNickname = $displayName -replace '[^\x21-\x7E]|[@()\\\[\]";:<>,]', '' Description = "$description $intent install." MailEnabled = $false SecurityEnabled = $true } Write-Verbose "Creating Intune group `"$displayName`"" New-EntraGroup @groupParams -ErrorAction Stop Write-Verbose "Group `"$displayName`" created." } catch { $lastError = $_ Write-Error -ErrorRecord $_ } } } } catch { # Reached when the caller asked for errors to stop (-ErrorAction Stop) $lastError = $_ throw } finally { Write-Progress -Activity 'Creating Intune Groups' -Completed if ($lastError) { Invoke-TelemetryCollection @TelemetryArgs -Stage End -Failed $true -Exception $lastError } else { Invoke-TelemetryCollection @TelemetryArgs -Stage End } } } |