Skip to content

Update-EntraGroup - WhatIf experiment #1414

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions module/Entra/Microsoft.Entra/Groups/Update-EntraGroup.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# ------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All Rights Reserved.
# Licensed under the MIT License. See License in the project root for license information.
# ------------------------------------------------------------------------------

function Update-EntraGroup {
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium', DefaultParameterSetName = 'Default')]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "The unique identifier for the group, such as its object ID.")]
[Alias("ObjectId", "Id")]
[ValidateNotNullOrEmpty()]
[string]$GroupId,

[Parameter(HelpMessage = "The description of the group.")]
[string]$Description,

[Parameter(HelpMessage = "The display name of the group.")]
[string]$DisplayName,

[Parameter(HelpMessage = "Defines the group type and membership. Possible values: 'Unified' (Microsoft 365 group) or 'DynamicMembership'. If not 'Unified', the group is a security or distribution group.")]
[string[]]$GroupTypes,

[Parameter(HelpMessage = "Specifies whether the group is mail-enabled.")]
[bool]$MailEnabled,

[Parameter(HelpMessage = "The mail nickname for the group.")]
[string]$MailNickname,

[Parameter(HelpMessage = "Specifies whether the group is a security group.")]
[bool]$SecurityEnabled,

[Parameter(HelpMessage = "Indicates if the group can be assigned to a Microsoft Entra role (only for security groups). This setting is fixed at creation and cannot be changed.")]
[bool]$IsAssignableToRole,

[Parameter(HelpMessage = "A list of SMTP proxy addresses for the group, including the primary SMTP address.")]
[string[]]$ProxyAddresses,

[Parameter(HelpMessage = "Specifies whether the group is visible in the address list.")]
[string]$Visibility,

[Parameter(Mandatory = $false, HelpMessage = "A hashtable of additional group properties to update.")]
[Alias("BodyParameter", "Body", "BodyParameters")]
[hashtable]$AdditionalProperties = @{}
)

begin {

# Ensure connection to Microsoft Entra
if (-not (Get-EntraContext)) {
$errorMessage = "Not connected to Microsoft Graph. Use 'Connect-Entra -Scopes Group.ReadWrite.All' to authenticate."
Write-Error -Message $errorMessage -ErrorAction Stop
return
}

}

process {
$customHeaders = New-EntraCustomHeaders -Command $MyInvocation.MyCommand

# Microsoft Graph API URL for updating group properties
$graphUri = "https://graph.microsoft.com/v1.0/groups/$GroupId"

# Initialize hashtable for group properties
$GroupProperties = @{}

$CommonParameters = @("Verbose", "Debug", "WarningAction", "WarningVariable", "ErrorAction", "ErrorVariable", "OutVariable", "OutBuffer", "WhatIf", "Confirm")

# Merge individual parameters into GroupProperties
foreach ($param in $PSBoundParameters.Keys) {
if ($param -ne "GroupId" -and $param -ne "AdditionalProperties" -and $CommonParameters -notcontains $param) {
$GroupProperties[$param] = $PSBoundParameters[$param]
}
}

# Merge AdditionalProperties if provided
foreach ($key in $AdditionalProperties.Keys) {
$GroupProperties[$key] = $AdditionalProperties[$key]
}

if ($GroupProperties.Count -eq 0) {
Write-Warning "No properties provided for update. Exiting."
return
}

# Convert final update properties to JSON
$bodyJson = $GroupProperties | ConvertTo-Json -Depth 2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-Depth 2 for ConvertTo-Json might be sufficient for deeply nested properties, for a user



if ($PSCmdlet.ShouldProcess("Group with ID '$GroupId'", "Update the following properties: $($GroupProperties.Keys -join ', ')")) {
try {
# Invoke Microsoft Graph API Request
Invoke-MgGraphRequest -Uri $graphUri -Method PATCH -Body $bodyJson -Headers $customHeaders
Write-Verbose "Properties for group $GroupId updated successfully. Updated properties: $($GroupProperties | Out-String)"
}
catch {
Write-Debug "Error Details: $_"
Write-Error "Failed to update group properties: $_"
}
}
}
}
65 changes: 65 additions & 0 deletions test/Entra/Groups/Update-EntraGroup.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# ------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
# ------------------------------------------------------------------------------

BeforeAll {
if((Get-Module -Name Microsoft.Entra.Groups) -eq $null){
Import-Module Microsoft.Entra.Groups
}
Import-Module (Join-Path $PSScriptRoot "..\..\Common-Functions.ps1") -Force

Mock -CommandName Invoke-MgGraphRequest -MockWith {} -ModuleName Microsoft.Entra.Groups
Mock -CommandName Get-EntraContext -MockWith { @{Scopes = @("Group.ReadWrite.All")} } -ModuleName Microsoft.Entra.Groups
}

Describe "Update-EntraGroup" {
Context "Test for Update-EntraGroup" {
It "Should return empty object" {
$result = Update-EntraGroup -GroupId bbbbbbbb-1111-2222-3333-cccccccccccc -DisplayName "demo" -MailEnabled $false -SecurityEnabled $true -MailNickName "demoNickname" -Description "test"
$result | Should -BeNullOrEmpty

Should -Invoke -CommandName Invoke-MgGraphRequest -ModuleName Microsoft.Entra.Groups -Times 1
}
It "Should execute successfully with Alias" {
$result = Update-EntraGroup -Id bbbbbbbb-1111-2222-3333-cccccccccccc -DisplayName "demo" -MailEnabled $false -SecurityEnabled $true -MailNickName "demoNickname" -Description "test"
$result | Should -BeNullOrEmpty

Should -Invoke -CommandName Invoke-MgGraphRequest -ModuleName Microsoft.Entra.Groups -Times 1
}
It "Should fail when GroupId is invalid" {
{ Update-EntraGroup -GroupId "" } | Should -Throw "Cannot validate argument on parameter 'GroupId'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again."
}
It "Should fail when GroupId is empty" {
{ Update-EntraGroup -GroupId } | Should -Throw "Missing an argument for parameter 'GroupId'*"
}
It "Should not execute Invoke-MgGraphRequest with WhatIf parameter" {
Update-EntraGroup -GroupId bbbbbbbb-1111-2222-3333-cccccccccccc -DisplayName "demo" -WhatIf
Should -Invoke -CommandName Invoke-MgGraphRequest -ModuleName Microsoft.Entra.Groups -Times 0
}
It "Should contain 'User-Agent' header" {
$userAgentHeaderValue = "PowerShell/$psVersion EntraPowershell/$entraVersion Update-EntraGroup"

Update-EntraGroup -Id bbbbbbbb-1111-2222-3333-cccccccccccc -DisplayName "demo"

$userAgentHeaderValue = "PowerShell/$psVersion EntraPowershell/$entraVersion Update-EntraGroup"
Should -Invoke -CommandName Invoke-MgGraphRequest -ModuleName Microsoft.Entra.Groups -Times 1 -ParameterFilter {
$Headers.'User-Agent' | Should -Be $userAgentHeaderValue
$true
}
}
It "Should execute successfully without throwing an error " {
# Disable confirmation prompts
$originalDebugPreference = $DebugPreference
$DebugPreference = 'Continue'

try {
# Act & Assert: Ensure the function doesn't throw an exception
{ Update-EntraGroup -Id bbbbbbbb-1111-2222-3333-cccccccccccc } | Should -Not -Throw
} finally {
# Restore original confirmation preference
$DebugPreference = $originalDebugPreference
}
}
}
}