Skip to content

Commit

Permalink
Adding Options parameter to Computer resource (#381)
Browse files Browse the repository at this point in the history
  • Loading branch information
nickgw authored May 23, 2022
1 parent 4a66e7c commit 49b3657
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- Computer
- Support Options Parameter for domain join - Fixes [Issue #234](https://github.com/dsccommunity/ComputerManagementDsc/issues/234).

## [8.5.0] - 2021-09-13

### Added
Expand Down
134 changes: 131 additions & 3 deletions source/DSCResources/DSC_Computer/DSC_Computer.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ $FailToRenameAfterJoinDomainErrorId = 'FailToRenameAfterJoinDomain,Microsoft.Pow
.PARAMETER Server
The Active Directory Domain Controller to use to join the domain.
.PARAMETER Options
Specifies advanced options for the Add-Computer join operation.
#>
function Get-TargetResource
{
Expand Down Expand Up @@ -84,7 +87,12 @@ function Get-TargetResource

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

[Parameter()]
[ValidateSet('AccountCreate', 'Win9XUpgrade', 'UnsecuredJoin', 'PasswordPass', 'JoinWithNewName', 'JoinReadOnly', 'InstallInvoke')]
[System.String[]]
$Options
)

Write-Verbose -Message ($script:localizedData.GettingComputerStateMessage -f $Name)
Expand Down Expand Up @@ -150,6 +158,9 @@ function Get-TargetResource
.PARAMETER Server
The Active Directory Domain Controller to use to join the domain.
.PARAMETER Options
Specifies advanced options for the Add-Computer join operation.
#>
function Set-TargetResource
{
Expand Down Expand Up @@ -188,7 +199,12 @@ function Set-TargetResource

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

[Parameter()]
[ValidateSet('AccountCreate', 'Win9XUpgrade', 'UnsecuredJoin', 'PasswordPass', 'JoinWithNewName', 'JoinReadOnly', 'InstallInvoke')]
[System.String[]]
$Options
)

Write-Verbose -Message ($script:localizedData.SettingComputerStateMessage -f $Name)
Expand Down Expand Up @@ -247,6 +263,15 @@ function Set-TargetResource
$addComputerParameters.Add("Server", $Server)
}

if (-not [System.String]::IsNullOrEmpty($Options))
{
<#
See https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/add-computer?view=powershell-5.1#parameters for available options and their description
#>
Assert-ResourceProperty @PSBoundParameters
$addComputerParameters.Add('Options', $Options)
}

# Rename the computer, and join it to the domain.
try
{
Expand Down Expand Up @@ -422,6 +447,9 @@ function Set-TargetResource
.PARAMETER Description
The value assigned here will be set as the local computer description.
.PARAMETER Options
Specifies advanced options for the Add-Computer join operation.
#>
function Test-TargetResource
{
Expand Down Expand Up @@ -461,7 +489,12 @@ function Test-TargetResource

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

[Parameter()]
[ValidateSet('AccountCreate', 'Win9XUpgrade', 'UnsecuredJoin', 'PasswordPass', 'JoinWithNewName', 'JoinReadOnly', 'InstallInvoke')]
[System.String[]]
$Options
)

Write-Verbose -Message ($script:localizedData.TestingComputerStateMessage -f $Name)
Expand Down Expand Up @@ -648,3 +681,98 @@ function Get-LogonServer
}

Export-ModuleMember -Function *-TargetResource

<#
.SYNOPSIS
This function validates the parameters passed. Called by Set-Resource.
Will throw an error if any parameters are invalid.
.PARAMETER Name
The desired computer name.
.PARAMETER DomainName
The name of the domain to join.
.PARAMETER JoinOU
The distinguished name of the organizational unit that the computer
account will be created in.
.PARAMETER Credential
Credential to be used to join a domain.
.PARAMETER UnjoinCredential
Credential to be used to leave a domain.
.PARAMETER WorkGroupName
The name of the workgroup.
.PARAMETER Description
The value assigned here will be set as the local computer description.
.PARAMETER Options
Specifies advanced options for the Add-Computer join operation.
#>
function Assert-ResourceProperty
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateLength(1, 15)]
[ValidateScript( { $_ -inotmatch '[\/\\:*?"<>|]' })]
[System.String]
$Name,

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

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

[Parameter()]
[System.Management.Automation.PSCredential]
$Credential,

[Parameter()]
[System.Management.Automation.PSCredential]
$UnjoinCredential,

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

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

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

[Parameter()]
[ValidateSet('AccountCreate', 'Win9XUpgrade', 'UnsecuredJoin', 'PasswordPass', 'JoinWithNewName', 'JoinReadOnly', 'InstallInvoke')]
[System.String[]]
$Options
)

