adding in all group changes

This commit is contained in:
Mariah Breakey
2016-12-15 16:04:17 -08:00
parent a5729ec92a
commit 9b335c1e75
12 changed files with 691 additions and 760 deletions
+3 -3
View File
@@ -105,9 +105,9 @@ function New-InvalidOperationException
.PARAMETER ResourceName
The name of the resource as it appears before '.strings.psd1' of the localized string file.
For example:
WindowsOptionalFeature: MSFT_WindowsOptionalFeature
Service: MSFT_ServiceResource
Registry: MSFT_RegistryResource
For WindowsOptionalFeature: MSFT_WindowsOptionalFeature
For Service: MSFT_ServiceResource
For Registry: MSFT_RegistryResource
#>
function Get-LocalizedData
{
@@ -60,6 +60,7 @@
with the associated SID of the member that cannot be resolved then continues the operation.
#>
$errorActionPreference = 'Stop'
Set-StrictMode -Version 'Latest'
Import-Module -Name (Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) `
-36
View File
@@ -1,36 +0,0 @@
<#
.SYNOPSIS
Creates a group with the specified name and members or modifies the members of a group if
the named group already exists.
.PARAMETER GroupName
The name of the group to create or modify.
.PARAMETER Members
The list of members the group should have.
The default value is an empty list which will remove all members from the group.
#>
Configuration Sample_Group
{
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$GroupName,
[String[]]
$Members = @()
)
Import-DscResource -ModuleName 'PSDscResources'
Group Group1
{
GroupName = $GroupName
Ensure = 'Present'
Members = $Members
}
}
Sample_Group
@@ -1,44 +0,0 @@
<#
.SYNOPSIS
Creates a group with the specified name and members included or modifies the members of a group if
the named group already exists.
.PARAMETER GroupName
The name of the group to create or modify.
.PARAMETER MembersToInclude
The list of members the group should contain.
The default value is an empty list.
.PARAMETER MembersToExclude
The list of members the group should not contain.
The default value is an empty list.
#>
Configuration Sample_Group
{
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$GroupName,
[String[]]
$MembersToInclude = @(),
[String[]]
$MembersToExclude = @()
)
Import-DscResource -ModuleName 'PSDscResources'
Group Group1
{
GroupName = $GroupName
Ensure = 'Present'
MembersToInclude = $MembersToInclude
MembersToExclude = $MembersToExclude
}
}
Sample_Group
+21
View File
@@ -0,0 +1,21 @@
<#
.SYNOPSIS
If the group named GroupName1 does not exist, creates a group named GroupName1.
If the group named GroupName1 already exists removes the users that have the usernames
Username1 or Username2 from the group.
#>
Configuration Sample_Group_RemoveMembers
{
[CmdletBinding()]
param ()
Import-DscResource -ModuleName 'PSDscResources'
Group Group1
{
GroupName = 'GroupName1'
Ensure = 'Present'
MembersToExclude = @( 'Username1', 'Username2' )
}
}
+23
View File
@@ -0,0 +1,23 @@
<#
.SYNOPSIS
If the group named GroupName1 does not exist, creates a group named GroupName1 and adds the
users with the usernames Username1 and Username2 to the group.
If the group named GroupName1 already exists, removes any users that do not have the
usernames Username1 or Username2 from the group and adds the users that have the usernames
Username1 and Username2 to the group.
#>
Configuration Sample_Group_SetMembers
{
[CmdletBinding()]
param ()
Import-DscResource -ModuleName 'PSDscResources'
Group Group1
{
GroupName = 'GroupName1'
Ensure = 'Present'
Members = @( 'Username1', 'Username2' )
}
}
+7 -5
View File
@@ -267,15 +267,17 @@ None
* Updated unit tests.
* Added WindowsProcess
* CommonTestHelper:
* Added Get-AppVeyorAdministratorCredential
* Added Set-StrictMode -'Latest' and $errorActionPreference -'Stop'
* Added Get-AppVeyorAdministratorCredential.
* Added Set-StrictMode -'Latest' and $errorActionPreference -'Stop'.
* Service:
* Updated resource module, tests, and examples to reflect the changes made in xPSDesiredStateConfiguration
* Updated resource module, unit tests, integration tests, and examples to reflect the changes made in xPSDesiredStateConfiguration.
* Group:
* Updated resource module, examples, and integration tests to reflect the changes made in xPSDesiredStateConfiguration.
### 2.1.0.0
* Added WindowsFeature
* Added WindowsFeature.
### 2.0.0.0
* Initial release of PSDscResources
* Initial release of PSDscResources.
@@ -1,6 +1,9 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]
param ()
$errorActionPreference = 'Stop'
Set-StrictMode -Version 'Latest'
if ($PSVersionTable.PSVersion.Major -lt 5 -or $PSVersionTable.PSVersion.Minor -lt 1)
{
Write-Warning -Message 'Cannot run PSDscResources integration tests on PowerShell versions lower than 5.1'
@@ -28,6 +31,27 @@ try
-ChildPath 'MSFT_GroupResource_Members.config.ps1'
$script:confgurationWithMembersToIncludeExcludeFilePath = Join-Path -Path $PSScriptRoot `
-ChildPath 'MSFT_GroupResource_MembersToIncludeExclude.config.ps1'
# Fake users for testing
$testUsername1 = 'TestUser1'
$testUsername2 = 'TestUser2'
$testUsernames = @( $testUsername1, $testUsername2 )
$testPassword = 'T3stPassw0rd#'
$secureTestPassword = ConvertTo-SecureString -String $testPassword -AsPlainText -Force
foreach ($username in $testUsernames)
{
$testUserCredential = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( $username, $secureTestPassword )
$null = New-User -Credential $testUserCredential
}
}
AfterAll {
foreach ($username in $testUsernames)
{
Remove-User -UserName $username
}
}
It 'Should use Group from PSDscResources' {
@@ -63,7 +87,7 @@ try
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
Test-GroupExists -GroupName $testGroupName | Should Be $true
Test-GroupExists -GroupName $testGroupName -Members @() | Should Be $true
}
finally
{
@@ -78,22 +102,12 @@ try
$configurationName = 'CreateGroupWithTwoMembers'
$testGroupName = 'TestGroupWithMembers2'
$username1 = 'TestUser1'
$username2 = 'TestUser2'
$testPassword = 'T3stPassw0rd#'
$secureTestPassword = ConvertTo-SecureString -String $testPassword -AsPlainText -Force
$testUserCredential1 = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( $username1, $secureTestPassword )
$testUserCredential2 = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( $username2, $secureTestPassword )
$user1 = New-User -Credential $testUserCredential1
$user2 = New-User -Credential $testUserCredential2
$groupMembers = $testUsernames
$resourceParameters = @{
Ensure = 'Present'
GroupName = $testGroupName
Members = @( $username1, $username2 )
Members = $groupMembers
}
Test-GroupExists -GroupName $testGroupName | Should Be $false
@@ -106,7 +120,7 @@ try
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
Test-GroupExists -GroupName $testGroupName | Should Be $true
Test-GroupExists -GroupName $testGroupName -Members $groupMembers | Should Be $true
}
finally
{
@@ -114,9 +128,6 @@ try
{
Remove-Group -GroupName $testGroupName
}
Remove-User -UserName $username1
Remove-User -UserName $username2
}
}
@@ -124,19 +135,12 @@ try
$configurationName = 'CreateGroupWithTwoMembers'
$testGroupName = 'TestGroupWithMembersToInclude3'
$username1 = 'TestUser1'
$testPassword = 'T3stPassw0rd#'
$secureTestPassword = ConvertTo-SecureString -String $testPassword -AsPlainText -Force
$testUserCredential1 = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( $username1, $secureTestPassword )
$user1 = New-User -Credential $testUserCredential1
$groupMembers = @( $testUsername1 )
$resourceParameters = @{
Ensure = 'Present'
GroupName = $testGroupName
MembersToInclude = @( $username1 )
MembersToInclude = $groupMembers
}
Test-GroupExists -GroupName $testGroupName | Should Be $false
@@ -153,7 +157,7 @@ try
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
Test-GroupExists -GroupName $testGroupName | Should Be $true
Test-GroupExists -GroupName $testGroupName -MembersToInclude $groupMembers | Should Be $true
}
finally
{
@@ -161,8 +165,6 @@ try
{
Remove-Group -GroupName $testGroupName
}
Remove-User -UserName $username1
}
}
@@ -170,24 +172,17 @@ try
$configurationName = 'CreateGroupWithTwoMembers'
$testGroupName = 'TestGroupWithMembersToInclude3'
$username1 = 'TestUser1'
$testPassword = 'T3stPassw0rd#'
$secureTestPassword = ConvertTo-SecureString -String $testPassword -AsPlainText -Force
$testUserCredential1 = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( $username1, $secureTestPassword )
$user1 = New-User -Credential $testUserCredential1
$groupMembersToExclude = @( $testUsername1 )
$resourceParameters = @{
Ensure = 'Present'
GroupName = $testGroupName
MembersToExclude = @( $username1 )
MembersToExclude = $groupMembersToExclude
}
Test-GroupExists -GroupName $testGroupName | Should Be $false
New-Group -GroupName $testGroupName -MemberUserNames @( $username1 )
New-Group -GroupName $testGroupName -Members $groupMembersToExclude
Test-GroupExists -GroupName $testGroupName | Should Be $true
@@ -199,7 +194,7 @@ try
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
Test-GroupExists -GroupName $testGroupName | Should Be $true
Test-GroupExists -GroupName $testGroupName -MembersToExclude $groupMembersToExclude | Should Be $true
}
finally
{
@@ -207,8 +202,40 @@ try
{
Remove-Group -GroupName $testGroupName
}
}
}
Remove-User -UserName $username1
It 'Should remove a group' {
$configurationName = 'RemoveGroup'
$testGroupName = 'TestRemoveGroup1'
$resourceParameters = @{
Ensure = 'Absent'
GroupName = $testGroupName
}
Test-GroupExists -GroupName $testGroupName | Should Be $false
New-Group -GroupName $testGroupName
Test-GroupExists -GroupName $testGroupName | Should Be $true
try
{
{
. $script:confgurationWithMembersFilePath -ConfigurationName $configurationName
& $configurationName -OutputPath $TestDrive @resourceParameters
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
Test-GroupExists -GroupName $testGroupName | Should Be $false
}
finally
{
if (Test-GroupExists -GroupName $testGroupName)
{
Remove-Group -GroupName $testGroupName
}
}
}
}
-406
View File
@@ -106,409 +106,6 @@ function Test-IsLocalMachine
return $false
}
<#
.SYNOPSIS
Creates a user account.
.DESCRIPTION
This function creates a user on the local or remote machine.
.PARAMETER Credential
The credential containing the username and password to use to create the account.
.PARAMETER Description
The optional description to set on the user account.
.PARAMETER ComputerName
The optional name of the computer to update. Omit to create a user on the local machine.
.NOTES
For remote machines, the currently logged on user must have rights to create a user.
#>
function New-User
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential,
[String]
$Description,
[String]
$ComputerName = $env:COMPUTERNAME
)
if (Test-IsNanoServer)
{
New-UserOnNanoServer @PSBoundParameters
}
else
{
New-UserOnFullSKU @PSBoundParameters
}
}
<#
.SYNOPSIS
Creates a user account on a full server.
.DESCRIPTION
This function creates a user on the local or remote machine running a full server.
.PARAMETER Credential
The credential containing the username and password to use to create the account.
.PARAMETER Description
The optional description to set on the user account.
.PARAMETER ComputerName
The optional name of the computer to update. Omit to create a user on the local machine.
.NOTES
For remote machines, the currently logged on user must have rights to create a user.
#>
function New-UserOnFullSKU
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential,
[String]
$Description,
[String]
$ComputerName = $env:COMPUTERNAME
)
Set-StrictMode -Version Latest
$userName = $Credential.UserName
$password = $Credential.GetNetworkCredential().Password
# Remove user if it already exists.
Remove-User $userName $ComputerName
$adComputerEntry = [ADSI] "WinNT://$ComputerName"
$adUserEntry = $adComputerEntry.Create('User', $userName)
$null = $adUserEntry.SetPassword($password)
if ($PSBoundParameters.ContainsKey('Description'))
{
$null = $adUserEntry.Put('Description', $Description)
}
$null = $adUserEntry.SetInfo()
}
<#
.SYNOPSIS
Creates a user account on a Nano server.
.DESCRIPTION
This function creates a user on the local machine running a Nano server.
.PARAMETER Credential
The credential containing the username and password to use to create the account.
.PARAMETER Description
The optional description to set on the user account.
.PARAMETER ComputerName
This parameter should not be used on NanoServer.
#>
function New-UserOnNanoServer
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential,
[String]
$Description,
[String]
$ComputerName = $env:COMPUTERNAME
)
Set-StrictMode -Version Latest
if ($PSBoundParameters.ContainsKey('ComputerName'))
{
if (-not (Test-IsLocalMachine -Scope $ComputerName))
{
throw 'Do not specify the ComputerName arguments when running on NanoServer unless it is a local machine.'
}
}
$userName = $Credential.UserName
$securePassword = $Credential.GetNetworkCredential().SecurePassword
# Remove user if it already exists.
Remove-LocalUser -Name $userName -ErrorAction SilentlyContinue
New-LocalUser -Name $userName -Password $securePassword
if ($PSBoundParameters.ContainsKey('Description'))
{
Set-LocalUser -Name $userName -Description $Description
}
}
<#
.SYNOPSIS
Removes a user account.
.DESCRIPTION
This function removes a local user from the local or remote machine.
.PARAMETER UserName
The name of the user to remove.
.PARAMETER ComputerName
The optional name of the computer to update. Omit to remove the user on the local machine.
.NOTES
For remote machines, the currently logged on user must have rights to remove a user.
#>
function Remove-User
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$UserName,
[String]
$ComputerName = $env:COMPUTERNAME
)
if (Test-IsNanoServer)
{
Remove-UserOnNanoServer @PSBoundParameters
}
else
{
Remove-UserOnFullSKU @PSBoundParameters
}
}
<#
.SYNOPSIS
Removes a user account on a full server.
.DESCRIPTION
This function removes a local user from the local or remote machine running a full server.
.PARAMETER UserName
The name of the user to remove.
.PARAMETER ComputerName
The optional name of the computer to update. Omit to remove the user on the local machine.
.NOTES
For remote machines, the currently logged on user must have rights to remove a user.
#>
function Remove-UserOnFullSKU
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$UserName,
[String]
$ComputerName = $env:COMPUTERNAME
)
Set-StrictMode -Version Latest
$adComputerEntry = [ADSI] "WinNT://$ComputerName"
if ($adComputerEntry.Children | Where-Object Path -like "WinNT://*$ComputerName/$UserName")
{
$null = $adComputerEntry.Delete('user', $UserName)
}
}
<#
.SYNOPSIS
Removes a local user account on a Nano server.
.DESCRIPTION
This function removes a local user from the local machine running a Nano Server.
.PARAMETER UserName
The name of the user to remove.
.PARAMETER ComputerName
This parameter should not be used on NanoServer.
#>
function Remove-UserOnNanoServer
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$UserName,
[String]
$ComputerName = $env:COMPUTERNAME
)
Set-StrictMode -Version Latest
if ($PSBoundParameters.ContainsKey('ComputerName'))
{
if (-not (Test-IsLocalMachine -Scope $ComputerName))
{
throw 'Do not specify the ComputerName arguments when running on NanoServer unless it is a local machine.'
}
}
Remove-LocalUser -Name $UserName
}
<#
.SYNOPSIS
Determines if a user exists.
.DESCRIPTION
This function determines if a user exists on a local or remote machine.
.PARAMETER UserName
The name of the user to test.
.PARAMETER ComputerName
The optional name of the computer to update.
#>
function Test-User
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$UserName,
[String]
$ComputerName = $env:COMPUTERNAME
)
if (Test-IsNanoServer)
{
Test-UserOnNanoServer @PSBoundParameters
}
else
{
Test-UserOnFullSKU @PSBoundParameters
}
}
<#
.SYNOPSIS
Determines if a user exists on a full server.
.DESCRIPTION
This function determines if a user exists on a local or remote machine running a full server.
.PARAMETER UserName
The name of the user to test.
.PARAMETER ComputerName
The optional name of the computer to update.
#>
function Test-UserOnFullSKU
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$UserName,
[String]
$ComputerName = $env:COMPUTERNAME
)
Set-StrictMode -Version Latest
$adComputerEntry = [ADSI] "WinNT://$ComputerName"
if ($adComputerEntry.Children | Where-Object Path -like "WinNT://*$ComputerName/$UserName")
{
return $true
}
return $false
}
<#
.SYNOPSIS
Determines if a user exists on a Nano server.
.DESCRIPTION
This function determines if a user exists on a local or remote machine running a Nano server.
.PARAMETER UserName
The name of the user to test.
.PARAMETER ComputerName
This parameter should not be used on NanoServer.
#>
function Test-UserOnNanoServer
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$UserName,
[String]
$ComputerName = $env:COMPUTERNAME
)
if ($PSBoundParameters.ContainsKey('ComputerName'))
{
if (-not (Test-IsLocalMachine -Scope $ComputerName))
{
throw 'Do not specify the ComputerName arguments when running on NanoServer unless it is a local machine.'
}
}
# Try to find a user by name.
try
{
$null = Get-LocalUser -Name $UserName -ErrorAction Stop
return $true
}
catch [System.Exception]
{
if ($_.CategoryInfo.ToString().Contains('UserNotFoundException'))
{
# A user with the provided name does not exist.
return $false
}
throw $_.Exception
}
return $false
}
<#
.SYNOPSIS
Waits a certain amount of time for a script block to return true.
@@ -815,9 +412,6 @@ function Exit-DscResourceTestEnvironment
Export-ModuleMember -Function @(
'Test-GetTargetResourceResult', `
'New-User', `
'Remove-User', `
'Test-User', `
'Wait-ScriptBlockReturnTrue', `
'Test-IsFileLocked', `
'Test-SetTargetResourceWithWhatIf', `
@@ -1,21 +1,28 @@
Import-Module -Name (Join-Path -Path (Join-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -ChildPath 'DSCResources') -ChildPath 'CommonResourceHelper.psm1')
$errorActionPreference = 'Stop'
Set-StrictMode -Version 'Latest'
#Import CommonResourceHelper for Test-IsNanoServer
$moduleRootFilePath = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent
$dscResourcesFolderFilePath = Join-Path -Path $moduleRootFilePath -ChildPath 'DSCResources'
$commonResourceHelperFilePath = Join-Path -Path $dscResourcesFolderFilePath -ChildPath 'CommonResourceHelper.psm1'
Import-Module -Name $commonResourceHelperFilePath
<#
.SYNOPSIS
Determines if a Windows group exists.
.DESCRIPTION
This function determines if a Windows group exists on a local or remote machine.
Tests if a Windows group with the given name and members exists.
.PARAMETER GroupName
The name of the group to test.
The name of the group.
.PARAMETER ComputerName
The optional name of the computer to check.
The default value is the local machine.
.PARAMETER Members
The usernames of the members of the group.
.NOTES
For remote machines, the currently logged on user must have rights to enumerate groups.
.PARAMETER MembersToInclude
The usernames of the members that should be included in the group.
.PARAMETER MembersToExclude
The usernames of the members that should be excluded from the group.
#>
function Test-GroupExists
{
@@ -27,9 +34,17 @@ function Test-GroupExists
[String]
$GroupName,
[ValidateNotNullOrEmpty()]
[String]
$ComputerName = $env:computerName
[Parameter()]
[String[]]
$Members,
[Parameter()]
[String[]]
$MembersToInclude,
[Parameter()]
[String[]]
$MembersToExclude
)
if (Test-IsNanoServer)
@@ -40,46 +55,23 @@ function Test-GroupExists
{
return Test-GroupExistsOnFullSKU @PSBoundParameters
}
if (Test-IsNanoServer)
{
# Try to find a group by its name.
try
{
$null = Get-LocalGroup -Name $GroupName -ErrorAction Stop
return $true
}
catch [System.Exception]
{
if ($_.CategoryInfo.ToString().Contains('GroupNotFoundException'))
{
# A group with the provided name does not exist.
return $false
}
throw $_.Exception
}
}
else
{
return [ADSI]::Exists("WinNT://$env:ComputerName/$GroupName,group")
}
}
<#
.SYNOPSIS
Determines if a Windows group exists.
.DESCRIPTION
This function determines if a Windows group exists on a local or remote machine.
Tests if a Windows group with the given name and members exists.
.PARAMETER GroupName
The name of the group to test.
The name of the group.
.PARAMETER ComputerName
The optional name of the computer to check. Omit to check for the group on the local machine.
.PARAMETER Members
The usernames of the members of the group.
.NOTES
For remote machines, the currently logged on user must have rights to enumerate groups.
.PARAMETER MembersToInclude
The usernames of the members that should be included in the group.
.PARAMETER MembersToExclude
The usernames of the members that should be excluded from the group.
#>
function Test-GroupExistsOnFullSKU
{
@@ -92,38 +84,131 @@ function Test-GroupExistsOnFullSKU
[String]
$GroupName,
[ValidateNotNullOrEmpty()]
[String]
$ComputerName = $env:computerName
[Parameter()]
[String[]]
$Members,
[Parameter()]
[String[]]
$MembersToInclude,
[Parameter()]
[String[]]
$MembersToExclude
)
Set-StrictMode -Version 'Latest'
$principalContext = New-Object -TypeName 'System.DirectoryServices.AccountManagement.PrincipalContext' `
-ArgumentList @( [System.DirectoryServices.AccountManagement.ContextType]::Machine )
$adsiComputerEntry = [ADSI] "WinNT://$ComputerName"
$group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($principalContext, $GroupName)
$groupExists = $null -ne $group
foreach ($adsiComputerEntryChild in $adsiComputerEntry.Children)
if ($groupExists)
{
if ($adsiComputerEntryChild.Path -like "WinNT://*$ComputerName/$GroupName")
if ($PSBoundParameters.ContainsKey('Members'))
{
return $true
$noActualMembers = ($null -eq $group.Members) -or ($group.Members.Count -eq 0)
$noExpectedMembers = ($null -eq $Members) -or ($Members.Count -eq 0)
if ($noActualMembers -and $noExpectedMembers)
{
$membersMatch = $true
}
elseif ($noActualMembers -xor $noExpectedMembers)
{
$membersMatch = $false
}
else
{
$membersMatch = $null -eq (Compare-Object -ReferenceObject $Members -DifferenceObject $group.Members.Name)
}
$groupExists = $groupExists -and $membersMatch
}
if ($PSBoundParameters.ContainsKey('MembersToInclude'))
{
$noActualMembers = ($null -eq $group.Members) -or ($group.Members.Count -eq 0)
$noExpectedMembers = ($null -eq $MembersToInclude) -or ($MembersToInclude.Count -eq 0)
if ($noExpectedMembers)
{
$membersToIncludeMatch = $true
}
elseif ($noActualMembers)
{
$membersToIncludeMatch = $false
}
else
{
$membersToIncludeMatch = $true
foreach ($expectedMemberName in $MembersToInclude)
{
if ($group.Members.Name -inotcontains $expectedMemberName)
{
$membersToIncludeMatch = $false
break
}
}
}
$groupExists = $groupExists -and $membersToIncludeMatch
}
if ($PSBoundParameters.ContainsKey('MembersToExclude'))
{
$noActualMembers = ($null -eq $group.Members) -or ($group.Members.Count -eq 0)
$noExcludedMembers = ($null -eq $MembersToExclude) -or ($MembersToExclude.Count -eq 0)
if ($noExcludedMembers)
{
$membersToExcludeMatch = $true
}
elseif ($noActualMembers)
{
$membersToExcludeMatch = $true
}
else
{
$groupMemberNames = $group.Members.Name | ForEach-Object { ($_ -split '/')[-1] }
$membersToExcludeMatch = $true
foreach ($excludedMemberName in $MembersToExclude)
{
if ($group.Members.Name -icontains $excludedMemberName)
{
$membersToExcludeMatch = $false
break
}
}
}
$groupExists = $groupExists -and $membersToExcludeMatch
}
}
return $false
$null = $principalContext.Dispose()
return $groupExists
}
<#
.SYNOPSIS
Determines if a Windows group exists.
.DESCRIPTION
This function determines if a Windows group exists on a local or remote machine.
Tests if a Windows group with the given name and members exists.
.PARAMETER GroupName
The name of the group to test.
The name of the group.
.PARAMETER ComputerName
This parameter should not be used on NanoServer.
.PARAMETER Members
The usernames of the members of the group.
.PARAMETER MembersToInclude
The usernames of the members that should be included in the group.
.PARAMETER MembersToExclude
The usernames of the members that should be excluded from the group.
#>
function Test-GroupExistsOnNanoServer
{
@@ -136,31 +221,30 @@ function Test-GroupExistsOnNanoServer
[String]
$GroupName,
[ValidateNotNullOrEmpty()]
[String]
$ComputerName = $env:computerName
[Parameter()]
[String[]]
$Members,
[Parameter()]
[String[]]
$MembersToInclude,
[Parameter()]
[String[]]
$MembersToExclude
)
Set-StrictMode -Version 'Latest'
if ($PSBoundParameters.ContainsKey('ComputerName'))
{
if (-not (Test-IsLocalMachine -Scope $ComputerName))
{
throw 'Do not specify ComputerName when running on NanoServer unless it is the local machine.'
}
}
$groupExists = $true
try
{
Get-LocalGroup -Name $GroupName -ErrorAction Stop | Out-Null
return $true
$null = Get-LocalGroup -Name $GroupName
}
catch [System.Exception]
{
if ($_.CategoryInfo.ToString().Contains('GroupNotFoundException'))
{
return $false
$groupExists = $false
}
else
{
@@ -168,30 +252,116 @@ function Test-GroupExistsOnNanoServer
}
}
return $false
if ($groupExists)
{
if ($PSBoundParameters.ContainsKey('Members'))
{
$groupMembers = Get-LocalGroupMember -Group $Group
$noActualMembers = ($null -eq $groupMembers) -or ($groupMembers.Count -eq 0)
$noExpectedMembers = ($null -eq $Members) -or ($Members.Count -eq 0)
if ($noActualMembers -and $noExpectedMembers)
{
$membersMatch = $true
}
elseif ($noActualMembers -xor $noExpectedMembers)
{
$membersMatch = $false
}
else
{
$groupMemberNames = $groupMembers.Name | ForEach-Object { ($_ -split '/')[-1] }
$membersMatch = $null -eq (Compare-Object -ReferenceObject $Members -DifferenceObject $groupMemberNames)
}
$groupExists = $groupExists -and $membersMatch
}
if ($PSBoundParameters.ContainsKey('MembersToInclude'))
{
$groupMembers = Get-LocalGroupMember -Group $Group
$noActualMembers = ($null -eq $groupMembers) -or ($groupMembers.Count -eq 0)
$noExpectedMembers = ($null -eq $MembersToInclude) -or ($MembersToInclude.Count -eq 0)
if ($noExpectedMembers)
{
$membersToIncludeMatch = $true
}
elseif ($noActualMembers)
{
$membersToIncludeMatch = $false
}
else
{
$groupMemberNames = $groupMembers.Name | ForEach-Object { ($_ -split '/')[-1] }
$membersToIncludeMatch = $true
foreach ($expectedMemberName in $MembersToInclude)
{
if ($groupMemberNames -inotcontains $expectedMemberName)
{
$membersToIncludeMatch = $false
break
}
}
}
$groupExists = $groupExists -and $membersToIncludeMatch
}
if ($PSBoundParameters.ContainsKey('MembersToExclude'))
{
$groupMembers = Get-LocalGroupMember -Group $Group
$noActualMembers = ($null -eq $groupMembers) -or ($groupMembers.Count -eq 0)
$noExcludedMembers = ($null -eq $MembersToExclude) -or ($MembersToExclude.Count -eq 0)
if ($noExcludedMembers)
{
$membersToExcludeMatch = $true
}
elseif ($noActualMembers)
{
$membersToExcludeMatch = $true
}
else
{
$groupMemberNames = $groupMembers.Name | ForEach-Object { ($_ -split '/')[-1] }
$membersToExcludeMatch = $true
foreach ($excludedMemberName in $MembersToExclude)
{
if ($groupMemberNames -icontains $excludedMemberName)
{
$membersToExcludeMatch = $false
break
}
}
}
$groupExists = $groupExists -and $membersToExcludeMatch
}
}
return $groupExists
}
<#
.SYNOPSIS
Creates a Windows group
.DESCRIPTION
This function creates a Windows group on the local or remote machine.
Creates a Windows group.
.PARAMETER GroupName
The name of the group to create
The name of the group.
.PARAMETER Description
The optional description to set for the group.
The description of the group.
.PARAMETER MemberUserNames
The usernames of the optional members to add to the group.
.PARAMETER ComputerName
The optional name of the computer to update. Omit to create the group on the local machine.
.NOTES
For remote machines, the currently logged on user must have rights to create a group.
.PARAMETER Members
The usernames of the members to add to the group.
#>
function New-Group
{
@@ -203,18 +373,19 @@ function New-Group
[String]
$GroupName,
[Parameter()]
[String]
$Description,
[Parameter()]
[String[]]
$MemberUserNames,
[ValidateNotNullOrEmpty()]
[String]
$ComputerName = $env:computerName
$Members
)
Set-StrictMode -Version 'Latest'
if (Test-GroupExists -GroupName $GroupName)
{
throw "Group $GroupName already exists."
}
if (Test-IsNanoServer)
{
@@ -228,25 +399,16 @@ function New-Group
<#
.SYNOPSIS
Creates a Windows group on a full server
.DESCRIPTION
This function creates a Windows group on the local or remote full server machine.
Creates a Windows group on a full server.
.PARAMETER GroupName
The name of the group to create
The name of the group.
.PARAMETER Description
The optional description to set for the group.
The description of the group.
.PARAMETER MemberUserNames
The usernames of the optional members to add to the group.
.PARAMETER ComputerName
The optional name of the computer to update. Omit to create the group on the local machine.
.NOTES
For remote machines, the currently logged on user must have rights to create a group.
.PARAMETER Members
The usernames of the members to add to the group.
#>
function New-GroupOnFullSKU
{
@@ -258,64 +420,48 @@ function New-GroupOnFullSKU
[String]
$GroupName,
[Parameter()]
[String]
$Description,
[Parameter()]
[String[]]
$MemberUserNames,
[ValidateNotNullOrEmpty()]
[String]
$ComputerName = $env:computerName
$Members
)
Set-StrictMode -Version 'Latest'
$adsiComputerEntry = [ADSI] "WinNT://$ComputerName"
if (Test-GroupExists -GroupName $GroupName)
{
Remove-Group -GroupName $GroupName -ComputerName $ComputerName
}
$adsiComputerEntry = [ADSI] "WinNT://$env:computerName"
$adsiGroupEntry = $adsiComputerEntry.Create('Group', $GroupName)
if ($PSBoundParameters.ContainsKey('Description'))
{
$adsiGroupEntry.Put('Description', $Description) | Out-Null
$null = $adsiGroupEntry.Put('Description', $Description)
}
$adsiGroupEntry.SetInfo() | Out-Null
$null = $adsiGroupEntry.SetInfo()
if ($PSBoundParameters.ContainsKey("MemberUserNames"))
if ($PSBoundParameters.ContainsKey("Members"))
{
$adsiGroupEntry = [ADSI]"WinNT://$ComputerName/$GroupName,group"
$adsiGroupEntry = [ADSI]"WinNT://$env:computerName/$GroupName,group"
foreach ($memberUserName in $MemberUserNames)
foreach ($memberUserName in $Members)
{
$adsiGroupEntry.Add("WinNT://$ComputerName/$memberUserName") | Out-Null
$null = $adsiGroupEntry.Add("WinNT://$env:computerName/$memberUserName")
}
}
}
<#
.SYNOPSIS
Creates a Windows group on a Nano server
.DESCRIPTION
This function creates a Windows group on the local Nano server machine.
Creates a Windows group on a Nano server.
.PARAMETER GroupName
The name of the group to create
The name of the group.
.PARAMETER Description
The optional description to set for the group.
The description of the group.
.PARAMETER MemberUserNames
The usernames of the optional members to add to the group.
.PARAMETER ComputerName
This parameter should not be used on a Nano server.
.PARAMETER Members
The usernames of the members to add to the group.
#>
function New-GroupOnNanoServer
{
@@ -327,55 +473,34 @@ function New-GroupOnNanoServer
[String]
$GroupName,
[Parameter()]
[String]
$Description,
[Parameter()]
[String[]]
$MemberUserNames,
[ValidateNotNullOrEmpty()]
[String]
$ComputerName = $env:computerName
$Members
)
Set-StrictMode -Version 'Latest'
if ($PSBoundParameters.ContainsKey('ComputerName'))
{
if (-not (Test-IsLocalMachine -Scope $ComputerName))
{
throw 'Do not specify ComputerName when running on NanoServer unless it is the local machine.'
}
}
if (Test-GroupExists -GroupName $GroupName)
{
Remove-LocalGroup -Name $GroupName -ErrorAction SilentlyContinue
}
New-LocalGroup -Name $GroupName
$null = New-LocalGroup -Name $GroupName
if ($PSBoundParameters.ContainsKey('Description'))
{
Set-LocalGroup -Name $GroupName -Description $Description
$null = Set-LocalGroup -Name $GroupName -Description $Description
}
if ($PSBoundParameters.ContainsKey('MemberUserNames'))
if ($PSBoundParameters.ContainsKey('Members'))
{
Add-LocalGroupMember -Name $GroupName -Member $Members
$null = Add-LocalGroupMember -Name $GroupName -Member $Members
}
}
<#
.SYNOPSIS
Deletes a user group.
Deletes a Windows group.
.PARAMETER GroupName
The name of the user group to delete.
.PARAMETER ComputerName
The optional name of the computer to update.
The default value is the local machine.
The name of the group.
#>
function Remove-Group
{
@@ -385,13 +510,14 @@ function Remove-Group
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$GroupName,
[ValidateNotNullOrEmpty()]
[String]
$ComputerName = $env:computerName
$GroupName
)
if (-not (Test-GroupExists -GroupName $GroupName))
{
throw "Group $GroupName does not exist to remove."
}
if (Test-IsNanoServer)
{
Remove-GroupOnNanoServer @PSBoundParameters
@@ -404,14 +530,10 @@ function Remove-Group
<#
.SYNOPSIS
Deletes a local user group on a full server.
Deletes a Windows group on a full server.
.PARAMETER GroupName
The name of the local user group to delete.
.PARAMETER ComputerName
The optional name of the computer to update.
The default value is the local machine.
The name of the group.
#>
function Remove-GroupOnFullSKU
{
@@ -421,33 +543,19 @@ function Remove-GroupOnFullSKU
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$GroupName,
[ValidateNotNullOrEmpty()]
[String]
$ComputerName = $env:computerName
$GroupName
)
Set-StrictMode -Version 'Latest'
$adsiComputerEntry = [ADSI]"WinNT://$ComputerName"
if (Test-GroupExists -GroupName $GroupName)
{
$adsiComputerEntry.Delete('Group', $GroupName) | Out-Null
}
$adsiComputerEntry = [ADSI]("WinNT://$env:computerName")
$null = $adsiComputerEntry.Delete('Group', $GroupName)
}
<#
.SYNOPSIS
Deletes a local user group on a Nano server.
Deletes a Windows group on a Nano server.
.PARAMETER GroupName
The name of the local user group to delete.
.PARAMETER ComputerName
This parameter should not be used on NanoServer.
The default value is the local machine.
The name of the group.
#>
function Remove-GroupOnNanoServer
{
@@ -457,30 +565,263 @@ function Remove-GroupOnNanoServer
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$GroupName,
[ValidateNotNullOrEmpty()]
[String]
$ComputerName = $env:computerName
$GroupName
)
Set-StrictMode -Version 'Latest'
Remove-LocalGroup -Name $GroupName
}
if ($PSBoundParameters.ContainsKey('ComputerName'))
<#
.SYNOPSIS
Tests if a user with the given username exists.
.PARAMETER Username
The username of the user.
#>
function Test-UserExists
{
[OutputType([Boolean])]
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$Username
)
if (Test-IsNanoServer)
{
if (-not (Test-IsLocalMachine -Scope $ComputerName))
{
throw 'Do not specify ComputerName when running on NanoServer unless it is the local machine.'
}
return Test-UserExistsOnNanoServer @PSBoundParameters
}
if (Test-GroupExists -GroupName $GroupName)
else
{
Remove-LocalGroup -Name $GroupName
return Test-UserExistsOnFullSKU @PSBoundParameters
}
}
Export-ModuleMember -Function `
New-Group, `
Remove-Group, `
Test-GroupExists
<#
.SYNOPSIS
Tests if a user with the given username exists on a full server.
.PARAMETER Username
The username of the user.
#>
function Test-UserExistsOnFullSKU
{
[OutputType([Boolean])]
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$Username
)
$principalContext = New-Object -TypeName 'System.DirectoryServices.AccountManagement.PrincipalContext' `
-ArgumentList @( [System.DirectoryServices.AccountManagement.ContextType]::Machine )
$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($principalContext, $Username)
$userExists = $null -ne $user
$null = $principalContext.Dispose()
return $userExists
}
<#
.SYNOPSIS
Tests if a user with the given username exists on a Nano server.
.PARAMETER Username
The username of the user.
#>
function Test-UserExistsOnNanoServer
{
[OutputType([Boolean])]
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$Username
)
$userExists = $true
try
{
$null = Get-LocalUser -Name $Username
}
catch [System.Exception]
{
if ($_.CategoryInfo.ToString().Contains('UserNotFoundException'))
{
$userExists = $false
}
else
{
$_.Exception
}
}
return $userExists
}
<#
.SYNOPSIS
Creates a user account.
.PARAMETER Credential
The credential containing the user's username and password.
#>
function New-User
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
if (Test-UserExists -Username $Credential.UserName)
{
throw "User $($Credential.UserName) already exists."
}
if (Test-IsNanoServer)
{
New-UserOnNanoServer @PSBoundParameters
}
else
{
New-UserOnFullSKU @PSBoundParameters
}
}
<#
.SYNOPSIS
Creates a user on a full server.
.PARAMETER Credential
The credential containing the user's username and password.
#>
function New-UserOnFullSKU
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
$userName = $Credential.UserName
$password = $Credential.GetNetworkCredential().Password
$adsiComputerEntry = [ADSI]("WinNT://$env:computerName")
$adsiUserEntry = $adsiComputerEntry.Create('User', $userName)
$null = $adsiUserEntry.SetPassword($password)
$null = $adsiUserEntry.SetInfo()
}
<#
.SYNOPSIS
Creates a user on a Nano server.
.PARAMETER Credential
The credential containing the user's username and password.
#>
function New-UserOnNanoServer
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
$userName = $Credential.UserName
$securePassword = $Credential.GetNetworkCredential().Password
New-LocalUser -Name $userName -Password $securePassword
}
<#
.SYNOPSIS
Removes a user.
.PARAMETER UserName
The name of the user.
#>
function Remove-User
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$UserName
)
if (-not (Test-UserExists -Username $Username))
{
throw "User $Username does not exist to remove."
}
if (Test-IsNanoServer)
{
Remove-UserOnNanoServer @PSBoundParameters
}
else
{
Remove-UserOnFullSKU @PSBoundParameters
}
}
<#
.SYNOPSIS
Removes a user on a full server.
.PARAMETER UserName
The name of the user.
#>
function Remove-UserOnFullSKU
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$UserName
)
$adsiComputerEntry = [ADSI]("WinNT://$env:computerName")
$null = $adsiComputerEntry.Delete('User', $UserName)
}
<#
.SYNOPSIS
Removes a user on a Nano server.
.PARAMETER UserName
The name of the user.
#>
function Remove-UserOnNanoServer
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$UserName
)
$null = Remove-LocalUser -Name $UserName
}
Export-ModuleMember -Function @( 'New-Group', 'Remove-Group', 'Test-GroupExists', 'New-User', 'Remove-User' )
+6 -4
View File
@@ -1,6 +1,9 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]
param ()
$errorActionPreference = 'Stop'
Set-StrictMode -Version 'Latest'
Import-Module -Name (Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) `
-ChildPath (Join-Path -Path 'TestHelpers' `
-ChildPath 'CommonTestHelper.psm1'))
@@ -1664,8 +1667,9 @@ try
Mock 'Get-GroupMembersFromDirectoryEntry' { return @( $memberDirectoryEntry3 ) }
It 'Should ignore stale members - Expected to write a warning' {
$getMembersResult = Get-MembersAsPrincipalsList -Group $script:testGroup -PrincipalContextCache $principalContextCache -Disposables $disposables | Should Be $null
It 'Should ignore stale members' {
$getMembersResult = Get-MembersAsPrincipalsList -Group $script:testGroup -PrincipalContextCache $principalContextCache -Disposables $disposables -WarningAction 'SilentlyContinue'
$getMembersResult | Should Be $null
Assert-MockCalled -CommandName 'Get-GroupMembersFromDirectoryEntry' -ParameterFilter { $Group.Name -eq $script:testGroupName }
Assert-MockCalled -CommandName 'New-Object' -ParameterFilter { $TypeName -eq 'System.DirectoryServices.DirectoryEntry' }
@@ -1998,8 +2002,6 @@ try
}
}
}
}
}
}