Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Computer: Delete existing AD Computer object when joining Computer to Domain #386

Merged
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
35a7c41
First stab at computer object deletion if it exists already
nickgw May 17, 2022
f37afb2
Using functions and adding some verbose output
nickgw May 18, 2022
9b87213
Updating changelog and fixing formatting
nickgw May 18, 2022
27852f7
Fixing up functions
nickgw May 18, 2022
77423d3
fixing verbose message
nickgw May 18, 2022
0675006
adding tests
nickgw May 18, 2022
342891b
Fixing mocks for adsi funcs in workgroup join
nickgw May 18, 2022
b520ab1
initial getadsicomputer tests
nickgw May 19, 2022
a50330e
Add test with mocks of dot net objects
nickgw May 19, 2022
a92bdb1
Initial delete-adsiobject test
nickgw May 20, 2022
fd7a2c6
Updating tests for adsi stuff
nickgw May 20, 2022
e0d919d
Updating tests
nickgw May 20, 2022
fc0889a
mock the psautomation type better
nickgw May 20, 2022
b2c131a
mock the psbase obj type with property
nickgw May 20, 2022
987fc1b
Removing unnecessary property of fake_psbase_object
nickgw May 20, 2022
b807a02
moving scope
nickgw May 20, 2022
7fb77f7
does this work
nickgw May 20, 2022
3d658b6
no quotes
nickgw May 20, 2022
498639d
Simplify
nickgw May 20, 2022
5680604
no need for nested class
nickgw May 20, 2022
3c07223
Adding mocks for exceptions
nickgw May 20, 2022
cb6c1d0
Adding validation for path in delete-adsiobject
nickgw May 20, 2022
729e72a
updating tests
nickgw May 20, 2022
8164665
rescope new-object
nickgw May 20, 2022
77255ee
remove throw for write-error
nickgw May 20, 2022
8e9af1e
add space between credential and backtick
nickgw May 20, 2022
f14498f
add space between credential and backtick
nickgw May 20, 2022
a9a79b1
use splat rather than backtick
nickgw May 21, 2022
5cfb233
Resolving merge conflicts
nickgw May 23, 2022
9f7919f
fixing blocks from merge conflict
nickgw May 23, 2022
1c59352
Rework Get-AdsiComputer to throw correctly
nickgw May 31, 2022
2e236ee
resolving comments from PR
nickgw May 31, 2022
7ee2284
Fixing tests
nickgw May 31, 2022
1f68c52
Fixing error message quoting
nickgw May 31, 2022
9125fd7
Fixing error messages
nickgw May 31, 2022
5257d52
Fixing validation error message
nickgw May 31, 2022
a511666
Updating mock commands and removing try catches to let dotnet error e…
nickgw May 31, 2022
20df9dd
Removing unused string
nickgw May 31, 2022
9115448
update changelog and single quote string
nickgw Jun 1, 2022
f59de8f
changelog
nickgw Jun 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ The format is based on and uses the types of changes according to [Keep a Change
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
- Computer
- When joining a computer to a domain, existing AD computer objects will be deleted.

### Added
- Computer
Expand Down
118 changes: 118 additions & 0 deletions source/DSCResources/DSC_Computer/DSC_Computer.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,15 @@ 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)
{
Delete-ADSIObject -Path $computerObject.Path -Credential $Credential
Write-Verbose -Message ($script:localizedData.DeletedExistingComputerObject -f $Name, $computerObject.Path)
}

if (-not [System.String]::IsNullOrEmpty($Options))
{
<#
Expand Down Expand Up @@ -680,6 +689,115 @@ function Get-LogonServer
return $logonserver
}

<#
.SYNOPSIS
Returns an ADSI Computer Object.

.PARAMETER Name
Name of the computer to search for in the given domain.

.PARAMETER Domain
Domain to search.

.PARAMETER Credential
Credential to search domain with.
#>
function Get-ADSIComputer
{
[CmdletBinding()]
[OutputType([System.DirectoryServices.SearchResult])]
param
(
[Parameter(Mandatory = $true)]
[ValidateLength(1, 15)]
[ValidateScript( { $_ -inotmatch '[\/\\:*?"<>|]' })]
[System.String]
$Name,

[Parameter(Mandatory = $true)]
[System.String]
$DomainName,

[Parameter(Mandatory = $true)]
[System.Management.Automation.PSCredential]
$Credential
)

$searcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher
$searcher.Filter = "(&(objectCategory=computer)(objectClass=computer)(cn=$Name))"
if ($DomainName -notlike "LDAP://*")
{
$DomainName = "LDAP://$DomainName"
}

$params = @{
TypeName = 'System.DirectoryServices.DirectoryEntry'
ArgumentList = @(
$DomainName,
$Credential.UserName,
$Credential.GetNetworkCredential().password
)
ErrorAction = 'Stop'
}
$searchRoot = New-Object @params
$searcher.SearchRoot = $searchRoot

try
{
return $searcher.FindOne()
}
catch
{
New-InvalidOperationException -Message ($script:localizedData.InvalidUserNameorPassword -f $Credential.Username)
}
}

<#
.SYNOPSIS
Deletes an ADSI DirectoryEntry Object.

.PARAMETER Path
Path to Object to delete.

.PARAMETER Credential
Credential to authenticate to the domain.
#>
function Delete-ADSIObject
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateScript( { $_ -imatch "LDAP://*" })]
[System.String]
$Path,

[Parameter(Mandatory = $true)]
[System.Management.Automation.PSCredential]
$Credential
)

try
{
$params = @{
TypeName = 'System.DirectoryServices.DirectoryEntry'
ArgumentList = @(
$DomainName,
$Credential.UserName
$Credential.GetNetworkCredential().password
)
ErrorAction = 'Stop'
}
$adsiObj = New-Object @params

$adsiObj.DeleteTree()
}
catch
{
New-InvalidOperationException -Message $_.Exception.Message -ErrorRecord $_
}
}

Export-ModuleMember -Function *-TargetResource

<#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ 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.
DeletedExistingComputerObject = Deleted existing computer object with name '{0}' at path '{1}'.
InvalidOptionPasswordPassUnsecuredJoin = Domain Join option 'PasswordPass' may not be specified if 'UnsecuredJoin' is specified.
InvalidOptionCredentialUnsecuredJoinNullUsername = 'Credential' username must be null if 'UnsecuredJoin' is specified.
InvalidUserNameorPassword = Password specified for UserName {0} is invalid.
'@
Loading