User Tools

Site Tools


userspace:active_directory_-_join_leave_relocate_ou

This is an old revision of the document!


Active Directory client management, join/leave/relocate ou

  • tested under windows 7
  • tested under win2012 active directory environment
  • tested under winst 4.11.5.14

With this package, you can join or leave a domain, or change the ou-path for the client within a domain (still experimental, details below). These three functions are conveniently assigned to the action requests setup (join), uninstall (leave), update (relocate).

Setup

[Actions]
SetLogLevel = 9
ExitOnError = false
ScriptErrorMessages = on
TraceMode = off
StayOnTop = false
requiredWinstVersion >= "4.11.5.14"
ScriptErrorMessages = false
noUpdateScript
 
defVar $DomainRaw$
defVar $Domain$
defVar $DomainCurrent$
defVar $OUPath$
defVar $OUPathCurrent$
defVar $Username$
defVar $Password$
defVar $ExitCode$
defVar $JoinMode$
defVar $UnJoinMode$
defVar $JOIN_DOMAIN$
defVar $ACCT_CREATE$
defVar $ACCT_DELETE$
defVar $WIN9X_UPGRADE$
defVar $DOMAIN_JOIN_IF_JOINED$
defVar $JOIN_UNSECURE$
defVar $MACHINE_PASSWORD_PASSED$
defVar $DEFERRED_SPN_SET$
defVar $INSTALL_INVOCATION$
;defVar $ACCT_NO_OPTIONS$
;defVar $ACCT_DEACTIVATE$
 
;calculate joinmode from possible constants
set $JOIN_DOMAIN$ = "1"
set $ACCT_CREATE$ = "2"
set $ACCT_DELETE$ = "4"
set $WIN9X_UPGRADE$ = "16"
set $DOMAIN_JOIN_IF_JOINED$ = "32"
set $JOIN_UNSECURE$ = "64"
set $MACHINE_PASSWORD_PASSED$ = "128"
set $DEFERRED_SPN_SET$ = "256"
set $INSTALL_INVOCATION$ = "262144"
set $JoinMode$ = calculate($JOIN_DOMAIN$+"+"+$ACCT_CREATE$)
 
;calculate unjoinmode from possible constants
;set $ACCT_NO_OPTIONS$ = "0"
;set $ACCT_DEACTIVATE$ = "2"
;set $UnJoinMode$ = calculate($ACCT_DEACTIVATE$)
 
;product property domain_ou has the following syntax: [domain.tld][/ou_1/ou_2] - both segments are optional.
;domain must be the fqdn for the domain to join
;ou-path must consist of the hierarchical list of ou's the client should be put in, every ou must have a leading slash. 
set $DomainRaw$ = getProductProperty("domain_ou","")
 
;get domain from product property - if domain is not set, get domain from host identifier.
set $Domain$ = takeString(0, splitString($DomainRaw$,"/"))
if ($Domain$ = "")
	set $Domain$ = composeString(getSubList(1 : ,splitString("%HostId%",".")),".")
	set $DomainRaw$ = $Domain$ + $DomainRaw$
endif
 
;get ou-path from product property - if ou-path is not set, join client to standard client-ou-path for the domain.
;ou-path will be transformed into ldap-friendly syntax.
set $OUPath$ = ""
for %OU% in getSubList(1 : ,splitString($DomainRaw$,"/")) do set $OUPath$ = "OU=%OU%,"+$OUPath$
if not ($OUPath$ = "")
	for %DC% in splitString($Domain$,".") do set $OUPath$ = $OUPath$+"DC=%DC%,"
	set $OUPath$ = strPart($OUPath$,"1",calculate(strLength($OUPath$)+"-1"))
endif
 
;get username + password from, product properties, hide password value in log
set $Username$  = getProductProperty("username","")
setConfidential getProductProperty("password","")
set $Password$  = getProductProperty("password","")
 
