Handling changes to `ansible_user` host/group var for Windows hosts that change Active Directory domain membership

I’m currently using Ansible to automate an Active Directory domain migration. I’m developing playbooks (and modules and, eventually, roles) in a test environment currently, but this particular issue seems applicable to any environment.

My test environment only contains two hosts, both Windows hosts.

One host is a clone of an existing Active Directory domain controller – a domain controller for the source domain of the domain migration I’m going to perform.

The second host is a new server and will be the domain controller for the target domain of the domain migration.

I’ve got a playbook that (successfully) sets-up a newly-created Windows host to server as a domain controller for a new Active Directory domain that is that target domain of the domain migration I’m testing. The final task of that playbook is a script task that promotes the relevant host to be a domain controller for the new domain. And it works! Yay Ansible!

Now I’m working on a playbook to setup the new-domain domain controller host so I can perform the actual Active Directory migration. But now Ansible can’t connect.

Because the two hosts are not initially members of the same domain, I can’t use the same domain account (via NTLM or Kerberos – I’m using NTLM currently) to connect with Ansible. I’ve got host-specific ansible_user variables for both defined.

The problem is that for the second host, initially, before I promote it to be a domain controller for the new domain, I’ve configured the ansible_user to be a local administrator account, i.e. an account for that host itself and not part of a domain. But – and this is specific to Windows and Active Directory – after I promote the host to be a domain controller, local accounts can no longer be used (and, in fact, the local admin account is converted to an admin account for the new domain itself). Effectively, I need to use two different user accounts before and after the promotion.

I think that I might be able to get this to work with a custom dynamic inventory, but a blog post from March about Windows features mentions:

In future releases, we’ll include modules to allow basic management of Windows domains, including domain-join/leave, promotion/demotion of domain controllers, domain user management, and even deployment of entirely new forests/domains.

Anyone know or have an idea how promotion/demotion will work with Ansible’s authentication?

This blog post by TechRabbit describes an idea that seems promising – implement a custom dynamic inventory that leverages an existing (static) inventory defined in the conventional files in the main Ansible repo.

Any other ideas or suggestions would be appreciated.

Thanks,
Kenny

I think I’ve got a workable solution for at least the short term.

I move my hosts file and the host_vars and group_vars directories inside a new inventory directory.

I created a Python script in the inventory directory that just returns the ansible_user host variable for the relevant host in the _meta attribute (for the --list argument).

I removed the ansible_user variable from the relevant host variable file.

I was able to confirm that the variable is now being set by the script by running ansible host-name -m debug -a "var=hostvars[inventory_hostname]".

Right now I’ve simply hard-coded the new value for the ansible_user variable but it should be easy enough to modify it to use some kind of file or database to retrieve that value.

It should also be easy enough to my modify my ‘promote to be a domain controller’ playbook to run a local task to update the same file or database too.

I created a Gist with two Python files.

One creates a SQLite database file with a single host_vars table.

The second is my updated dynamic inventory script. It now retrieves all of the data from the SQLite database table and outputs the data as host variables in the expected JSON format.

Is it crazy to consider encapsulating this setup as an Ansible role itself?