Skip to content
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

xUser: add NewName property #719

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 xUser.

## [9.1.0] - 2020-02-19

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,8 @@ None
* Default Value: Present
* **[String] FullName** _(Write)_: Represents a string with the full name you
want to use for the user account.
* **[String] NewName** _(Write)_: Represents a string with the new name you
want to use for the user account. When setting this property, the UserName property must be set appropriately to uniquely identify the user both before and after setting the SamAccountName, e.g. by SID.
* **[PSCredential] Password** _(Write)_: Indicates the password you want to use
for this account.
* **[Boolean] PasswordChangeNotAllowed** _(Write)_: Indicates if the user can
Expand Down
104 changes: 104 additions & 0 deletions source/DSCResources/DSC_xUserResource/DSC_xUserResource.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ function Get-TargetResource
The (optional) full name or display name of the user.
If not provided this value will remain blank.

.PARAMETER NewName
Specifies the new name of the user.

.PARAMETER Description
Optional description for the user.

Expand Down Expand Up @@ -113,6 +116,10 @@ function Set-TargetResource
[System.String]
$FullName,

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

[Parameter()]
[System.String]
$Description,
Expand Down Expand Up @@ -165,6 +172,9 @@ function Set-TargetResource
The full name/display name that the user should have.
If not provided, this value will not be tested.

.PARAMETER NewName
Specifies the new name of the user.

.PARAMETER Description
The description that the user should have.
If not provided, this value will not be tested.
Expand Down Expand Up @@ -204,6 +214,10 @@ function Test-TargetResource
[System.String]
$FullName,

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

[Parameter()]
[System.String]
$Description,
Expand Down Expand Up @@ -328,6 +342,9 @@ function Get-TargetResourceOnFullSKU
The (optional) full name or display name of the user.
If not provided this value will remain blank.

.PARAMETER NewName
Specifies the new name of the user.

.PARAMETER Description
Optional description for the user.

Expand Down Expand Up @@ -372,6 +389,10 @@ function Set-TargetResourceOnFullSKU
[System.String]
$FullName,

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

[Parameter()]
[System.String]
$Description,
Expand Down Expand Up @@ -404,6 +425,10 @@ function Set-TargetResourceOnFullSKU
Write-Verbose -Message ($script:localizedData.ConfigurationStarted -f $UserName)

Assert-UserNameValid -UserName $UserName
if ($newName)
{
Assert-UserNameValid -UserName $NewName
}

# Try to find a user by name.
$principalContext = New-Object `
Expand All @@ -426,6 +451,7 @@ function Set-TargetResourceOnFullSKU
$whatIfShouldProcess = $true
$userExists = $false
$saveChanges = $false
$needsRename = $false

if ($null -eq $user)
{
Expand All @@ -446,6 +472,15 @@ function Set-TargetResourceOnFullSKU
if (-not $userExists)
{
# The user with the provided name does not exist so add a new user
foreach ($incompatibleParameterName in @( 'NewName' ))
{
if ($PSBoundParameters.ContainsKey($incompatibleParameterName))
{
New-InvalidArgumentException -ArgumentName $incompatibleParameterName `
-Message ($script:localizedData.NewUserNewNameConflict -f 'NewName', $incompatibleParameterName)
}
}

$user = New-Object `
-TypeName System.DirectoryServices.AccountManagement.UserPrincipal `
-ArgumentList $principalContext
Expand Down Expand Up @@ -474,6 +509,13 @@ function Set-TargetResourceOnFullSKU
$saveChanges = $true
}

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