;check if client is in domain 
if ( takeString(0, getOutStreamFromSection('execwith_vbs_check_domain cscript //nologo //e:vbs')) = "0" )
	showBitmap "%ScriptPath%\domain.png" "Active Directory" 
	message "Join domain " + $DomainRaw$
	execwith_vbs_domain_join cscript //nologo //e:vbs
	sub_check_domain_join
	dosinanicon_gpupdate /WaitOnClose
	comment "Setting default logon domain, clear previous login user"
	registry_default_domain /sysnative
	exitwindows /Reboot
else
	set $DomainCurrent$ = takeString(0, getOutStreamFromSection('execwith_vbs_get_domain cscript //nologo //e:vbs'))
	;check if client is already in domain requested
	if not ( $DomainCurrent$ = $Domain$ ) 
		showBitmap "%ScriptPath%\domain.png" "Active Directory" 
		message "Leave domain " + $DomainCurrent$
		execwith_vbs_domain_unjoin cscript //nologo //e:vbs
		sub_check_domain_unjoin
		;TODO remove client from ad
		;TODO check exitcode adsi
		exitwindows /ImmediateReboot
	else
		comment "Client is already in requested domain"
	endif
endif
 
;reset username + password entries in product properties
opsiservicecall_unset_username
opsiservicecall_unset_password
 
[execwith_vbs_check_domain]
Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'")
Wscript.Echo obj.PartOfDomain
 
[execwith_vbs_get_domain]
Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'")
Wscript.Echo obj.Domain
 
[execwith_vbs_domain_join]
Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'")
res = obj.JoinDomainOrWorkGroup("$Domain$", "$Password$", "$Username$", "$OUPath$", $JoinMode$)
Wscript.Quit res
 
[execwith_vbs_domain_unjoin]
Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'")
res = obj.UnjoinDomainOrWorkgroup("$Password$", "$Username$")
;res = obj.UnjoinDomainOrWorkgroup("$Password$", "$Username$", $UnJoinMode$)
Wscript.Quit res
 
[dosinanicon_gpupdate]
gpupdate /force
exit %ERRORLEVEL%
 
[registry_default_domain]
openkey [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]
set "DefaultDomainName"    = REG_SZ:"$Domain$"
set "AltDefaultDomainName" = REG_SZ:"$Domain$"
set "CachePrimaryDomain"   = REG_SZ:"$Domain$"
openKey [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI]
set "LastLoggedOnSAMUser" = REG_SZ:""
set "LastLoggedOnUser"    = REG_SZ:""
 
[opsiservicecall_unset_username]
"method": "setProductProperty"
"params": [
	"%installingProdName%",
	"username",
	"",
	"%hostid%"
]
 
[opsiservicecall_unset_password]
"method": "setProductProperty"
"params": [
	"%installingProdName%",
	"password",
	"",
	"%hostid%"
]
 
[sub_check_domain_unjoin]
set $ExitCode$ = getLastExitCode
if $ExitCode$ = "0" 
	comment "Success"
else
	logError "UNKNOWN ERROR " & ReturnValue
	isFatalError
endif
 
[sub_check_domain_join]
set $ExitCode$ = getLastExitCode
if $ExitCode$ = "0" 
	comment "Success"
else
if $ExitCode$ = "2" 
	logError "Missing OU"
	isFatalError
else
if $ExitCode$ = "5"
	logError "Access denied"
	isFatalError
else
if $ExitCode$ = "53" 
	logError "Network path not found"
	isFatalError
else
if $ExitCode$ = "87"
	logError "Parameter incorrect"
	isFatalError
else
if $ExitCode$ = "1326" 
	logError "Logon failure, user or pass"
	isFatalError
else
if $ExitCode$ = "1355" 
	logError "Domain can not be contacted"
	isFatalError
else
if $ExitCode$ = "1909" 
	logError "User account locked out"
	isFatalError
else
if $ExitCode$ = "2224" 
	logError "Computer Account allready exists"
	isFatalError
else
if $ExitCode$ = "2691" 
	logError "Allready joined"
	isFatalError
else
	logError "Unknown error " & ReturnValue
	isFatalError
