Skip to content

xGroup: add NewName property #718

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

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated build to use `Sampler.GitHubTasks` - Fixes [Issue #711](https://github.com/dsccommunity/xPSDesiredStateConfiguration/issues/711).
- Added support for publishing code coverage to `CodeCov.io` and
Azure Pipelines - Fixes [Issue #711](https://github.com/dsccommunity/xPSDesiredStateConfiguration/issues/711).
- Added NewName property to xGroup.

## [9.1.0] - 2020-02-19

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ None
remove a group, set this property to Absent. The default value is Present.
{ *Present* | Absent }.
* **[String] Description** _(Write)_: The description the group should have.
* **[String] NewName** _(Write)_: The new name the group should have. When setting this property, the GroupName property must be set appropriately to uniquely identify the group both before and after setting the SamAccountName, e.g. by SID.
* **[String[]] Members** _(Write)_: The members the group should have. This
property will replace all the current group members with the specified
members. Members should be specified as strings in the format of their domain
Expand Down
84 changes: 84 additions & 0 deletions source/DSCResources/DSC_xGroupResource/DSC_xGroupResource.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ function Get-TargetResource
.PARAMETER Description
The description the group should have.

.PARAMETER NewName
The name the group should have.

.PARAMETER Members
The members the group should have.

Expand Down Expand Up @@ -203,6 +206,10 @@ function Set-TargetResource
[System.String]
$Description,

[Parameter()]
[System.String]
$NewName,

[Parameter()]
[System.String[]]
$Members,
Expand Down Expand Up @@ -254,6 +261,9 @@ function Set-TargetResource
.PARAMETER Description
The description of the group to test for.

.PARAMETER NewName
The name of the group to test for.

.PARAMETER Members
The list of members the group should have.

Expand Down Expand Up @@ -307,6 +317,10 @@ function Test-TargetResource
[System.String]
$Description,

[Parameter()]
[System.String]
$NewName,

[Parameter()]
[System.String[]]
$Members,
Expand Down Expand Up @@ -493,6 +507,9 @@ function Get-TargetResourceOnNanoServer
.PARAMETER Description
The description of the group.

.PARAMETER NewName
The name the group should have.

.PARAMETER Members
Use this property to replace the current group membership with the specified members.

Expand Down Expand Up @@ -547,6 +564,10 @@ function Set-TargetResourceOnFullSKU
[System.String]
$Description,

[Parameter()]
[System.String]
$NewName,

[Parameter()]
[System.String[]]
$Members,
Expand Down Expand Up @@ -596,9 +617,19 @@ function Set-TargetResourceOnFullSKU
if ($whatIfShouldProcess)
{
$saveChanges = $false
$needsRename = $false

if (-not $groupOriginallyExists)
{
foreach ($incompatibleParameterName in @( 'NewName' ))
{
if ($PSBoundParameters.ContainsKey($incompatibleParameterName))
{
New-InvalidArgumentException -ArgumentName $incompatibleParameterName `
-Message ($script:localizedData.NewGroupNewNameConflict -f 'NewName', $incompatibleParameterName)
}
}

$localPrincipalContext = Get-PrincipalContext -PrincipalContextCache $principalContextCache `
-Disposables $disposables -Scope $env:COMPUTERNAME

Expand All @@ -618,6 +649,13 @@ function Set-TargetResourceOnFullSKU
$saveChanges = $true
}

if ($PSBoundParameters.ContainsKey('NewName') -and (($groupOriginallyExists) -and ($NewName -ne $group.SamAccountName)))
{
$group.SamAccountName = $NewName
$saveChanges = $true
$needsRename = $true
}

$actualMembersAsPrincipals = $null

<#
Expand Down Expand Up @@ -790,6 +828,13 @@ function Set-TargetResourceOnFullSKU
{
Save-Group -Group $group

if ($needsRename)
{
$dirEntry = $group.GetUnderlyingObject()
$dirEntry.Rename($newName)
$dirEntry.CommitChanges()
}

# Send an operation success verbose message.
if ($groupOriginallyExists)
{
Expand Down Expand Up @@ -851,6 +896,9 @@ function Set-TargetResourceOnFullSKU
.PARAMETER Description
The description of the group.

.PARAMETER NewName
The name the group should have.

.PARAMETER Members
Use this property to replace the current group membership with the specified members.

Expand Down Expand Up @@ -904,6 +952,10 @@ function Set-TargetResourceOnNanoServer
[System.String]
$Description,

[Parameter()]
[System.String]
$NewName,

[Parameter()]
[System.String[]]
$Members,
Expand Down Expand Up @@ -971,6 +1023,12 @@ function Set-TargetResourceOnNanoServer
Set-LocalGroup -Name $GroupName -Description $Description
}

if ($PSBoundParameters.ContainsKey('NewName') -and
((-not $groupOriginallyExists) -or ($NewName -ne $group.SamAccountName)))
{
Rename-LocalGroup -Sid $GroupName -NewName $NewName
}

if ($PSBoundParameters.ContainsKey('Members'))
{
foreach ($incompatibleParameterName in @( 'MembersToInclude', 'MembersToExclude' ))
Expand Down Expand Up @@ -1087,6 +1145,9 @@ function Set-TargetResourceOnNanoServer
.PARAMETER Description
The description of the group to test for.

.PARAMETER $NewName
The name of the group to test for.

.PARAMETER Members
Use this property to test if the existing membership of the group matches
the list provided.
Expand Down Expand Up @@ -1143,6 +1204,10 @@ function Test-TargetResourceOnFullSKU
[System.String]
$Description,

[Parameter()]
[System.String]
$NewName,

[Parameter()]
[System.String[]]
$Members,
Expand Down Expand Up @@ -1196,6 +1261,12 @@ function Test-TargetResourceOnFullSKU
return $false
}

if ($PSBoundParameters.ContainsKey('NewName') -and $NewName -ne $group.SamAccountName)
{
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'NewName', $NewName, $group.SamAccountName)
return $false
}

if ($PSBoundParameters.ContainsKey('Members'))
{
foreach ($incompatibleParameterName in @( 'MembersToInclude', 'MembersToExclude' ))
Expand Down Expand Up @@ -1354,6 +1425,9 @@ function Test-TargetResourceOnFullSKU
.PARAMETER Description
The description of the group to test for.

.PARAMETER NewName
The name of the group to test for.

.PARAMETER Members
Use this property to test if the existing membership of the group matches
the list provided.
Expand Down Expand Up @@ -1410,6 +1484,10 @@ function Test-TargetResourceOnNanoServer
[System.String]
$Description,

[Parameter()]
[System.String]
$NewName,

[Parameter()]
[System.String[]]
$Members,
Expand Down Expand Up @@ -1462,6 +1540,12 @@ function Test-TargetResourceOnNanoServer
return $false
}

if ($PSBoundParameters.ContainsKey('NewName') -and $NewName -ne $group.SamAccountName)
{
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'NewName', $NewName, $group.SamAccountName)
return $false
}

if ($PSBoundParameters.ContainsKey('Members'))
{
foreach ($incompatibleParameterName in @( 'MembersToInclude', 'MembersToExclude' ))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class DSC_xGroupResource : OMI_BaseResource
[Key, Description("The name of the group to create, modify, or remove.")] String GroupName;
[Write, ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}, Description("Indicates if the group should exist or not.")] String Ensure;
[Write, Description("The description the group should have.")] String Description;
[Write, Description("Specifies the new name of the group.")] String NewName;
[Write, Description("The members the group should have.")] String Members[];
[Write, Description("The members the group should include.")] String MembersToInclude[];
[Write, Description("The members the group should exclude.")] String MembersToExclude[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ConvertFrom-StringData @'
NoConfigurationRequiredGroupDoesNotExist = Group {0} does not exist on this node. No action required.
CouldNotFindPrincipal = Could not find a principal with the provided name {0}.
MembersAndIncludeExcludeConflict = The {0} and {1} parameters conflict. The {0} parameter should not be used in any combination with the {1} parameter.
NewGroupNewNameConflict = The {0} parameter cannot be used when creating a new group.
GroupAndMembersEmpty = Members is empty and group {0} has no members. No change to group members is needed.
MemberIsNotALocalUser = {0} is not a local user. User's principal source is {1}.
MemberNotValid = The group member {0} does not exist or cannot be resolved.
Expand Down
46 changes: 45 additions & 1 deletion tests/Unit/DSC_xGroupResource.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ try
$script:disposableObjects = @()

$script:testGroupName = 'TestGroup'
$script:testGroupName2= 'TestGroup2'
$script:testGroupDescription = 'A group for testing'

$script:localDomain = $env:computerName
Expand Down Expand Up @@ -439,6 +440,24 @@ try
Assert-MockCalled -CommandName 'Set-LocalGroup' -ParameterFilter { $Name -eq $script:testGroupName -and $Description -eq $script:testGroupDescription }
}

It 'Should change the name of an existing group' {
Set-TargetResourceOnNanoServer -GroupName $script:testGroupName `
-NewName $script:testGroupName2
#Assert-MockCalled -CommandName 'Get-PrincipalContext'
#Assert-MockCalled -CommandName 'Get-LocalGroup' -ParameterFilter { $GroupName -eq $script:testGroupName2 }
Assert-MockCalled -CommandName 'Get-LocalGroup' -ParameterFilter { $Sid -eq $script:testGroupName }
Assert-MockCalled -CommandName 'Rename-LocalGroup' -ParameterFilter { $Group.Sid -eq $script:testGroupName -and $Group.NewName -eq $script:testGroupName2 }
}

It 'Should change the name of an existing group again' {
Set-TargetResourceOnNanoServer -GroupName $script:testGroupName2 `
-NewName $script:testGroupName
#Assert-MockCalled -CommandName 'Get-PrincipalContext'
#Assert-MockCalled -CommandName 'Get-LocalGroup' -ParameterFilter { $GroupName -eq $script:testGroupName }
Assert-MockCalled -CommandName 'Get-LocalGroup' -ParameterFilter { $Sid -eq $script:testGroupName2 }
Assert-MockCalled -CommandName 'Rename-LocalGroup' -ParameterFilter { $Group.Sid -eq $script:testGroupName2 -and $Group.NewName -eq $script:testGroupName }
}

It 'Should create a group with one local member using Members' {
$testMembers = @( $script:testMemberName1 )

Expand Down Expand Up @@ -1088,7 +1107,32 @@ try
Assert-MockCalled -CommandName 'Remove-DisposableObject'
}

Mock -CommandName 'Get-Group' -MockWith { return $script:testGroup }
Mock -CommandName 'Get-Group' -MockWith { return $script:testGroup }

It 'Should change the name of an existing group' {
Mock -CommandName 'New-Object' -ParameterFilter { $TypeName -eq 'System.DirectoryServices.AccountManagement.GroupPrincipal' } -MockWith { return $testGroup }

Set-TargetResourceOnFullSKU -GroupName $script:testGroupName `
-NewName $script:testGroupName2

Assert-MockCalled -CommandName 'Get-PrincipalContext'
#Assert-MockCalled -CommandName 'Get-Group' -ParameterFilter { $GroupName -eq $script:testGroupName2 }
Assert-MockCalled -CommandName 'Get-Group' -ParameterFilter { $GroupName -eq $script:testGroupName }
Assert-MockCalled -CommandName 'New-Object' -ParameterFilter { $TypeName -eq 'System.DirectoryServices.AccountManagement.GroupPrincipal' }
Assert-MockCalled -CommandName 'Save-Group' -ParameterFilter { $Group.Name -eq $script:testGroupName -and $Group.NewName -eq $script:testGroupName2 }
}

It 'Should change the name of an existing group again' {
Mock -CommandName 'New-Object' -ParameterFilter { $TypeName -eq 'System.DirectoryServices.AccountManagement.GroupPrincipal' } -MockWith { return $testGroup }

Set-TargetResourceOnFullSKU -GroupName $script:testGroupName2 `
-NewName $script:testGroupName

Assert-MockCalled -CommandName 'Get-PrincipalContext'
#Assert-MockCalled -CommandName 'Get-Group' -ParameterFilter { $GroupName -eq $script:testGroupName }
Assert-MockCalled -CommandName 'Get-Group' -ParameterFilter { $GroupName -eq $script:testGroupName2 }
Assert-MockCalled -CommandName 'Save-Group' -ParameterFilter { $Group.Name -eq $script:testGroupName2 -and $Group.NewName -eq $script:testGroupName }
}

It 'Should add a member to an existing group with no members using Members' {
$testMembers = @( $script:testUserPrincipal1.Name )
Expand Down