if ($options -contains 'PasswordPass' -and
$options -notcontains 'UnsecuredJoin')
{
New-InvalidArgumentException `
-Message $script:localizedData.InvalidOptionPasswordPassUnsecuredJoin `
-ArgumentName 'PasswordPass'
}

if ($Options -contains 'PasswordPass' -and
$options -contains 'UnsecuredJoin' -and
-not [System.String]::IsNullOrEmpty($Credential.UserName))
{

New-InvalidArgumentException `
-Message $script:localizedData.InvalidOptionCredentialUnsecuredJoinNullUsername `
-ArgumentName 'Credential'
}

}
2 changes: 2 additions & 0 deletions source/DSCResources/DSC_Computer/DSC_Computer.schema.mof
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ class DSC_Computer : OMI_BaseResource
[Write, Description("The name of the workgroup.")] String WorkGroupName;
[Write, Description("The value assigned here will be set as the local computer description.")] String Description;
[Write, Description("The Active Directory Domain Controller to use to join the domain")] String Server;
[Write, Description("Specifies advanced options for the Add-Computer join operation"), ValueMap{"AccountCreate","Win9XUpgrade","UnsecuredJoin","PasswordPass","JoinWithNewName","JoinReadOnly","InstallInvoke"}, Values{"AccountCreate","Win9XUpgrade","UnsecuredJoin","PasswordPass","JoinWithNewName","JoinReadOnly","InstallInvoke"}] String Options[];
[Read, Description("A read-only property that specifies the organizational unit that the computer account is currently in.")] String CurrentOU;
};

Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ ConvertFrom-StringData @'
CheckingWorkgroupMemberMessage = Checking if the machine is a member of workgroup '{0}'.
DomainNameAndWorkgroupNameError = Only DomainName or WorkGroupName can be specified at once.
ComputerNotInDomainMessage = This machine is not a domain member.
InvalidOptionPasswordPassUnsecuredJoin = Domain Join option 'PasswordPass' may not be specified if 'UnsecuredJoin' is specified.
InvalidOptionCredentialUnsecuredJoinNullUsername = 'Credential' username must be null if 'UnsecuredJoin' is specified.
'@
57 changes: 57 additions & 0 deletions tests/Unit/DSC_Computer.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,34 @@ try
Assert-MockCalled -CommandName Add-Computer -Exactly -Times 0 -Scope It -ParameterFilter { $WorkGroupName }
}

It 'Changes ComputerName and changes Domain to new Domain with Options passed' {
Mock -CommandName Get-WMIObject -MockWith {
[PSCustomObject] @{
Domain = 'Contoso.com';
Workgroup = 'Contoso.com';
PartOfDomain = $true
}
}

Mock -CommandName Get-ComputerDomain -MockWith {
'contoso.com'
}

Mock -CommandName Add-Computer

Set-TargetResource `
-Name $notComputerName `
-DomainName 'adventure-works.com' `
-Credential $credential `
-UnjoinCredential $credential `
-Options @('InstallInvoke') `
-Verbose | Should -BeNullOrEmpty

Assert-MockCalled -CommandName Rename-Computer -Exactly -Times 0 -Scope It
Assert-MockCalled -CommandName Add-Computer -Exactly -Times 1 -Scope It -ParameterFilter { $DomainName -and $NewName }
Assert-MockCalled -CommandName Add-Computer -Exactly -Times 0 -Scope It -ParameterFilter { $WorkGroupName }
}

It 'Should try a separate rename if ''FailToRenameAfterJoinDomain'' occured during domain join' {
$message = "Computer '' was successfully joined to the new domain '', but renaming it to '' failed with the following error message: The directory service is busy."
$exception = [System.InvalidOperationException]::new($message)
Expand Down Expand Up @@ -1179,6 +1207,35 @@ try
Get-LogonServer | Should -Not -BeNullOrEmpty
}
}

Context 'DSC_Computer\Assert-ResourceProperty' {
It 'Should throw if PasswordPass and UnsecuredJoin is present but credential username is not null' {
$errorRecord = Get-InvalidArgumentRecord `
-Message ($LocalizedData.InvalidOptionCredentialUnsecuredJoinNullUsername) `
-ArgumentName 'Credential'

{
Assert-ResourceProperty `
-Name $env:COMPUTERNAME `
-Options @('PasswordPass', 'UnsecuredJoin') `
-Credential $credential `
-Verbose
} | Should -Throw $errorRecord
}

It 'Should throw if PasswordPass is present in options without UnsecuredJoin' {
$errorRecord = Get-InvalidArgumentRecord `
-Message ($LocalizedData.InvalidOptionPasswordPassUnsecuredJoin) `
-ArgumentName 'PasswordPass'

{
Assert-ResourceProperty `
-Name $env:COMPUTERNAME `
-Options @('PasswordPass') `
-Verbose
} | Should -Throw $errorRecord
}
}
}
}
}
Expand Down

0 comments on commit 49b3657

Please sign in to comment.