# Set the password regardless of the state of the user
if ($PSBoundParameters.ContainsKey('Password'))
{
Expand Down Expand Up @@ -514,6 +556,13 @@ function Set-TargetResourceOnFullSKU
{
$user.Save()

if ($needsRename)
{
$dirEntry = [System.DirectoryServices.DirectoryEntry]($user.GetUnderlyingObject())
$dirEntry.Rename($newName);
$dirEntry.CommitChanges();
}

# Send an operation success verbose message
if ($userExists)
{
Expand Down Expand Up @@ -582,6 +631,9 @@ function Set-TargetResourceOnFullSKU
The full name/display name that the user should have.
If not provided, this value will not be tested.

.PARAMETER NewName
Specifies the new name of the user.

.PARAMETER Description
The description that the user should have.
If not provided, this value will not be tested.
Expand Down Expand Up @@ -621,6 +673,10 @@ function Test-TargetResourceOnFullSKU
[System.String]
$FullName,

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

[Parameter()]
[System.String]
$Description,
Expand Down Expand Up @@ -651,6 +707,10 @@ function Test-TargetResourceOnFullSKU
Set-StrictMode -Version Latest

Assert-UserNameValid -UserName $UserName
if ($newName)
{
Assert-UserNameValid -UserName $NewName
}

# Try to find a user by a name
$principalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext `
Expand Down Expand Up @@ -699,6 +759,13 @@ function Test-TargetResourceOnFullSKU
return $false
}

if ($PSBoundParameters.ContainsKey('NewName') -and $NewName -ne $user.SamAccountName)
{
# The Name property does not match
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'NewName', $NewName, $user.SamAccountName)
return $false
}

# Password
if ($PSBoundParameters.ContainsKey('Password'))
{
Expand Down Expand Up @@ -833,6 +900,9 @@ function Get-TargetResourceOnNanoServer
The (optional) full name or display name of the user.
If not provided this value will remain blank.

.PARAMETER NewName
Specifies the new name of the user.

.PARAMETER Description
Optional description for the user.

Expand Down Expand Up @@ -876,6 +946,10 @@ function Set-TargetResourceOnNanoServer
[System.String]
$FullName,

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

[Parameter()]
[System.String]
$Description,
Expand Down Expand Up @@ -908,6 +982,10 @@ function Set-TargetResourceOnNanoServer
Write-Verbose -Message ($script:localizedData.ConfigurationStarted -f $UserName)

Assert-UserNameValid -UserName $UserName
if ($newName)
{
Assert-UserNameValid -UserName $NewName
}

# Try to find a user by a name.
$userExists = $false
Expand Down Expand Up @@ -977,6 +1055,14 @@ function Set-TargetResourceOnNanoServer
}
}

if ($PSBoundParameters.ContainsKey('NewName') -and ((-not $userExists) -or ($NewName -ne $user.SamAccountName)))
{
if ($null -ne $NewName)
{
Rename-LocalUser -Sid $UserName -NewName $NewName
}
}

# Set the password regardless of the state of the user
if ($PSBoundParameters.ContainsKey('Password'))
{
Expand Down Expand Up @@ -1054,6 +1140,9 @@ function Set-TargetResourceOnNanoServer
The full name/display name that the user should have.
If not provided, this value will not be tested.

.PARAMETER NewName
Specifies the new name of the user.

.PARAMETER Description
The description that the user should have.
If not provided, this value will not be tested.
Expand Down Expand Up @@ -1093,6 +1182,10 @@ function Test-TargetResourceOnNanoServer
[System.String]
$FullName,

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

[Parameter()]
[System.String]
$Description,
Expand Down Expand Up @@ -1123,6 +1216,10 @@ function Test-TargetResourceOnNanoServer
Set-StrictMode -Version Latest

Assert-UserNameValid -UserName $UserName
if ($newName)
{
Assert-UserNameValid -UserName $NewName
}

# Try to find a user by a name
try
Expand Down Expand Up @@ -1171,6 +1268,13 @@ function Test-TargetResourceOnNanoServer
return $false
}

if ($PSBoundParameters.ContainsKey('NewName') -and $NewName -ne $user.SamAccountName)
{
# The Name property does not match
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'NewName', $NewName, $user.SamAccountName)
return $false
}

if ($PSBoundParameters.ContainsKey('Password'))
{
if (-not (Test-CredentialsValidOnNanoServer -UserName $UserName -Password $Password.Password))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class DSC_xUserResource : OMI_BaseResource
[Key,Description("The name of the User to Create/Modify/Delete")] String UserName;
[Write,Description("An enumerated value that describes if the user is expected to exist on the machine"),ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] String Ensure;
[Write,Description("The display name of the user")] String FullName;
[Write,Description("Specifies the new name of the user")] String NewName;
[Write,Description("A description for the user")] String Description;
[Write,Description("The password for the user"),EmbeddedInstance("MSFT_Credential")] String Password;
[Write,Description("Value used to disable/enable a user account")] Boolean Disabled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ConvertFrom-StringData @'
UserRemoved = User {0} removed successfully.
NoConfigurationRequired = User {0} exists on this node with the desired properties. No action required.
NoConfigurationRequiredUserDoesNotExist = User {0} does not exist on this node. No action required.
NewUserNewNameConflict = The {0} parameter cannot be used when creating a new user.
InvalidUserName = The name {0} cannot be used. Names may not consist entirely of periods and/or spaces, or contain these characters: {1}
UserExists = A user with the name {0} exists.
UserDoesNotExist = A user with the name {0} does not exist.
Expand Down
29 changes: 29 additions & 0 deletions tests/Unit/DSC_xUserResource.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ try
}

Mock -CommandName Test-IsNanoServer -MockWith { return $false }
#Mock -CommandName New-Object

New-User -Credential $script:newCredential1 -Description $script:newUserDescription1

Expand All @@ -134,6 +135,20 @@ try
Test-User -UserName $script:newUserName2 | Should -BeTrue
}

It 'Should rename the user' {
Test-User -UserName $script:newUserName1 | Should -BeFalse
Set-TargetResource -UserName $script:newUserName2 `
-NewName $script:newUserName1
Test-User -UserName $script:newUserName1 | Should -BeTrue
}

It 'Should rename the user again' {
Test-User -UserName $script:newUserName2 | Should -BeFalse
Set-TargetResource -UserName $script:newUserName1 `
-NewName $script:newUserName2
Test-User -UserName $script:newUserName2 | Should -BeTrue
}

It 'Should update the user' {
$disabled = $false
$passwordNeverExpires = $true
Expand Down Expand Up @@ -212,6 +227,20 @@ try
Test-User -UserName $script:newUserName2 | Should -BeTrue
}

It 'Should rename the user' -Skip:$script:skipMe {
Test-User -UserName $script:newUserName1 | Should -BeFalse
Set-TargetResource -UserName $script:newUserName2 `
-NewName $script:newUserName1
Test-User -UserName $script:newUserName1 | Should -BeTrue
}

It 'Should rename the user again' -Skip:$script:skipMe {
Test-User -UserName $script:newUserName2 | Should -BeFalse
Set-TargetResource -UserName $script:newUserName1 `
-NewName $script:newUserName2
Test-User -UserName $script:newUserName2 | Should -BeTrue
}

It 'Should update the user' -Skip:$script:skipMe {
$disabled = $false
$passwordNeverExpires = $true
Expand Down