User Tools

Site Tools


userspace:active_directory_-_join_leave_relocate_ou

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

userspace:active_directory_-_join_leave_relocate_ou [2015/09/30 18:25]
larsg
userspace:active_directory_-_join_leave_relocate_ou [2021/08/23 08:37]
Line 1: Line 1:
-====== Active Directory client management, join/leave/relocate ou ====== 
- 
-   * created by LarsG [[lars.gruenheid@civitec.de]] 2015/09/30 
- 
-   * 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, and in theory 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). 
- 
-This package relies on three product properties: 
-   * **domain_ou** 
- 
-''domain_ou'' must follows this syntax: ''[domain.tld][/ou_1/ou_2]'', both segments are independent and optional  
-and only taken into account when joining a domain or relocating to another ou. when a client shall leave a domain, required information are gathered  
-from operating system. 
- 
-if no domain is specified, it's being extracted from host identifier. 
-if no ou is specified, the client will be placed in the default computer ou-path for the domain. 
-each ou needs a leading forward-slash, all have to be in the right order, beginning at the top-most level. 
- 
-   * **username** 
-   * **password** 
- 
-''username'' must include the domain it belongs to, either like ''DOMAIN\username'' or ''username@domain.tld'', and it has to be   
-an account with sufficient privileges to join/unjoin clients to/from the domain(s) you want to manage. 
- 
-if a client currently is in a domain and shall join another, you need one account with sufficient privileges for 
-both domains, f.e. a trusted management domain containing such administrative accounts.  
- 
-otherwise you have to do both steps seperately with different accounts. 
- 
-''username'' and ''password'' are prunned from productproperties upon every successful execution, so that they won't remain for  
-everyone to see in cleartext. //i hope an option for password-masking in productproperties will be available soon.// 
- 
-==== Setup ==== 
-<code winst> 
-[Actions] 
-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> 
- 
- 
- 
-==== Uninstall ==== 
-<code winst> 
-[Actions] 
-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> 
- 
-==== Update ==== 
-Relocating a client to a different ou within the same domain is still giving me some headache, 
-i am currently stuck at the part where the ADSI movehere function actually performs the relocation, 
-it will throw an arror ''Active Directory: not implemented'' (what ever that means). 
- 
-If anyone can get this to work, i wouldn't mind a heads up (; 
- 
-<code winst> 
-[Actions] 
-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> 
  
userspace/active_directory_-_join_leave_relocate_ou.txt ยท Last modified: 2021/08/23 08:37 (external edit)