Tests/TestHelpers/MSFT_GroupResource.TestHelper.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 if (-not (Test-IsNanoServer)) { Add-Type -AssemblyName 'System.DirectoryServices.AccountManagement' } <# .SYNOPSIS Tests if a Windows group with the given name and members exists. .PARAMETER GroupName The name of the group. .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-GroupExists { [OutputType([Boolean])] [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [String] $GroupName, [Parameter()] [String[]] $Members, [Parameter()] [String[]] $MembersToInclude, [Parameter()] [String[]] $MembersToExclude ) if (Test-IsNanoServer) { return Test-GroupExistsOnNanoServer @PSBoundParameters } else { return Test-GroupExistsOnFullSKU @PSBoundParameters } } <# .SYNOPSIS Tests if a Windows group with the given name and members exists. .PARAMETER GroupName The name of the group. .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-GroupExistsOnFullSKU { [OutputType([Boolean])] [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $GroupName, [Parameter()] [String[]] $Members, [Parameter()] [String[]] $MembersToInclude, [Parameter()] [String[]] $MembersToExclude ) $principalContext = New-Object -TypeName 'System.DirectoryServices.AccountManagement.PrincipalContext' ` -ArgumentList @( [System.DirectoryServices.AccountManagement.ContextType]::Machine ) $group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($principalContext, $GroupName) $groupExists = $null -ne $group if ($groupExists) { if ($PSBoundParameters.ContainsKey('Members')) { $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 } } $null = $principalContext.Dispose() return $groupExists } <# .SYNOPSIS Tests if a Windows group with the given name and members exists. .PARAMETER GroupName The name of the group. .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 { [OutputType([Boolean])] [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $GroupName, [Parameter()] [String[]] $Members, [Parameter()] [String[]] $MembersToInclude, [Parameter()] [String[]] $MembersToExclude ) $groupExists = $true try { $null = Get-LocalGroup -Name $GroupName } catch [System.Exception] { if ($_.CategoryInfo.ToString().Contains('GroupNotFoundException')) { $groupExists = $false } else { throw $_.Exception } } 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. .PARAMETER GroupName The name of the group. .PARAMETER Description The description of the group. .PARAMETER Members The usernames of the members to add to the group. #> function New-Group { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $GroupName, [Parameter()] [String] $Description, [Parameter()] [String[]] $Members ) if (Test-GroupExists -GroupName $GroupName) { throw "Group $GroupName already exists." } if (Test-IsNanoServer) { New-GroupOnNanoServer @PSBoundParameters } else { New-GroupOnFullSKU @PSBoundParameters } } <# .SYNOPSIS Creates a Windows group on a full server. .PARAMETER GroupName The name of the group. .PARAMETER Description The description of the group. .PARAMETER Members The usernames of the members to add to the group. #> function New-GroupOnFullSKU { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $GroupName, [Parameter()] [String] $Description, [Parameter()] [String[]] $Members ) $adsiComputerEntry = [ADSI] "WinNT://$env:computerName" $adsiGroupEntry = $adsiComputerEntry.Create('Group', $GroupName) if ($PSBoundParameters.ContainsKey('Description')) { $null = $adsiGroupEntry.Put('Description', $Description) } $null = $adsiGroupEntry.SetInfo() if ($PSBoundParameters.ContainsKey("Members")) { $adsiGroupEntry = [ADSI]"WinNT://$env:computerName/$GroupName,group" foreach ($memberUserName in $Members) { $null = $adsiGroupEntry.Add("WinNT://$env:computerName/$memberUserName") } } } <# .SYNOPSIS Creates a Windows group on a Nano server. .PARAMETER GroupName The name of the group. .PARAMETER Description The description of the group. .PARAMETER Members The usernames of the members to add to the group. #> function New-GroupOnNanoServer { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $GroupName, [Parameter()] [String] $Description, [Parameter()] [String[]] $Members ) $null = New-LocalGroup -Name $GroupName if ($PSBoundParameters.ContainsKey('Description')) { $null = Set-LocalGroup -Name $GroupName -Description $Description } if ($PSBoundParameters.ContainsKey('Members')) { $null = Add-LocalGroupMember -Name $GroupName -Member $Members } } <# .SYNOPSIS Deletes a Windows group. .PARAMETER GroupName The name of the group. #> function Remove-Group { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $GroupName ) if (-not (Test-GroupExists -GroupName $GroupName)) { throw "Group $GroupName does not exist to remove." } if (Test-IsNanoServer) { Remove-GroupOnNanoServer @PSBoundParameters } else { Remove-GroupOnFullSKU @PSBoundParameters } } <# .SYNOPSIS Deletes a Windows group on a full server. .PARAMETER GroupName The name of the group. #> function Remove-GroupOnFullSKU { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $GroupName ) $adsiComputerEntry = [ADSI]("WinNT://$env:computerName") $null = $adsiComputerEntry.Delete('Group', $GroupName) } <# .SYNOPSIS Deletes a Windows group on a Nano server. .PARAMETER GroupName The name of the group. #> function Remove-GroupOnNanoServer { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $GroupName ) Remove-LocalGroup -Name $GroupName } <# .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) { return Test-UserExistsOnNanoServer @PSBoundParameters } else { return Test-UserExistsOnFullSKU @PSBoundParameters } } <# .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' ) |