mirror of
https://github.com/PowerShell/PSDscResources
synced 2026-06-21 13:45:29 +00:00
1596 lines
44 KiB
PowerShell
1596 lines
44 KiB
PowerShell
# User name and password needed for this resource and Write-Verbose Used in helper functions
|
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingUserNameAndPassWordParams', '')]
|
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSDSCUseVerboseMessageInDSCResource', '')]
|
|
param ()
|
|
|
|
$errorActionPreference = 'Stop'
|
|
Set-StrictMode -Version 'Latest'
|
|
|
|
Import-Module -Name (Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) `
|
|
-ChildPath 'CommonResourceHelper.psm1')
|
|
|
|
# Localized messages for Write-Verbose statements in this resource
|
|
$script:localizedData = Get-LocalizedData -ResourceName 'MSFT_UserResource'
|
|
|
|
if (-not (Test-IsNanoServer))
|
|
{
|
|
Add-Type -AssemblyName 'System.DirectoryServices.AccountManagement'
|
|
}
|
|
# get rid of this else once the fix for this is released
|
|
else
|
|
{
|
|
Import-Module -Name 'Microsoft.Powershell.LocalAccounts'
|
|
}
|
|
|
|
# Commented out until the fix is released
|
|
#Import-Module -Name 'Microsoft.Powershell.LocalAccounts'
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Retrieves the user with the given username
|
|
|
|
.PARAMETER UserName
|
|
The name of the user to retrieve.
|
|
#>
|
|
function Get-TargetResource
|
|
{
|
|
[OutputType([System.Collections.Hashtable])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName
|
|
)
|
|
|
|
if (Test-IsNanoServer)
|
|
{
|
|
Get-TargetResourceOnNanoServer @PSBoundParameters
|
|
}
|
|
else
|
|
{
|
|
Get-TargetResourceOnFullSKU @PSBoundParameters
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Creates, modifies, or deletes a user.
|
|
|
|
.PARAMETER UserName
|
|
The name of the user to create, modify, or delete.
|
|
|
|
.PARAMETER Ensure
|
|
Specifies whether the user should exist or not.
|
|
By default this is set to Present.
|
|
|
|
.PARAMETER FullName
|
|
The (optional) full name or display name of the user.
|
|
If not provided this value will remain blank.
|
|
|
|
.PARAMETER Description
|
|
Optional description for the user.
|
|
|
|
.PARAMETER Password
|
|
The desired password for the user.
|
|
|
|
.PARAMETER Disabled
|
|
Specifies whether the user should be disabled or not.
|
|
By default this is set to $false
|
|
|
|
.PARAMETER PasswordNeverExpires
|
|
Specifies whether the password should ever expire or not.
|
|
By default this is set to $false
|
|
|
|
.PARAMETER PasswordChangeRequired
|
|
Specifies whether the user must reset their password or not.
|
|
By default this is set to $false
|
|
|
|
.PARAMETER PasswordChangeNotAllowed
|
|
Specifies whether the user is allowed to change their password or not.
|
|
By default this is set to $false
|
|
|
|
.NOTES
|
|
If Ensure is set to 'Present' then the password parameter is required.
|
|
#>
|
|
function Set-TargetResource
|
|
{
|
|
# Should process is called in a helper functions but not directly in Set-TargetResource
|
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
|
[CmdletBinding(SupportsShouldProcess = $true)]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName,
|
|
|
|
[Parameter()]
|
|
[ValidateSet('Present', 'Absent')]
|
|
[System.String]
|
|
$Ensure = 'Present',
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$FullName,
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$Description,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCredential]
|
|
[System.Management.Automation.Credential()]
|
|
$Password,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$Disabled,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordNeverExpires,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeRequired,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeNotAllowed
|
|
)
|
|
|
|
if (Test-IsNanoServer)
|
|
{
|
|
Set-TargetResourceOnNanoServer @PSBoundParameters
|
|
}
|
|
else
|
|
{
|
|
Set-TargetResourceOnFullSKU @PSBoundParameters
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Tests if a user is in the desired state.
|
|
|
|
.PARAMETER UserName
|
|
The name of the user to test the state of.
|
|
|
|
.PARAMETER Ensure
|
|
Specifies whether the user should exist or not.
|
|
By default this is set to Present
|
|
|
|
.PARAMETER FullName
|
|
The full name/display name that the user should have.
|
|
If not provided, this value will not be tested.
|
|
|
|
.PARAMETER Description
|
|
The description that the user should have.
|
|
If not provided, this value will not be tested.
|
|
|
|
.PARAMETER Password
|
|
The password the user should have.
|
|
|
|
.PARAMETER Disabled
|
|
Specifies whether the user account should be disabled or not.
|
|
|
|
.PARAMETER PasswordNeverExpires
|
|
Specifies whether the password should ever expire or not.
|
|
|
|
.PARAMETER PasswordChangeRequired
|
|
Not used in Test-TargetResource as there is no easy way to test this value.
|
|
|
|
.PARAMETER PasswordChangeNotAllowed
|
|
Specifies whether the user should be allowed to change their password or not.
|
|
#>
|
|
function Test-TargetResource
|
|
{
|
|
[OutputType([System.Boolean])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName,
|
|
|
|
[Parameter()]
|
|
[ValidateSet('Present', 'Absent')]
|
|
[System.String]
|
|
$Ensure = 'Present',
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$FullName,
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$Description,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCredential]
|
|
[System.Management.Automation.Credential()]
|
|
$Password,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$Disabled,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordNeverExpires,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeRequired,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeNotAllowed
|
|
)
|
|
|
|
if (Test-IsNanoServer)
|
|
{
|
|
Test-TargetResourceOnNanoServer @PSBoundParameters
|
|
}
|
|
else
|
|
{
|
|
Test-TargetResourceOnFullSKU @PSBoundParameters
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Retrieves the user with the given username when on a full server
|
|
|
|
.PARAMETER UserName
|
|
The name of the user to retrieve.
|
|
#>
|
|
function Get-TargetResourceOnFullSKU
|
|
{
|
|
[OutputType([System.Collections.Hashtable])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
|
|
Assert-UserNameValid -UserName $UserName
|
|
|
|
$disposables = @()
|
|
|
|
try
|
|
{
|
|
Write-Verbose -Message 'Starting Get-TargetResource on FullSKU'
|
|
|
|
$user = Find-UserByNameOnFullSku -UserName $UserName
|
|
$disposables += $user
|
|
$valuesToReturn = @{}
|
|
|
|
if ($null -ne $user)
|
|
{
|
|
$valuesToReturn = @{
|
|
UserName = $user.Name
|
|
Ensure = 'Present'
|
|
FullName = $user.DisplayName
|
|
Description = $user.Description
|
|
Disabled = (-not $user.Enabled)
|
|
PasswordNeverExpires = $user.PasswordNeverExpires
|
|
PasswordChangeRequired = $null
|
|
PasswordChangeNotAllowed = $user.UserCannotChangePassword
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# The user is not found. Return Ensure = Absent.
|
|
$valuesToReturn = @{
|
|
UserName = $UserName
|
|
Ensure = 'Absent'
|
|
}
|
|
}
|
|
|
|
return $valuesToReturn
|
|
}
|
|
catch
|
|
{
|
|
New-InvalidOperationException -Message ($script:localizedData.MultipleMatches + $_)
|
|
}
|
|
finally
|
|
{
|
|
Remove-DisposableObject -Disposables $disposables
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Creates, modifies, or deletes a user when on a full server.
|
|
|
|
.PARAMETER UserName
|
|
The name of the user to create, modify, or delete.
|
|
|
|
.PARAMETER Ensure
|
|
Specifies whether the user should exist or not.
|
|
By default this is set to Present
|
|
|
|
.PARAMETER FullName
|
|
The (optional) full name or display name of the user.
|
|
If not provided this value will remain blank.
|
|
|
|
.PARAMETER Description
|
|
Optional description for the user.
|
|
|
|
.PARAMETER Password
|
|
The desired password for the user.
|
|
|
|
.PARAMETER Disabled
|
|
Specifies whether the user should be disabled or not.
|
|
By default this is set to $false
|
|
|
|
.PARAMETER PasswordNeverExpires
|
|
Specifies whether the password should ever expire or not.
|
|
By default this is set to $false
|
|
|
|
.PARAMETER PasswordChangeRequired
|
|
Specifies whether the user must reset their password or not.
|
|
By default this is set to $false
|
|
|
|
.PARAMETER PasswordChangeNotAllowed
|
|
Specifies whether the user is allowed to change their password or not.
|
|
By default this is set to $false
|
|
|
|
.NOTES
|
|
If Ensure is set to 'Present' then the Password parameter is required.
|
|
#>
|
|
function Set-TargetResourceOnFullSKU
|
|
{
|
|
[CmdletBinding(SupportsShouldProcess = $true)]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName,
|
|
|
|
[Parameter()]
|
|
[ValidateSet('Present', 'Absent')]
|
|
[System.String]
|
|
$Ensure = 'Present',
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$FullName,
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$Description,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCredential]
|
|
[System.Management.Automation.Credential()]
|
|
$Password,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$Disabled,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordNeverExpires,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeRequired,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeNotAllowed
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
|
|
Write-Verbose -Message ($script:localizedData.ConfigurationStarted -f $UserName)
|
|
|
|
Assert-UserNameValid -UserName $UserName
|
|
|
|
$disposables = @()
|
|
|
|
try
|
|
{
|
|
if ($Ensure -eq 'Present')
|
|
{
|
|
try
|
|
{
|
|
$user = Find-UserByNameOnFullSku -UserName $UserName
|
|
|
|
}
|
|
catch
|
|
{
|
|
$disposables += $user
|
|
New-InvalidOperationException -Message ($script:localizedData.MultipleMatches + $_)
|
|
}
|
|
|
|
$disposables += $user
|
|
|
|
$userExists = $false
|
|
$saveChanges = $false
|
|
|
|
if ($null -eq $user)
|
|
{
|
|
Write-Verbose -Message ($script:localizedData.UserWithName -f $UserName, $script:localizedData.AddOperation)
|
|
}
|
|
else
|
|
{
|
|
$userExists = $true
|
|
Write-Verbose -Message ($script:localizedData.UserWithName -f $UserName, $script:localizedData.SetOperation)
|
|
}
|
|
|
|
if (-not $userExists)
|
|
{
|
|
# The user with the provided name does not exist so add a new user
|
|
if ($PSBoundParameters.ContainsKey('Password'))
|
|
{
|
|
$user = Add-UserOnFullSku -UserName $UserName -Password $Password
|
|
}
|
|
else
|
|
{
|
|
$user = Add-UserOnFullSku -UserName $UserName
|
|
}
|
|
|
|
$saveChanges = $true
|
|
}
|
|
|
|
# Set user properties.
|
|
if ($PSBoundParameters.ContainsKey('FullName') -and ((-not $userExists) -or ($FullName -ne $user.DisplayName)))
|
|
{
|
|
$user.DisplayName = $FullName
|
|
$saveChanges = $true
|
|
}
|
|
elseif (-not $userExists)
|
|
{
|
|
<#
|
|
For a newly created user, set the DisplayName property to an empty string
|
|
since by default DisplayName is set to user's name.
|
|
#>
|
|
$user.DisplayName = [String]::Empty
|
|
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('Description') -and ((-not $userExists) -or ($Description -ne $user.Description)))
|
|
{
|
|
$user.Description = $Description
|
|
$saveChanges = $true
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('Password') -and $userExists)
|
|
{
|
|
Set-UserPasswordOnFullSku -User $user -Password $Password
|
|
$saveChanges = $true
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('Disabled') -and ((-not $userExists) -or ($Disabled -eq $user.Enabled)))
|
|
{
|
|
$user.Enabled = -not $Disabled
|
|
$saveChanges = $true
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('PasswordNeverExpires') -and ((-not $userExists) -or ($PasswordNeverExpires -ne $user.PasswordNeverExpires)))
|
|
{
|
|
$user.PasswordNeverExpires = $PasswordNeverExpires
|
|
$saveChanges = $true
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('PasswordChangeRequired') -and $PasswordChangeRequired)
|
|
{
|
|
# Expire the password which will force the user to change the password at the next logon
|
|
Revoke-UserPassword -User $user
|
|
$saveChanges = $true
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('PasswordChangeNotAllowed') -and ((-not $userExists) -or ($PasswordChangeNotAllowed -ne $user.UserCannotChangePassword)))
|
|
{
|
|
$user.UserCannotChangePassword = $PasswordChangeNotAllowed
|
|
$saveChanges = $true
|
|
|
|
}
|
|
|
|
if ($saveChanges)
|
|
{
|
|
Save-UserOnFullSku -User $user
|
|
|
|
# Send an operation success verbose message
|
|
if ($userExists)
|
|
{
|
|
Write-Verbose -Message ($script:localizedData.UserUpdated -f $UserName)
|
|
}
|
|
else
|
|
{
|
|
Write-Verbose -Message ($script:localizedData.UserCreated -f $UserName)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Write-Verbose -Message ($script:localizedData.NoConfigurationRequired -f $UserName)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Remove-UserOnFullSku -UserName $UserName
|
|
}
|
|
|
|
Write-Verbose -Message ($script:localizedData.ConfigurationCompleted -f $UserName)
|
|
}
|
|
catch
|
|
{
|
|
New-InvalidOperationException -Message $_
|
|
}
|
|
finally
|
|
{
|
|
Remove-DisposableObject -Disposables $disposables
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Tests if a user is in the desired state when on a full server.
|
|
|
|
.PARAMETER UserName
|
|
The name of the user to test the state of.
|
|
|
|
.PARAMETER Ensure
|
|
Specifies whether the user should exist or not.
|
|
By default this is set to Present
|
|
|
|
.PARAMETER FullName
|
|
The full name/display name that the user should have.
|
|
If not provided, this value will not be tested.
|
|
|
|
.PARAMETER Description
|
|
The description that the user should have.
|
|
If not provided, this value will not be tested.
|
|
|
|
.PARAMETER Password
|
|
The password the user should have.
|
|
|
|
.PARAMETER Disabled
|
|
Specifies whether the user account should be disabled or not.
|
|
|
|
.PARAMETER PasswordNeverExpires
|
|
Specifies whether the password should ever expire or not.
|
|
|
|
.PARAMETER PasswordChangeRequired
|
|
Not used in Test-TargetResource as there is no easy way to test this value.
|
|
|
|
.PARAMETER PasswordChangeNotAllowed
|
|
Specifies whether the user should be allowed to change their password or not.
|
|
#>
|
|
function Test-TargetResourceOnFullSKU
|
|
{
|
|
[OutputType([System.Boolean])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName,
|
|
|
|
[Parameter()]
|
|
[ValidateSet('Present', 'Absent')]
|
|
[System.String]
|
|
$Ensure = 'Present',
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$FullName,
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$Description,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCredential]
|
|
[System.Management.Automation.Credential()]
|
|
$Password,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$Disabled,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordNeverExpires,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeRequired,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeNotAllowed
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
|
|
Assert-UserNameValid -UserName $UserName
|
|
|
|
$disposables = @()
|
|
|
|
try
|
|
{
|
|
$user = Find-UserByNameOnFullSku -UserName $UserName
|
|
$disposables += $user
|
|
|
|
$inDesiredState = $true
|
|
|
|
if ($null -eq $user)
|
|
{
|
|
# A user with the provided name does not exist
|
|
Write-Verbose -Message ($script:localizedData.UserDoesNotExist -f $UserName)
|
|
|
|
if ($Ensure -eq 'Absent')
|
|
{
|
|
return $true
|
|
}
|
|
else
|
|
{
|
|
return $false
|
|
}
|
|
}
|
|
|
|
# A user with the provided name exists
|
|
Write-Verbose -Message ($script:localizedData.UserExists -f $UserName)
|
|
|
|
# Validate separate properties
|
|
if ($Ensure -eq 'Absent')
|
|
{
|
|
# The Ensure property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'Ensure', 'Absent', 'Present')
|
|
$inDesiredState = $false
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('FullName') -and $FullName -ne $user.DisplayName)
|
|
{
|
|
# The FullName property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'FullName', $FullName, $user.DisplayName)
|
|
$inDesiredState = $false
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('Description') -and $Description -ne $user.Description)
|
|
{
|
|
# The Description property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'Description', $Description, $user.Description)
|
|
$inDesiredState = $false
|
|
}
|
|
|
|
# Password
|
|
if ($PSBoundParameters.ContainsKey('Password'))
|
|
{
|
|
if (-not (Test-UserPasswordOnFullSku -UserName $UserName -Password $Password))
|
|
{
|
|
# The Password property does not match
|
|
Write-Verbose -Message ($script:localizedData.PasswordPropertyMismatch -f 'Password')
|
|
$inDesiredState = $false
|
|
}
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('Disabled') -and $Disabled -eq $user.Enabled)
|
|
{
|
|
# The Disabled property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'Disabled', $Disabled, $user.Enabled)
|
|
$inDesiredState = $false
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('PasswordNeverExpires') -and $PasswordNeverExpires -ne $user.PasswordNeverExpires)
|
|
{
|
|
# The PasswordNeverExpires property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'PasswordNeverExpires', $PasswordNeverExpires, $user.PasswordNeverExpires)
|
|
$inDesiredState = $false
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('PasswordChangeNotAllowed') -and $PasswordChangeNotAllowed -ne $user.UserCannotChangePassword)
|
|
{
|
|
# The PasswordChangeNotAllowed property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'PasswordChangeNotAllowed', $PasswordChangeNotAllowed, $user.UserCannotChangePassword)
|
|
$inDesiredState = $false
|
|
}
|
|
|
|
if ($inDesiredState)
|
|
{
|
|
Write-Verbose -Message ($script:localizedData.AllUserPropertiesMatch -f 'User', $UserName)
|
|
}
|
|
|
|
return $inDesiredState
|
|
}
|
|
catch
|
|
{
|
|
New-InvalidOperationException -Message ($script:localizedData.MultipleMatches + $_)
|
|
}
|
|
finally
|
|
{
|
|
Remove-DisposableObject -Disposables $disposables
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Retrieves the user with the given username when on Nano Server.
|
|
|
|
.PARAMETER UserName
|
|
The name of the user to retrieve.
|
|
#>
|
|
function Get-TargetResourceOnNanoServer
|
|
{
|
|
[OutputType([System.Collections.Hashtable])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName
|
|
)
|
|
|
|
Assert-UserNameValid -UserName $UserName
|
|
|
|
$returnValue = @{}
|
|
|
|
# Try to find a user by a name
|
|
try
|
|
{
|
|
Write-Verbose -Message 'Starting Get-TargetResource on NanoServer'
|
|
$user = Find-UserByNameOnNanoServer -UserName $UserName
|
|
|
|
# The user is found. Return all user properties and Ensure = 'Present'.
|
|
$returnValue = @{
|
|
UserName = $user.Name
|
|
Ensure = 'Present'
|
|
FullName = $user.FullName
|
|
Description = $user.Description
|
|
Disabled = -not $user.Enabled
|
|
PasswordChangeRequired = $null
|
|
PasswordChangeNotAllowed = -not $user.UserMayChangePassword
|
|
}
|
|
|
|
if ($user.PasswordExpires)
|
|
{
|
|
$returnValue.Add('PasswordNeverExpires', $false)
|
|
}
|
|
else
|
|
{
|
|
$returnValue.Add('PasswordNeverExpires', $true)
|
|
}
|
|
}
|
|
catch [System.Exception]
|
|
{
|
|
if ($_.FullyQualifiedErrorId -match 'UserNotFound')
|
|
{
|
|
# The user is not found
|
|
$returnValue = @{
|
|
UserName = $UserName
|
|
Ensure = 'Absent'
|
|
}
|
|
}
|
|
else
|
|
{
|
|
New-InvalidOperationException -ErrorRecord $_
|
|
}
|
|
}
|
|
|
|
return $returnValue
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Creates, modifies, or deletes a user when on Nano Server.
|
|
|
|
.PARAMETER UserName
|
|
The name of the user to create, modify, or delete.
|
|
|
|
.PARAMETER Ensure
|
|
Specifies whether the user should exist or not.
|
|
By default this is set to Present
|
|
|
|
.PARAMETER FullName
|
|
The (optional) full name or display name of the user.
|
|
If not provided this value will remain blank.
|
|
|
|
.PARAMETER Description
|
|
Optional description for the user.
|
|
|
|
.PARAMETER Password
|
|
The desired password for the user.
|
|
|
|
.PARAMETER Disabled
|
|
Specifies whether the user should be disabled or not.
|
|
By default this is set to $false
|
|
|
|
.PARAMETER PasswordNeverExpires
|
|
Specifies whether the password should ever expire or not.
|
|
By default this is set to $false
|
|
|
|
.PARAMETER PasswordChangeRequired
|
|
Specifies whether the user must reset their password or not.
|
|
By default this is set to $false
|
|
|
|
.PARAMETER PasswordChangeNotAllowed
|
|
Specifies whether the user is allowed to change their password or not.
|
|
By default this is set to $false
|
|
|
|
.NOTES
|
|
If Ensure is set to 'Present' then the Password parameter is required.
|
|
#>
|
|
function Set-TargetResourceOnNanoServer
|
|
{
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName,
|
|
|
|
[Parameter()]
|
|
[ValidateSet('Present', 'Absent')]
|
|
[System.String]
|
|
$Ensure = 'Present',
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$FullName,
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$Description,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCredential]
|
|
[System.Management.Automation.Credential()]
|
|
$Password,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$Disabled,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordNeverExpires,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeRequired,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeNotAllowed
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
|
|
Write-Verbose -Message ($script:localizedData.ConfigurationStarted -f $UserName)
|
|
|
|
Assert-UserNameValid -UserName $UserName
|
|
|
|
# Try to find a user by a name.
|
|
$userExists = $false
|
|
|
|
try
|
|
{
|
|
$user = Find-UserByNameOnNanoServer -UserName $UserName
|
|
$userExists = $true
|
|
}
|
|
catch [System.Exception]
|
|
{
|
|
if ($_.FullyQualifiedErrorId -match 'UserNotFound')
|
|
{
|
|
# The user is not found.
|
|
Write-Verbose -Message ($script:localizedData.UserDoesNotExist -f $UserName)
|
|
}
|
|
else
|
|
{
|
|
New-InvalidOperationException -ErrorRecord $_
|
|
}
|
|
}
|
|
|
|
if ($Ensure -eq 'Present')
|
|
{
|
|
# Ensure is set to 'Present'
|
|
|
|
if (-not $userExists)
|
|
{
|
|
# The user with the provided name does not exist so add a new user
|
|
New-LocalUser -Name $UserName -NoPassword
|
|
Write-Verbose -Message ($script:localizedData.UserCreated -f $UserName)
|
|
}
|
|
|
|
# Set user properties
|
|
if ($PSBoundParameters.ContainsKey('FullName'))
|
|
{
|
|
if (-not $userExists -or $FullName -ne $user.FullName)
|
|
{
|
|
Set-LocalUser -Name $UserName -FullName $FullName
|
|
}
|
|
}
|
|
elseif (-not $userExists)
|
|
{
|
|
# For a newly created user, set the DisplayName property to an empty string since by default DisplayName is set to user's name.
|
|
Set-LocalUser -Name $UserName -FullName ([String]::Empty)
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('Description') -and ((-not $userExists) -or ($Description -ne $user.Description)))
|
|
{
|
|
Set-LocalUser -Name $UserName -Description $Description
|
|
}
|
|
|
|
# Set the password regardless of the state of the user
|
|
if ($PSBoundParameters.ContainsKey('Password'))
|
|
{
|
|
Set-LocalUser -Name $UserName -Password $Password.Password
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('Disabled') -and ((-not $userExists) -or ($Disabled -eq $user.Enabled)))
|
|
{
|
|
if ($Disabled)
|
|
{
|
|
Disable-LocalUser -Name $UserName
|
|
}
|
|
else
|
|
{
|
|
Enable-LocalUser -Name $UserName
|
|
}
|
|
}
|
|
|
|
$existingUserPasswordNeverExpires = (($userExists) -and ($null -eq $user.PasswordExpires))
|
|
if ($PSBoundParameters.ContainsKey('PasswordNeverExpires') -and ((-not $userExists) -or ($PasswordNeverExpires -ne $existingUserPasswordNeverExpires)))
|
|
{
|
|
Set-LocalUser -Name $UserName -PasswordNeverExpires:$passwordNeverExpires
|
|
}
|
|
|
|
# Only set the AccountExpires attribute if PasswordChangeRequired is set to true
|
|
if ($PSBoundParameters.ContainsKey('PasswordChangeRequired') -and ($PasswordChangeRequired))
|
|
{
|
|
Set-LocalUser -Name $UserName -AccountExpires ([DateTime]::Now)
|
|
}
|
|
|
|
# NOTE: The parameter name and the property name have opposite meaning.
|
|
$expected = (-not $PasswordChangeNotAllowed)
|
|
$actual = $expected
|
|
|
|
if ($userExists)
|
|
{
|
|
$actual = $user.UserMayChangePassword
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('PasswordChangeNotAllowed') -and ((-not $userExists) -or ($expected -ne $actual)))
|
|
{
|
|
Set-LocalUser -Name $UserName -UserMayChangePassword $expected
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Ensure is set to 'Absent'
|
|
if ($userExists)
|
|
{
|
|
# The user exists
|
|
Remove-LocalUser -Name $UserName
|
|
|
|
Write-Verbose -Message ($script:localizedData.UserRemoved -f $UserName)
|
|
}
|
|
else
|
|
{
|
|
Write-Verbose -Message ($script:localizedData.NoConfigurationRequiredUserDoesNotExist -f $UserName)
|
|
}
|
|
}
|
|
|
|
Write-Verbose -Message ($script:localizedData.ConfigurationCompleted -f $UserName)
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Tests if a user is in the desired state when on Nano Server.
|
|
|
|
.PARAMETER UserName
|
|
The name of the user to test the state of.
|
|
|
|
.PARAMETER Ensure
|
|
Specifies whether the user should exist or not.
|
|
By default this is set to Present
|
|
|
|
.PARAMETER FullName
|
|
The full name/display name that the user should have.
|
|
If not provided, this value will not be tested.
|
|
|
|
.PARAMETER Description
|
|
The description that the user should have.
|
|
If not provided, this value will not be tested.
|
|
|
|
.PARAMETER Password
|
|
The password the user should have.
|
|
|
|
.PARAMETER Disabled
|
|
Specifies whether the user account should be disabled or not.
|
|
|
|
.PARAMETER PasswordNeverExpires
|
|
Specifies whether the password should ever expire or not.
|
|
|
|
.PARAMETER PasswordChangeRequired
|
|
Not used in Test-TargetResource as there is no easy way to test this value.
|
|
|
|
.PARAMETER PasswordChangeNotAllowed
|
|
Specifies whether the user should be allowed to change their password or not.
|
|
#>
|
|
function Test-TargetResourceOnNanoServer
|
|
{
|
|
[OutputType([System.Boolean])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName,
|
|
|
|
[Parameter()]
|
|
[ValidateSet('Present', 'Absent')]
|
|
[System.String]
|
|
$Ensure = 'Present',
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$FullName,
|
|
|
|
[Parameter()]
|
|
[System.String]
|
|
$Description,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCredential]
|
|
[System.Management.Automation.Credential()]
|
|
$Password,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$Disabled,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordNeverExpires,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeRequired,
|
|
|
|
[Parameter()]
|
|
[System.Boolean]
|
|
$PasswordChangeNotAllowed
|
|
)
|
|
|
|
Assert-UserNameValid -UserName $UserName
|
|
|
|
# Try to find a user by a name
|
|
try
|
|
{
|
|
$user = Find-UserByNameOnNanoServer -UserName $UserName
|
|
}
|
|
catch [System.Exception]
|
|
{
|
|
if ($_.FullyQualifiedErrorId -match 'UserNotFound')
|
|
{
|
|
# The user is not found
|
|
return ($Ensure -eq 'Absent')
|
|
}
|
|
else
|
|
{
|
|
New-InvalidOperationException -ErrorRecord $_
|
|
}
|
|
}
|
|
|
|
# A user with the provided name exists
|
|
Write-Verbose -Message ($script:localizedData.UserExists -f $UserName)
|
|
|
|
# Validate separate properties
|
|
if ($Ensure -eq 'Absent')
|
|
{
|
|
# The Ensure property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'Ensure', 'Absent', 'Present')
|
|
return $false
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('FullName') -and $FullName -ne $user.FullName)
|
|
{
|
|
# The FullName property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'FullName', $FullName, $user.FullName)
|
|
return $false
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('Description') -and $Description -ne $user.Description)
|
|
{
|
|
# The Description property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'Description', $Description, $user.Description)
|
|
return $false
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('Password'))
|
|
{
|
|
if(-not (Test-CredentialsValidOnNanoServer -UserName $UserName -Password $Password.Password))
|
|
{
|
|
# The Password property does not match
|
|
Write-Verbose -Message ($script:localizedData.PasswordPropertyMismatch -f 'Password')
|
|
return $false
|
|
}
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('Disabled') -and ($Disabled -eq $user.Enabled))
|
|
{
|
|
# The Disabled property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'Disabled', $Disabled, $user.Enabled)
|
|
return $false
|
|
}
|
|
|
|
$existingUserPasswordNeverExpires = ($null -eq $user.PasswordExpires)
|
|
if ($PSBoundParameters.ContainsKey('PasswordNeverExpires') -and $PasswordNeverExpires -ne $existingUserPasswordNeverExpires)
|
|
{
|
|
# The PasswordNeverExpires property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'PasswordNeverExpires', $PasswordNeverExpires, $existingUserPasswordNeverExpires)
|
|
return $false
|
|
}
|
|
|
|
if ($PSBoundParameters.ContainsKey('PasswordChangeNotAllowed') -and $PasswordChangeNotAllowed -ne (-not $user.UserMayChangePassword))
|
|
{
|
|
# The PasswordChangeNotAllowed property does not match
|
|
Write-Verbose -Message ($script:localizedData.PropertyMismatch -f 'PasswordChangeNotAllowed', $PasswordChangeNotAllowed, (-not $user.UserMayChangePassword))
|
|
return $false
|
|
}
|
|
|
|
# All properties match. Return $true.
|
|
Write-Verbose -Message ($script:localizedData.AllUserPropertiesMatch -f 'User', $UserName)
|
|
return $true
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Checks that the username does not contain invalid characters.
|
|
|
|
.PARAMETER UserName
|
|
The username to validate.
|
|
#>
|
|
function Assert-UserNameValid
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName
|
|
)
|
|
|
|
# Check if the name consists of only periods and/or white spaces
|
|
$wrongName = $true
|
|
|
|
for ($i = 0; $i -lt $UserName.Length; $i++)
|
|
{
|
|
if (-not [System.Char]::IsWhiteSpace($UserName, $i) -and $UserName[$i] -ne '.')
|
|
{
|
|
$wrongName = $false
|
|
break
|
|
}
|
|
}
|
|
|
|
$invalidChars = @('\', '/', '"', '[', ']', ':', '|', '<', '>', '+', '=', ';', ',', '?', '*', '@')
|
|
|
|
if ($wrongName)
|
|
{
|
|
New-InvalidArgumentException `
|
|
-Message ($script:localizedData.InvalidUserName -f $UserName, [System.String]::Join(' ', $invalidChars)) `
|
|
-ArgumentName 'UserName'
|
|
}
|
|
|
|
if ($UserName.IndexOfAny($invalidChars) -ne -1)
|
|
{
|
|
New-InvalidArgumentException `
|
|
-Message ($script:localizedData.InvalidUserName -f $UserName, [System.String]::Join(' ', $invalidChars)) `
|
|
-ArgumentName 'UserName'
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Tests the local user's credentials on the local machine.
|
|
|
|
.PARAMETER UserName
|
|
The username to validate the credentials of.
|
|
|
|
.PARAMETER Password
|
|
The password of the given user.
|
|
#>
|
|
function Test-CredentialsValidOnNanoServer
|
|
{
|
|
[OutputType([System.Boolean])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.String]
|
|
$UserName,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Security.SecureString]
|
|
$Password
|
|
)
|
|
|
|
$source = @'
|
|
[Flags]
|
|
private enum LogonType
|
|
{
|
|
Logon32LogonInteractive = 2,
|
|
Logon32LogonNetwork,
|
|
Logon32LogonBatch,
|
|
Logon32LogonService,
|
|
Logon32LogonUnlock,
|
|
Logon32LogonNetworkCleartext,
|
|
Logon32LogonNewCredentials
|
|
}
|
|
|
|
[Flags]
|
|
private enum LogonProvider
|
|
{
|
|
Logon32ProviderDefault = 0,
|
|
Logon32ProviderWinnt35,
|
|
Logon32ProviderWinnt40,
|
|
Logon32ProviderWinnt50
|
|
}
|
|
|
|
[DllImport("api-ms-win-security-logon-l1-1-1.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
private static extern Boolean LogonUser(
|
|
String lpszUserName,
|
|
String lpszDomain,
|
|
IntPtr lpszPassword,
|
|
LogonType dwLogonType,
|
|
LogonProvider dwLogonProvider,
|
|
out IntPtr phToken
|
|
);
|
|
|
|
|
|
[DllImport("api-ms-win-core-handle-l1-1-0.dll",
|
|
EntryPoint = "CloseHandle", SetLastError = true,
|
|
CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
|
internal static extern bool CloseHandle(IntPtr handle);
|
|
|
|
public static bool ValidateCredentials(string username, SecureString password)
|
|
{
|
|
IntPtr tokenHandle = IntPtr.Zero;
|
|
IntPtr unmanagedPassword = IntPtr.Zero;
|
|
|
|
unmanagedPassword = SecureStringMarshal.SecureStringToCoTaskMemUnicode(password);
|
|
|
|
try
|
|
{
|
|
return LogonUser(
|
|
username,
|
|
null,
|
|
unmanagedPassword,
|
|
LogonType.Logon32LogonInteractive,
|
|
LogonProvider.Logon32ProviderDefault,
|
|
out tokenHandle);
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
finally
|
|
{
|
|
if (tokenHandle != IntPtr.Zero)
|
|
{
|
|
CloseHandle(tokenHandle);
|
|
}
|
|
if (unmanagedPassword != IntPtr.Zero) {
|
|
Marshal.ZeroFreeCoTaskMemUnicode(unmanagedPassword);
|
|
}
|
|
unmanagedPassword = IntPtr.Zero;
|
|
}
|
|
}
|
|
'@
|
|
|
|
Add-Type -PassThru -Namespace Microsoft.Windows.DesiredStateConfiguration.NanoServer.UserResource `
|
|
-Name CredentialsValidationTool -MemberDefinition $source -Using System.Security -ReferencedAssemblies System.Security.SecureString.dll | Out-Null
|
|
return [Microsoft.Windows.DesiredStateConfiguration.NanoServer.UserResource.CredentialsValidationTool]::ValidateCredentials($UserName, $Password)
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Queries a user by the given username. If found the function returns a UserPrincipal object.
|
|
Otherwise, the function returns $null.
|
|
|
|
.PARAMETER UserName
|
|
The username to search for.
|
|
#>
|
|
function Find-UserByNameOnFullSku
|
|
{
|
|
[OutputType([System.DirectoryServices.AccountManagement.UserPrincipal])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$UserName
|
|
)
|
|
|
|
$principalContext = New-Object `
|
|
-TypeName System.DirectoryServices.AccountManagement.PrincipalContext `
|
|
-ArgumentList ([System.DirectoryServices.AccountManagement.ContextType]::Machine)
|
|
|
|
$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($principalContext, $UserName)
|
|
|
|
return $user
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Adds a user with the given username and returns the new user object
|
|
|
|
.PARAMETER UserName
|
|
The username for the new user
|
|
#>
|
|
function Add-UserOnFullSku
|
|
{
|
|
[OutputType([System.DirectoryServices.AccountManagement.UserPrincipal])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$UserName,
|
|
|
|
[Parameter()]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCredential]
|
|
[System.Management.Automation.Credential()]
|
|
$Password
|
|
)
|
|
|
|
$principalContext = New-Object `
|
|
-TypeName 'System.DirectoryServices.AccountManagement.PrincipalContext' `
|
|
-ArgumentList @( [System.DirectoryServices.AccountManagement.ContextType]::Machine )
|
|
|
|
$user = New-Object -TypeName 'System.DirectoryServices.AccountManagement.UserPrincipal' `
|
|
-ArgumentList @( $principalContext )
|
|
$user.Name = $UserName
|
|
|
|
if ($PSBoundParameters.ContainsKey('Password'))
|
|
{
|
|
$user.SetPassword($Password.GetNetworkCredential().Password)
|
|
}
|
|
|
|
return $user
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Sets the password for the given user
|
|
|
|
.PARAMETER User
|
|
The user to set the password for
|
|
|
|
.PARAMETER Password
|
|
The credential to use for the user's password
|
|
#>
|
|
function Set-UserPasswordOnFullSku
|
|
{
|
|
[OutputType([System.DirectoryServices.AccountManagement.UserPrincipal])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.DirectoryServices.AccountManagement.UserPrincipal]
|
|
$User,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCredential]
|
|
[System.Management.Automation.Credential()]
|
|
$Password
|
|
)
|
|
|
|
$User.SetPassword($Password.GetNetworkCredential().Password)
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Validates the password is correct for the given user. Returns $true if the
|
|
Password is correct for the given username, false otherwise.
|
|
|
|
.PARAMETER UserName
|
|
The UserName to check
|
|
|
|
.PARAMETER Password
|
|
The credential to check
|
|
#>
|
|
function Test-UserPasswordOnFullSku
|
|
{
|
|
[OutputType([Boolean])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$UserName,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.Management.Automation.PSCredential]
|
|
[System.Management.Automation.Credential()]
|
|
$Password
|
|
)
|
|
|
|
$principalContext = New-Object `
|
|
-TypeName 'System.DirectoryServices.AccountManagement.PrincipalContext' `
|
|
-ArgumentList @( [System.DirectoryServices.AccountManagement.ContextType]::Machine )
|
|
try
|
|
{
|
|
$credentailsValid = $principalContext.ValidateCredentials($UserName, $Password.GetNetworkCredential().Password)
|
|
return $credentailsValid
|
|
}
|
|
finally
|
|
{
|
|
$principalContext.Dispose()
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Queries a user by the given username. If found the function returns a UserPrincipal object.
|
|
Otherwise, the function returns $null.
|
|
|
|
.PARAMETER UserName
|
|
The username to search for.
|
|
#>
|
|
function Remove-UserOnFullSku
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$UserName
|
|
)
|
|
|
|
$user = Find-UserByNameOnFullSku -Username $UserName
|
|
|
|
if ($null -ne $user)
|
|
{
|
|
try
|
|
{
|
|
Write-Verbose -Message ($script:localizedData.UserWithName -f $UserName, $script:localizedData.RemoveOperation)
|
|
$user.Delete()
|
|
Write-Verbose -Message ($script:localizedData.UserRemoved -f $UserName)
|
|
}
|
|
finally
|
|
{
|
|
$user.Dispose()
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Write-Verbose -Message ($script:localizedData.NoConfigurationRequiredUserDoesNotExist -f $UserName)
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Saves changes for the given user on a machine.
|
|
|
|
.PARAMETER User
|
|
The user to save the changes of
|
|
#>
|
|
function Save-UserOnFullSku
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.DirectoryServices.AccountManagement.UserPrincipal]
|
|
$User
|
|
)
|
|
|
|
$User.Save()
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Expires the password of the given user.
|
|
|
|
.PARAMETER User
|
|
The user to expire the password of.
|
|
#>
|
|
function Revoke-UserPassword
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[System.DirectoryServices.AccountManagement.UserPrincipal]
|
|
$User
|
|
)
|
|
|
|
$User.ExpirePasswordNow()
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Queries a user by the given username. If found the function returns a LocalUser object.
|
|
Otherwise, the function throws an error that the user was not found.
|
|
|
|
.PARAMETER UserName
|
|
The username to search for.
|
|
#>
|
|
function Find-UserByNameOnNanoServer
|
|
{
|
|
#[OutputType([Microsoft.PowerShell.Commands.LocalUser])]
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[String]
|
|
$UserName
|
|
)
|
|
|
|
return Get-LocalUser -Name $UserName -ErrorAction Stop
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Disposes of the contents of an array list containing IDisposable objects.
|
|
|
|
.PARAMETER Disosables
|
|
The array list of IDisposable Objects to dispose of.
|
|
#>
|
|
function Remove-DisposableObject
|
|
{
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter()]
|
|
[System.Collections.ArrayList]
|
|
[AllowEmptyCollection()]
|
|
$Disposables
|
|
)
|
|
|
|
if ($null -ne $Disposables)
|
|
{
|
|
foreach ($disposable in $Disposables)
|
|
{
|
|
if ($disposable -is [System.IDisposable])
|
|
{
|
|
$disposable.Dispose()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Export-ModuleMember -Function *-TargetResource
|