functions/group/Add-PSEntraIDGroupMember.ps1
|
function Add-PSEntraIDGroupMember { <# .SYNOPSIS Add a member to a security or Microsoft 365 group. .DESCRIPTION Add a member to a security or Microsoft 365 group. .PARAMETER InputObject PSMicrosoftEntraID.Users.User object in tenant/directory. .PARAMETER Identity MailNickName or Id of group or team .PARAMETER User UserPrincipalName, Mail or Id of the user attribute populated in tenant/directory. .PARAMETER EnableException This parameter disables user-friendly warnings and enables the throwing of exceptions. This is less user friendly, but allows catching exceptions in calling scripts. .PARAMETER WhatIf Enables the function to simulate what it will do instead of actually executing. .PARAMETER Force Suppresses the confirmation prompt, for unattended use. An explicitly bound -Confirm wins over it, whatever its value: -Confirm:$true prompts even with -Force present. The two are therefore alternatives rather than a pair - passing both says nothing the second one does not already say. Without either, whether the command prompts is left to its ConfirmImpact and the session ConfirmPreference, which is the PowerShell default behaviour. .PARAMETER Confirm Prompts for confirmation before the command makes a change. -Confirm:$false suppresses that prompt. Bound explicitly it wins over -Force, whatever its value - so -Confirm:$true prompts even alongside -Force, and the two are alternatives rather than a pair. Left unbound, the decision belongs to this command's ConfirmImpact and the session ConfirmPreference, which is the PowerShell default behaviour. .PARAMETER PassThru When specified, the cmdlet will not execute the action but will instead return a `PSMicrosoftEntraID.Batch.Request` object for batch processing. .EXAMPLE PS C:\> Add-PSEntraIDGroupMember -Identity group1 -User user1,user2 Add member to Azure AD group group1 #> [OutputType([PSMicrosoftEntraID.Batch.Request])] [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium', DefaultParameterSetName = 'IdentityInputObject')] param( [Parameter(Mandatory = $true, ParameterSetName = 'IdentityInputObject')] [Parameter(Mandatory = $true, ParameterSetName = 'IdentityUser')] [Alias("Id", "GroupId", "TeamId", "MailNickName")] [ValidateGroupIdentity()] [string] $Identity, [Parameter(Mandatory = $True, ValueFromPipeline = $true, ParameterSetName = 'IdentityInputObject')] [PSMicrosoftEntraID.Users.User[]] $InputObject, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'IdentityUser')] [Alias("UserId", "UserPrincipalName", "Mail")] [ValidateUserIdentity()] [string[]] $User, [Parameter()] [switch] $EnableException, [Parameter()] [switch] $Force, [Parameter()] [switch]$PassThru ) begin { [string] $service = Get-PSFConfigValue -FullName ('{0}.Settings.DefaultService' -f $script:ModuleName) Assert-EntraConnection -Service $service -Cmdlet $PSCmdlet [int] $commandRetryCount = Get-PSFConfigValue -FullName ('{0}.Settings.Command.RetryCount' -f $script:ModuleName) [System.TimeSpan] $commandRetryWait = New-TimeSpan -Seconds (Get-PSFConfigValue -FullName ('{0}.Settings.Command.RetryWaitInSeconds' -f $script:ModuleName)) [int] $nextLoop = 20 [hashtable] $header = @{ 'Content-Type' = 'application/json' } [hashtable] $cmdLetConfirm = Resolve-PSEntraIDConfirmPreference -BoundParameters $PSBoundParameters -Force:$Force -Confirm:$Confirm [PSMicrosoftEntraID.Groups.Group] $group = Get-PSEntraIDGroup -Identity $Identity if ([object]::Equals($group, $null)) { Invoke-TerminatingException -Cmdlet $PSCmdlet -Message ((Get-PSFLocalizedString -Module $script:ModuleName -Name Group.Get.Failed) -f $Identity) } } process { [System.Collections.Generic.List[object]] $memberUrlList = [System.Collections.Generic.List[object]]::new() [System.Collections.Generic.List[object]] $memberObjectIdList = [System.Collections.Generic.List[object]]::new() [System.Collections.Generic.List[object]] $memberUserPrincipalNameList = [System.Collections.Generic.List[object]]::new() [System.Collections.Generic.List[object]] $memberMailList = [System.Collections.Generic.List[object]]::new() switch ($PSCmdlet.ParameterSetName) { 'IdentityInputObject' { if ($InputObject.Count -eq 1) { [void] $memberUrlList.Add(('{0}/directoryObjects/{1}' -f (Get-EntraService -Name $service).ServiceUrl, $InputObject.Id)) [void] $memberObjectIdList.Add($InputObject.Id) [void] $memberUserPrincipalNameList.Add($InputObject.UserPrincipalName) [void] $memberMailList.Add($InputObject.Mail) [hashtable] $requestHash = @{ ObjectId = $memberObjectIdList UserPrincipalName = $memberUserPrincipalNameList Mail = $memberMailList Role = 'Member' UrlPath = ('groups/{0}/members/$ref' -f $group.Id) Method = 'POST' MemberUrlList = $memberUrlList } } else { foreach ($itemInputObject in $InputObject) { [void]$memberUrlList.Add(('{0}/directoryObjects/{1}' -f (Get-EntraService -Name $service).ServiceUrl, $itemInputObject.Id)) [void]$memberObjectIdList.Add($itemInputObject.Id) [void]$memberUserPrincipalNameList.Add($itemInputObject.UserPrincipalName) [void]$memberMailList.Add($itemInputObject.Mail) } [hashtable] $requestHash = @{ ObjectId = $memberObjectIdList UserPrincipalName = $memberUserPrincipalNameList Mail = $memberMailList Role = 'Member' UrlPath = ('groups/{0}' -f $group.Id) Method = 'PATCH' MemberUrlList = $memberUrlList } } } 'IdentityUser' { if ($User.Count -eq 1) { [PSMicrosoftEntraID.Users.User] $aADUser = Get-PSEntraIDUser -Identity $User if ([object]::Equals($aADUser, $null)) { if ($EnableException.IsPresent) { Invoke-TerminatingException -Cmdlet $PSCmdlet -Message ((Get-PSFLocalizedString -Module $script:ModuleName -Name User.Get.Failed) -f $User) } } else { [void] $memberUrlList.Add(('{0}/directoryObjects/{1}' -f (Get-EntraService -Name $service).ServiceUrl, $aADUser.Id)) [void] $memberObjectIdList.Add($aADUser.Id) [void] $memberUserPrincipalNameList.Add($aADUser.UserPrincipalName) [void] $memberMailList.Add($aADUser.Mail) [hashtable] $requestHash = @{ ObjectId = $memberObjectIdList UserPrincipalName = $memberUserPrincipalNameList Mail = $memberMailList Role = 'Member' UrlPath = ('groups/{0}/members/$ref' -f $group.Id) Method = 'POST' MemberUrlList = $memberUrlList } } } else { foreach ($itemUser in $User) { [PSMicrosoftEntraID.Users.User] $aADUser = Get-PSEntraIDUser -Identity $itemUser if ([object]::Equals($aADUser, $null)) { if ($EnableException.IsPresent) { Invoke-TerminatingException -Cmdlet $PSCmdlet -Message ((Get-PSFLocalizedString -Module $script:ModuleName -Name User.Get.Failed) -f $itemUser) } } else { [void] $memberUrlList.Add(('{0}/directoryObjects/{1}' -f (Get-EntraService -Name $service).ServiceUrl, $aADUser.Id)) [void] $memberObjectIdList.Add($aADUser.Id) [void] $memberUserPrincipalNameList.Add($aADUser.UserPrincipalName) [void] $memberMailList.Add($aADUser.Mail) } } $requestHash = @{ ObjectId = $memberObjectIdList UserPrincipalName = $memberUserPrincipalNameList Mail = $memberMailList Role = 'Member' UrlPath = ('groups/{0}' -f $group.Id) Method = 'PATCH' MemberUrlList = $memberUrlList } } } } if ($requestHash.ObjectId.Count -gt 1) { [string[]] $bodyList = $requestHash.MemberUrlList | Step-Array -Size $nextLoop foreach ($bodyItem in $bodyList) { [hashtable] $body = @{ 'members@odata.bind' = @($bodyItem) } $path = $requestHash.UrlPath $method = $requestHash.Method if ($PassThru.IsPresent) { [PSMicrosoftEntraID.Batch.Request]@{ Method = $method; Url = ('/{0}' -f $path); Body = $body; Headers = $header } } else { $userActionString = ($requestHash.UserPrincipalName | ForEach-Object { "{0}" -f $_ }) -join ',' Invoke-PSFProtectedCommand -ActionString 'GroupMember.Add' -ActionStringValues $userActionString -Target $group.DisplayName -ScriptBlock { [void] (Invoke-EntraRequest -Service $service -Path $path -Header $header -Body $body -Method $requestHash.Method -ErrorAction Stop) } -EnableException:$EnableException @cmdLetConfirm -PSCmdlet $PSCmdlet -Continue -RetryCount $commandRetryCount -RetryWait $commandRetryWait if (Test-PSFFunctionInterrupt) { return } } } } else { foreach ($memberUrl in $requestHash.MemberUrlList) { [hashtable] $body = @{ '@odata.id' = $memberUrl } $path = $requestHash.UrlPath $method = $requestHash.Method if ($PassThru.IsPresent) { [PSMicrosoftEntraID.Batch.Request]@{ Method = $method; Url = ('/{0}' -f $path); Body = $body; Headers = $header } } else { $userActionString = ($requestHash.UserPrincipalName | ForEach-Object { "{0}" -f $_ }) -join ',' Invoke-PSFProtectedCommand -ActionString 'GroupMember.Add' -ActionStringValues $userActionString -Target $group.DisplayName -ScriptBlock { [void] (Invoke-EntraRequest -Service $service -Path $path -Header $header -Body $body -Method $requestHash.Method -ErrorAction Stop) } -EnableException:$EnableException @cmdLetConfirm -PSCmdlet $PSCmdlet -Continue -RetryCount $commandRetryCount -RetryWait $commandRetryWait if (Test-PSFFunctionInterrupt) { return } } } } } end { } } |