Ansible Windows Join Domain and Rejoin Playbooks

0

Automating Windows with Ansible modules is a great way to become more effective, productive, and efficient as a Windows administrator. Ansible provides a number of modules that can allow you to interact with your Windows machines either at the guest level with WinRM or if you are using VMware vSphere, you have access to modules specific to the vSphere platform. One area that Ansible can help with is Windows domain joins. With ansible windows join domain operations can be made much less cumbersome and even automated. In this post, we will take a look at different Ansible windows join domain and rejoin playbooks and see how you can do this in a number of use cases.

Using the win_domain_membership module

Ansible has a purpose-built module for Windows domain joins called win_domain_membership. Using this module, you can join a Windows host to a domain or workgroup. Using the module in a playbook is fairly easy. Ansible gives a good example on the official win_domain_membership site. You can use the module in a domain join playbook like the following:

- hosts: winclient
  gather_facts: no
  tasks:
  - win_domain_membership:
      dns_domain_name: yourdomain.local
      hostname: hostname_you_want_to_join
      domain_admin_user: [email protected]
      domain_admin_password: [email protected]$$w0rd!
      domain_ou_path: "OU=Windows,OU=Servers,DC=yourdomain,DC=local"
      state: domain
    register: domain_state

  - win_reboot:
    when: domain_state.reboot_required

Instead of the above, you can use an inventory file like so:

[winclient]winhost1
winhost2
winhost3

Then, we can use a variable for hostname and loop through the hosts listed in the inventory file.

- hosts: winclient
  gather_facts: no
  tasks:
  - win_domain_membership:
      dns_domain_name: yourdomain.local
      hostname: '{{ inventory_hostname }}'
      domain_admin_user: [email protected]
      domain_admin_password: [email protected]$$w0rd!
      domain_ou_path: "OU=Windows,OU=Servers,DC=yourdomain,DC=local"
      state: domain
    register: domain_state

  - win_reboot:
    when: domain_state.reboot_required

As you will notice, the playbook joins a specific workstation to a Windows domain. This is a very basic representation of how you would want to form up a playbook. You most likely will want to place credentials inside a variables file or vault for better security so the credentials are not placed directly inside the playbook itself.

Also, you could loop through a number of hosts that you want to join by using an inventory file to pass in a number of hosts. You can use the variable {{ inventory_hostname }} to substitute for an explicit name for the hostname entry.

Another really cool part of the win_domain_membership module is that it will automatically reboot your workstation after the domain join is completed. This is shown in the win_reboot section of the playbook.

Ansible vmware_vm_shell

There is another really great module that you can use for Windows join domain operations with Ansible called the vmware_vm_shell module. As you can tell, this is specific to VMware vSphere environments.

The great thing about this module that I really like is that it allows you to interact with your Windows hosts in an out-of-band sort of way. Even if you do not have network connectivity to the Windows guest itself, you can still interact with your Windows guest by way of the vmware_vm_shell.

It uses a connection via VMware Tools that is installed on each Windows host running inside your Vmware vSphere environment. In this way, you can interact with your Windows host and run PowerShell scripts of various kinds.

Below, I am copying a PowerShell script that uses the test-computersecurechannel PowerShell cmdlet to “fix” a busted domain join. First, I am copying the PowerShell script over, then running it, then deleting it from the Windows host.

- name: copy file to vm
    local_action:
      module: vmware_guest_file_operation
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"  
      validate_certs: no
      vm_username: administrator
      vm_password: password
      vm_id: "{{ inventory_hostname }}"
      copy:
          src: "resources/fixdomain.ps1"
          dest: "c:\\windows\\tools\\fixdomain.ps1"
          overwrite: true

  - name: Fix broken domain membership
    local_action:
      module: vmware_vm_shell
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"  
      validate_certs: no
      vm_username: administrator
      vm_password: password
      vm_id: "{{ inventory_hostname }}"
      vm_shell: 'c:\windows\system32\windowspowershell\v1.0\powershell.exe'
      vm_shell_args: '-command "(C:\windows\tools\fixdomain.ps1)"'
      wait_for_process: true


  - name: Remove domain script
    local_action:
      module: vmware_vm_shell
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"  
      validate_certs: no
      vm_username: administrator
      vm_password: password
      vm_id: "{{ inventory_hostname }}"
      vm_shell: 'c:\windows\system32\windowspowershell\v1.0\powershell.exe'
      vm_shell_args: '-command "(Remove-Item -path c:\windows\tools\fixdomain.ps1)"'
      wait_for_process: true

The fixdomain.ps1 scripts looks like this:

$domain = "cloud.local"
$UserName = "CLOUD\administrator"
$Password = "[email protected]$$w0rd1" | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName,$Password
test-computersecurechannel -repair -credential $Credential

You could easily run a different script than the fixdomain.ps1 script and use something like the add-computer –domainname ad.contoso.com -Credential DOMAIN\administrator -restart –force command.

Thoughts and Considerations for Ansible Domain Joins

As you can see, using only these two different Ansible modules, you have a lot of different possibilities for Windows domain join and rejoin operations. A domain join can be a headache to sort out for automation purposes as it can throw a “monkey wrench” into all other automation operations as authentication may rely on domain resources and authentication.

There are a couple of notes to make with the above. The win_domain_membership and vmware_vm_shell modules require that you have a way to authenticate to your Windows host already, so, local credentials.

Also, for a domain rejoin, you will need to use PowerShell as the win_domain_membership module will basically think it has nothing to do if it sees the Windows host is already joined, even if the membership is busted. This is whether the test-computersecurechannel come into play.

Ansible is a great Windows automation tool and can certainly be used for various Windows domain join use cases and even resolving Windows domain trust relationship issues.

StarWind VSAN