From fad75aba31220e63aaedd60e07f4d149b285c982 Mon Sep 17 00:00:00 2001 From: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com> Date: Fri, 16 May 2025 17:56:53 +0200 Subject: [PATCH 1/5] Remove deletion of AD computer object when using PasswordPass and UnsecuredJoin options --- CHANGELOG.md | 5 +++++ .../DSC_Computer/DSC_Computer.psm1 | 19 ++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd7bfed1..43de36e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Remove deletion of computer object when PasswordPass and UnsecuredJoin options are used in DSC_Computer. + Fixes [Issue #446](https://github.com/dsccommunity/ComputerManagementDsc/issues/446). + ## [10.0.0] - 2025-01-25 ### Added diff --git a/source/DSCResources/DSC_Computer/DSC_Computer.psm1 b/source/DSCResources/DSC_Computer/DSC_Computer.psm1 index 1051014c..bd73ff48 100644 --- a/source/DSCResources/DSC_Computer/DSC_Computer.psm1 +++ b/source/DSCResources/DSC_Computer/DSC_Computer.psm1 @@ -262,13 +262,18 @@ function Set-TargetResource $addComputerParameters.Add("Server", $Server) } - # Check for existing computer objecst using ADSI without ActiveDirectory module - $computerObject = Get-ADSIComputer -Name $Name -DomainName $DomainName -Credential $Credential - - if ($computerObject) - { - Remove-ADSIObject -Path $computerObject.Path -Credential $Credential - Write-Verbose -Message ($script:localizedData.DeletedExistingComputerObject -f $Name, $computerObject.Path) + # When using the UnsecuredJoin and PasswordPass options means the computer object + # has been precreated in the domain and should not be deleted before joining the domain. + if ( -not ($Options -contains 'PasswordPass' -and + $options -contains 'UnsecuredJoin')) { + # Check for existing computer objecst using ADSI without ActiveDirectory module + $computerObject = Get-ADSIComputer -Name $Name -DomainName $DomainName -Credential $Credential + + if ($computerObject) + { + Remove-ADSIObject -Path $computerObject.Path -Credential $Credential + Write-Verbose -Message ($script:localizedData.DeletedExistingComputerObject -f $Name, $computerObject.Path) + } } if (-not [System.String]::IsNullOrEmpty($Options)) From d15afe1a1466acbe8b8e3e54f93a9493eda79ec4 Mon Sep 17 00:00:00 2001 From: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com> Date: Mon, 16 Jun 2025 22:10:13 +0200 Subject: [PATCH 2/5] Improve the check and add JoinReadOnly option --- .../DSC_Computer/DSC_Computer.psm1 | 24 ++++++++++++------- .../en-US/DSC_Computer.strings.psd1 | 1 + 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/source/DSCResources/DSC_Computer/DSC_Computer.psm1 b/source/DSCResources/DSC_Computer/DSC_Computer.psm1 index c0fdfb96..ee431b94 100644 --- a/source/DSCResources/DSC_Computer/DSC_Computer.psm1 +++ b/source/DSCResources/DSC_Computer/DSC_Computer.psm1 @@ -262,19 +262,25 @@ function Set-TargetResource $addComputerParameters.Add("Server", $Server) } - # When using the UnsecuredJoin and PasswordPass options means the computer object - # has been precreated in the domain and should not be deleted before joining the domain. - if ( -not ($Options -contains 'PasswordPass' -and - $options -contains 'UnsecuredJoin')) { - # Check for existing computer objecst using ADSI without ActiveDirectory module - $computerObject = Get-ADSIComputer -Name $Name -DomainName $DomainName -Credential $Credential - - if ($computerObject) - { + # Check for existing computer objecst using ADSI without ActiveDirectory module + $computerObject = Get-ADSIComputer -Name $Name -DomainName $DomainName -Credential $Credential + if ($computerObject) + { + # UnsecuredJoin and PasswordPass options or JoinReadOnly option uses an existing machine account + # to join the computer to the domain and should not be deleted before. + if ( -not (($Options -contains 'PasswordPass' -and $options -contains 'UnsecuredJoin') -or ($Options -contains 'JoinReadOnly'))) { Remove-ADSIObject -Path $computerObject.Path -Credential $Credential Write-Verbose -Message ($script:localizedData.DeletedExistingComputerObject -f $Name, $computerObject.Path) } } + else + { + # Check if the computer object exists in the domain when using UnsecuredJoin and PasswordPass options or JoinReadOnly option + if (($Options -contains 'PasswordPass' -and $options -contains 'UnsecuredJoin') -or ($Options -contains 'JoinReadOnly')) { + $errorMessage = $script:localizedData.ComputerObjectNotFound -f $Name,$DomainName + New-ObjectNotFoundException -Message $errorMessage + } + } if (-not [System.String]::IsNullOrEmpty($Options)) { diff --git a/source/DSCResources/DSC_Computer/en-US/DSC_Computer.strings.psd1 b/source/DSCResources/DSC_Computer/en-US/DSC_Computer.strings.psd1 index 22903a87..0ceb448c 100644 --- a/source/DSCResources/DSC_Computer/en-US/DSC_Computer.strings.psd1 +++ b/source/DSCResources/DSC_Computer/en-US/DSC_Computer.strings.psd1 @@ -17,6 +17,7 @@ ConvertFrom-StringData @' DomainNameAndWorkgroupNameError = Only DomainName or WorkGroupName can be specified at once. ComputerNotInDomainMessage = This machine is not a domain member. DeletedExistingComputerObject = Deleted existing computer object with name '{0}' at path '{1}'. + ComputerObjectNotFound = Computer object with name '{0}' not found in domain '{1}'. InvalidOptionPasswordPassUnsecuredJoin = Domain Join option 'PasswordPass' may not be specified if 'UnsecuredJoin' is specified. InvalidOptionCredentialUnsecuredJoinNullUsername = 'Credential' username must be null if 'UnsecuredJoin' is specified. '@ From 861b24a81c2fb606bcbb6564a66a1415c2e7363d Mon Sep 17 00:00:00 2001 From: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com> Date: Mon, 16 Jun 2025 22:41:50 +0200 Subject: [PATCH 3/5] Fix syntax --- source/DSCResources/DSC_Computer/DSC_Computer.psm1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/DSCResources/DSC_Computer/DSC_Computer.psm1 b/source/DSCResources/DSC_Computer/DSC_Computer.psm1 index ee431b94..9d3c8e6a 100644 --- a/source/DSCResources/DSC_Computer/DSC_Computer.psm1 +++ b/source/DSCResources/DSC_Computer/DSC_Computer.psm1 @@ -268,7 +268,8 @@ function Set-TargetResource { # UnsecuredJoin and PasswordPass options or JoinReadOnly option uses an existing machine account # to join the computer to the domain and should not be deleted before. - if ( -not (($Options -contains 'PasswordPass' -and $options -contains 'UnsecuredJoin') -or ($Options -contains 'JoinReadOnly'))) { + if ( -not (($Options -contains 'PasswordPass' -and $options -contains 'UnsecuredJoin') -or ($Options -contains 'JoinReadOnly'))) + { Remove-ADSIObject -Path $computerObject.Path -Credential $Credential Write-Verbose -Message ($script:localizedData.DeletedExistingComputerObject -f $Name, $computerObject.Path) } @@ -276,7 +277,8 @@ function Set-TargetResource else { # Check if the computer object exists in the domain when using UnsecuredJoin and PasswordPass options or JoinReadOnly option - if (($Options -contains 'PasswordPass' -and $options -contains 'UnsecuredJoin') -or ($Options -contains 'JoinReadOnly')) { + if (($Options -contains 'PasswordPass' -and $options -contains 'UnsecuredJoin') -or ($Options -contains 'JoinReadOnly')) + { $errorMessage = $script:localizedData.ComputerObjectNotFound -f $Name,$DomainName New-ObjectNotFoundException -Message $errorMessage } From 1cf12f8e533166c6c912f16b160e30bddcace089 Mon Sep 17 00:00:00 2001 From: Alexandre JARDON <28548335+webalexeu@users.noreply.github.com> Date: Wed, 3 Sep 2025 21:47:44 +0200 Subject: [PATCH 4/5] Typo --- source/DSCResources/DSC_Computer/DSC_Computer.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/DSCResources/DSC_Computer/DSC_Computer.psm1 b/source/DSCResources/DSC_Computer/DSC_Computer.psm1 index 9d3c8e6a..43145ca2 100644 --- a/source/DSCResources/DSC_Computer/DSC_Computer.psm1 +++ b/source/DSCResources/DSC_Computer/DSC_Computer.psm1 @@ -262,7 +262,7 @@ function Set-TargetResource $addComputerParameters.Add("Server", $Server) } - # Check for existing computer objecst using ADSI without ActiveDirectory module + # Check for existing computer object using ADSI without ActiveDirectory module $computerObject = Get-ADSIComputer -Name $Name -DomainName $DomainName -Credential $Credential if ($computerObject) { From 643f5fb799a6729cc534e677bdba2b556a381b22 Mon Sep 17 00:00:00 2001 From: "Alexandre JARDON (WebalexEU)" <28548335+webalexeu@users.noreply.github.com> Date: Mon, 8 Sep 2025 17:05:37 +0200 Subject: [PATCH 5/5] Manage condition using variable --- source/DSCResources/DSC_Computer/DSC_Computer.psm1 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/DSCResources/DSC_Computer/DSC_Computer.psm1 b/source/DSCResources/DSC_Computer/DSC_Computer.psm1 index 43145ca2..598a8e20 100644 --- a/source/DSCResources/DSC_Computer/DSC_Computer.psm1 +++ b/source/DSCResources/DSC_Computer/DSC_Computer.psm1 @@ -264,11 +264,12 @@ function Set-TargetResource # Check for existing computer object using ADSI without ActiveDirectory module $computerObject = Get-ADSIComputer -Name $Name -DomainName $DomainName -Credential $Credential + # True when a pre-created computer object is required + $requiresPrecreated = ('JoinReadOnly' -in $Options) -or (('PasswordPass' -in $Options) -and ('UnsecuredJoin' -in $Options)) + if ($computerObject) { - # UnsecuredJoin and PasswordPass options or JoinReadOnly option uses an existing machine account - # to join the computer to the domain and should not be deleted before. - if ( -not (($Options -contains 'PasswordPass' -and $options -contains 'UnsecuredJoin') -or ($Options -contains 'JoinReadOnly'))) + if (-not $requiresPrecreated) { Remove-ADSIObject -Path $computerObject.Path -Credential $Credential Write-Verbose -Message ($script:localizedData.DeletedExistingComputerObject -f $Name, $computerObject.Path) @@ -276,10 +277,9 @@ function Set-TargetResource } else { - # Check if the computer object exists in the domain when using UnsecuredJoin and PasswordPass options or JoinReadOnly option - if (($Options -contains 'PasswordPass' -and $options -contains 'UnsecuredJoin') -or ($Options -contains 'JoinReadOnly')) + if ($requiresPrecreated) { - $errorMessage = $script:localizedData.ComputerObjectNotFound -f $Name,$DomainName + $errorMessage = $script:localizedData.ComputerObjectNotFound -f $Name, $DomainName New-ObjectNotFoundException -Message $errorMessage } }