Windows Server 2008 introduces one of the coolest features in AD, being IMHO the Read-Only Domain Controller (RODC). The main goal of the RODC is to improve the AD security and to mitigate risks. It is therefore also preferably deployed at the perimeter of the network. Based upon that, three different scenarios/deployments exist:
- RODC in a Branch Office (= primary focus!)
- RODC in the DMZ (under investigation by MS)
- RODC on the internet (under investigation by MS)
With regards to the RODC, Microsoft created a planning and deployment guide. This guide can be found here. Additionally Microsoft also released a RODC Compatibility Pack which can be found here.
The RODC needs to be able to "talk" to a writable W2K8 DC (W2K8 RWDC) for replication, authentication forwarding, etc. In all three scenarios it is very feasible to place a firewall between RWDCs and RODCs, whereas only one or more RODCs can talk to one or more RWDCs. Clients and servers can make LDAP writes, which refer a client to a RWDC, or special writes which are forwarded by the RODC to an RWDC. For more info about this see the presentations (PDFs in RAR files) here and here and here and here.
Joining clients to an AD domain is such an operation for which you normally require to contact an RWDC. However, in those scenarios where the Branch Office has been separated from the Datacenter by a firewall so that only the RODC can contact an RWDC, you cannot join clients in the normal way against an RODC. The reason? Well, only the RODC can contact an RWDC and the clients/servers cannot. Another way is to join the computer in the datacenter first and then ship it to the Branch Office. However, that may not be feasible. Another way is to join the computer against the RODC with a workaround. The steps for that are explained below.
On some RWDC perform the following steps:
(1) Pre-create a computer account and set a custom password on that same computer account:
- From a command line: net computer \\<NetBIOS Name Computer> /add & net user <NetBIOS Name Computer>$ <Password>
(additional attributes must be set afterwards such as "dNSHostName", "servicePrincipalName"!) (Be aware that this way the "userAccountControl" attribute contains an incorrect value. I'm saying "incorrect" because the bit "Password Not Required is also set" and that's something I do not like!)
OR
- From a command line: ADMOD -replacedn XXX-DOMAIN-XXX:_default -add -b "CN=<NetBIOS Name Computer>,OU=<SOME OU>,XXX-DOMAIN-XXX" "objectClass::computer" "sAMAccountName:: <NetBIOS Name Computer>$" "userAccountControl::4096" -kerbenc "unicodePwd::<Password>" "dNSHostName::<NetBIOS Name Computer>.%USERDNSDOMAIN%" "servicePrincipalName:++:HOST/<NetBIOS Name Computer>;HOST/<NetBIOS Name Computer>.%USERDNSDOMAIN%"
(2) Allow the password of the computer account to be cached on the RODC
OR
(3) Force the computer account to be cached at the RODC
- Using ADUC: By selecting the computer account of the RODC and selecting the tab "Password Replication Policy" and clicking the Advanced button and clicking the Prepopulate Passwords button to pre-cache the password on the RODC
OR
- From a command line: REPADMIN /RODCPWDREPL <RODC> <RWDC> "CN=<NetBIOS Name Computer>,OU=<SOME OU>,DC=<DOMAIN>,DC=<TLD>"
On the client or server to be joined to the AD domain using an RODC implement the following script and execute it (it is provided as an attachment to this post also, "DomainJoinAgainstRODC.vbs.txt"):
Const JOIN_DOMAIN = 1 ' Joins a computer to a domain. If this value is not specified, the join is a computer to a workgroup
Const ACCT_CREATE = 2 ' Creates an account on a domain
Const ACCT_DELETE = 4 ' Deletes an account when a domain exists
Const WIN9X_UPGRADE = 16 ' The join operation is part of an upgrade from Windows 98 or Windows 95 to Windows 2000 or Windows NT
Const DOMAIN_JOIN_IF_JOINED = 32 ' Allows a join to a new domain, even if the computer is already joined to a domain
Const JOIN_UNSECURE = 64 ' Performs an unsecured join
Const MACHINE_PASSWORD_PASSED = 128 ' The machine, not the user, password passed. This option is only valid for unsecure joins
Const DEFERRED_SPN_SET = 256 ' Writing SPN and DnsHostName attributes on the computer object should be deferred until the rename that follows the join
Const NETSETUP_JOIN_READONLY = 2048 ' Use an RODC to perform the domain join against
Const INSTALL_INVOCATION = 262144 ' The APIs were invoked during install
strDomain = "ADCORP.LAB" ' The FQDN of the AD domain
strRODC = "RFSRODC1.ADCORP.LAB" ' The FQDN of the RODC to use
strPassword = "Pa$$w0rd" ' The custom password for the computer account
Set objNetwork = CreateObject("WScript.Network")
strComputer = objNetwork.ComputerName ' The NetBIOS name of the local computer
Set objComputer = GetObject("winmgmts:{impersonationLevel=Impersonate}!\\" & strComputer & "\root\cimv2:Win32_ComputerSystem.Name='" & strComputer & "'")
Wscript.echo("### STARTING ###")
Wscript.echo("Trying to join the local computer to the AD domain using an RODC...")
Wscript.echo("")
ReturnValue = objComputer.JoinDomainOrWorkGroup(strDomain & "\" & strRODC, strPassword, NULL, NULL, JOIN_DOMAIN+MACHINE_PASSWORD_PASSED+NETSETUP_JOIN_READONLY)
' List of 'system error codes' (http://msdn.microsoft.com/en-us/library/ms681381.aspx) and
' List of 'network management error codes' (http://msdn.microsoft.com/en-us/library/aa370674(VS.85).aspx)
Select Case ReturnValue
Case 0 strErrDescr = "The operation completed successfully"
Case 5 strErrDescr = "Access is denied"
Case 87 strErrDescr = "The parameter is incorrect"
Case 1326 strErrDescr = "Logon failure: unknown username or bad password"
Case 1355 strErrDescr = "The specified domain either does not exist or could not be contacted"
Case 2691 strErrDescr = "The machine is already joined to the domain"
End Select
Wscript.echo("FQDN AD Domain : '" & strDomain & "'")
Wscript.echo("FQDN RODC : '" & strRODC & "'")
Wscript.echo("Local Computer Name : '" & strComputer & "." & strDomain & "'")
Wscript.echo("Domain Join Result Code : '" & ReturnValue & "'")
Wscript.echo("Domain Join Result Text : '" & strErrDescr & "'")
Wscript.echo("")
Wscript.echo("### FINISHED ###")
Execute the VBS script: CSCRIPT DomainJoinAgainstRODC.vbs
Depending in the current condition of the client you may receive an output similar to the picture below.
When:
Domain Join Result Code : '0'
Domain Join Result Text : 'The operation completed successfully'
Then the client is successfully joined to the AD domain!
Let's analyze a few parts of the script….
(1) The name of the RODC is specified. Why is this required? When a client/server joins an AD domain it queries DNS for DCs that have registered the domain-wide SRV resource records. RODCs by default DO NOT register domain-wide SRV resource records, only site-wide SRV resource records! Because of that, you must specify in the script WHICH DC the client/server must contact for the domain join
(2) You must specify the custom password that has been configured on the computer account in AD
(3) You need to specify the option 'JOIN_DOMAIN' to make sure it joins a DOMAIN and not a WORKGROUP
(4) You need to specify the option 'MACHINE_PASSWORD_PASSED' to make sure you pass the password that has been configured on the AD account and NOT credentials that are allowed to make the join. The authentication/authorization of the domain join occurs by just knowing the password that has been configured on the AD computer account!
(5) You need to specify the option 'NETSETUP_JOIN_READONLY' to make the join is made in READ-ONLY mode
The procedure above works for: Windows Vista (and later), Windows Server 2008 (and later), Windows XP Professional SP2 (and later), Windows Server 2003 SP1 (and later). For both Windows XP Professional and Windows Server 2003 the hotfix specified in MS-KBQ944043_Description of the Windows Server 2008 read-only domain controller compatibility pack for Windows Server 2003 clients and for Windows XP clients *MUST* be installed! You will get a "Domain Join Result Code" of 87 (The parameter is incorrect) when the hotfix is NOT installed! Make sure it is installed!
More information:
Windows 7 (Windows Server 2008 R2) will provide an even cooler way of joining clients/servers to an AD domain. More of that later, so stay tuned!
Cheers,
Jorge
--------------------------------------------------------------------------------------------------
* This posting is provided "AS IS" with no warranties and confers no rights!
* Always test before implementing!
--------------------------------------------------------------------------------------------------
############### Jorge's Quest For Knowledge ###############
######## http://blogs.dirteam.com/blogs/jorge/default.aspx #########
--------------------------------------------------------------------------------------------------