endif
endif
endif
endif
endif
endif
endif
endif
endif
endif

Uninstall

[Actions]
SetLogLevel = 9 
ExitOnError = false
ScriptErrorMessages = on
TraceMode = off
StayOnTop = false
requiredWinstVersion >= "4.11.5.14"
ScriptErrorMessages = false
 
defVar $DomainCurrent$
defVar $Username$
defVar $Password$
defVar $ExitCode$
defVar $UnJoinMode$
;defVar $ACCT_NO_OPTION$
;defVar $ACCT_DEACTIVATE$
 
;calculate unjoinmode from possible constants
;set $ACCT_NO_OPTION$ = "0"
;set $ACCT_DEACTIVATE$ = "2"
;set $UnJoinMode$ = calculate($ACCT_DEACTIVATE$)
 
;get username + password from, product properties, hide password value in log
set $Username$  = getProductProperty("username","")
setConfidential getProductProperty("password","")
set $Password$  = getProductProperty("password","")
 
;reset username + password entries in product properties
;opsiservicecall_unset_username
;opsiservicecall_unset_password
 
;check if client is in domain 
if not ( takeString(0, getOutStreamFromSection('execwith_vbs_check_domain cscript //nologo //e:vbs')) = "0" )
	set $DomainCurrent$ = takeString(0, getOutStreamFromSection('execwith_vbs_get_domain cscript //nologo //e:vbs'))
	showBitmap "%ScriptPath%\domain.png" "Active Directory" 
	message "Leave domain " + $DomainCurrent$
	;leave domain
	execwith_vbs_domain_unjoin cscript //nologo //e:vbs
	sub_check_domain_unjoin
	;TODO remove client from ad
	;TODO check exitcode adsi
	;restart client, script will be re-executed upon next opsi request 
	exitwindows /Reboot
else
	comment "Computer is currently not part of a domain"
endif
 
;reset username + password entries in product properties
opsiservicecall_unset_username
opsiservicecall_unset_password
 
[execwith_vbs_check_domain]
Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'")
Wscript.Echo obj.PartOfDomain
 
[execwith_vbs_get_domain]
Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'")
Wscript.Echo obj.Domain
 
[execwith_vbs_domain_unjoin]
Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'")
res = obj.UnjoinDomainOrWorkgroup("$Password$", "$Username$")
;res = obj.UnjoinDomainOrWorkgroup("$Password$", "$Username$", $UnJoinMode$)
Wscript.Quit res
 
[opsiservicecall_unset_username]
"method": "setProductProperty"
"params": [
	"%installingProdName%",
	"username",
	"",
	"%hostid%"
]
 
[opsiservicecall_unset_password]
"method": "setProductProperty"
"params": [
	"%installingProdName%",
	"password",
	"",
	"%hostid%"
]
 
[sub_check_domain_unjoin]
set $ExitCode$ = getLastExitCode
if $ExitCode$ = "0"
	comment "Success"
else
	logError "UNKNOWN ERROR " & ReturnValue
	isFatalError
endif

Update

[Actions]
SetLogLevel = 9
ExitOnError = false
ScriptErrorMessages = on
TraceMode = off
StayOnTop = false
requiredWinstVersion >= "4.11.5.14"
ScriptErrorMessages = false
 
defVar $DomainRaw$
defVar $Domain$
defVar $DomainCurrent$
defVar $OUPath$
defVar $OUPathCurrent$
defVar $Username$
defVar $Password$
defVar $ExitCode$
 
;product property domain_ou has the following syntax: [domain.tld][/ou_1/ou_2] - both segments are optional.
;domain must be the fqdn for the domain to join
;ou-path must consist of the hierarchical list of ou's the client should be put in, every ou must have a leading slash. 
set $DomainRaw$ = getProductProperty("domain_ou","")
 
;get domain from product property - if domain is not set, get domain from host identifier.
set $Domain$ = takeString(0, splitString($DomainRaw$,"/"))
if ($Domain$ = "")
	set $Domain$ = composeString(getSubList(1 : ,splitString("%HostId%",".")),".")
	set $DomainRaw$ = $Domain$ + $DomainRaw$
