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

<code winst> [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 </code winst>

Uninstall

<code winst> [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 </code winst>

Update

<code winst> [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%” ] </code winst>

userspace/active_directory_-_join_leave_relocate_ou.1443635294.txt.gz · Last modified: 2021/08/23 08:37 (external edit)