endif
 
;get ou-path from product property - if ou-path is not set, join client to standard client-ou-path for the domain.
;ou-path will be transformed into ldap-friendly syntax.
set $OUPath$ = ""
for %OU% in getSubList(1 : ,splitString($DomainRaw$,"/")) do set $OUPath$ = "OU=%OU%,"+$OUPath$
if not ($OUPath$ = "")
	for %DC% in splitString($Domain$,".") do set $OUPath$ = $OUPath$+"DC=%DC%,"
	set $OUPath$ = strPart($OUPath$,"1",calculate(strLength($OUPath$)+"-1"))
endif
 
;get username + password from, product properties, hide password value in log
set $Username$  = getProductProperty("username","")
setConfidential getProductProperty("password","")
set $Password$  = getProductProperty("password","")
 
if not ( takeString(0, getOutStreamFromSection('execwith_vbs_check_domain cscript //nologo //e:vbs')) = "0" )
	set $DomainCurrent$ = takeString(0, getOutStreamFromSection('execwith_vbs_get_domain cscript //nologo //e:vbs'))
	;check if client is in domain requested
	if ( $DomainCurrent$ = $Domain$ ) 
		set $OUPathCurrent$ = takeString(0, getOutStreamFromSection('execwith_vbs_get_oupath cscript //nologo //e:vbs'))
		;check if client is already in ou-path requested
		if not ( $OUPathCurrent$ = $OUPath$ )
			showBitmap "%ScriptPath%\domain.png" "Active Directory" 
			message "Relocate to ou-path " + $DomainRaw$
			execwith_vbs_move_oupath cscript //nologo //e:vbs
			;TODO check exitcode adsi
			dosinanicon_gpupdate /WaitOnClose
		else
			comment "Computer is already in the given ou-path"
		endif
	else
		logError "Computer is not part of the domain requested, moving to another ou-path only works within the same domain"
		isFatalError
	endif
else
	logError "Computer is currently not part of a domain"
	isFatalError
endif
 
[execwith_vbs_check_domain]
Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'")
Wscript.Echo obj.PartOfDomain
 
[execwith_vbs_get_domain]
Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'")
Wscript.Echo obj.Domain
 
[execwith_vbs_get_oupath]
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Properties("User ID") = "$Username$"
adoConnection.Properties("Password") = "$Password$"
adoConnection.Properties("Encrypt Password") = True
Set adoCommand = CreateObject("ADODB.Command")
adoConnection.Properties("ADSI Flag") = &H200 Or &H1
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection
adoCommand.CommandText = "Select distinguishedName from 'LDAP://$Domain$' where objectClass='computer' and cn='%PCNAME%'"
adoCommand.Properties("Searchscope") = 2
Set adoRecordSet = adoCommand.Execute
adoRecordSet.MoveFirst
OUPathCurrent = adoRecordSet.Fields("distinguishedName").Value
Wscript.Echo Mid(OUPathCurrent,InStr(OUPathCurrent,",")+1)
 
[execwith_vbs_move_oupath]
Set obj = GetObject("LDAP:")
obj.OpenDSObject "LDAP://w8vrsag08.$Domain$/$OUPath$", "$Username$", "$Password$", 1
res = obj.MoveHere("LDAP://CN=%PCNAME%,$OUPathCurrent$", "CN=%PCNAME%")
Wscript.Quit res
 
[dosinanicon_gpupdate]
gpupdate /force
exit %ERRORLEVEL%
 
[opsiservicecall_unset_username]
"method": "setProductProperty"
"params": [
	"%installingProdName%",
	"username",
	"",
	"%hostid%"
]
 
[opsiservicecall_unset_password]
"method": "setProductProperty"
"params": [
	"%installingProdName%",
	"password",
	"",
	"%hostid%"
]
userspace/active_directory_-_join_leave_relocate_ou.1443635376.txt.gz · Last modified: 2021/08/23 08:37 (external edit)