Join VM to AD with vRealize Automation 8 or Cloud (Part 2)

This is continuing from my previous article about Joining VM to domain. In this article, I will explain about vRA integration to Ansible to achieve the domain join.

3. Ansible Integration

vRA 8 or vRA cloud has native integration with Ansible. vRA Cloud Assembly blueprint can be configured to trigger multiple Ansible playbooks during VM provisioning and deprovisioning.

We don’t need to setup AD integration in vRA if we use ansible to do AD join, because Ansible can target specific OU during playbook execution

vRA supports using Open Source Ansible and Ansible Tower. For my case, I am using Ansible Open Source. The configuration for vRA to Ansible Tower will be slightly different.

This diagram shows the authentication that I need configured for authentication between all components.

Following are the components needed to be setup:

Ansible User Account

vRA needs an account to be setup in Ansible machine, this account will be used by vRA to connect to Ansible. This account needs to be configured with public and private ssh authentication. Once you have the account, ansible integration endpoint can be setup in vRA as follow.

VM template

VM template used for provisioning need to have the right WinRM configuration. This is to allow ansible to connect to guest VM. See this article from Ansible

https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html

VM template need to be configured to use either Basic or Certificate Authentication. Kerberos will not work at this stage, because windows has not joined domain yet. For my environment, Im using certificate authentication

Ansible Playbook

Ansible playbook to perform AD join for the VM need to be setup in Ansible server. I created 1 playbook to join Domain, if needed to, you can create another playbook to delete computer object from AD, when VM are de-provisioned. For my use case, I don’t need that. My playbook to join VM is

- hosts: windows
  gather_facts: yes
  tasks:
  - win_domain_membership:
      dns_domain_name: "{{ domain }}"
      hostname: "{{ ansible_facts['nodename'] }}"
      domain_admin_user: "{{ vault_adusername }}"
      domain_admin_password: "{{ vault_adpassword }}"
      domain_ou_path: "{{ adpath }}"
      state: domain
    register: domain_state
  - win_reboot:
    when: domain_state.reboot_required

I use a group and host variable in Ansible and also combine with vault secret variable. I think this is a really good feature in Ansible, by using this feature, it offers me two benefit:

  1. I can separate the variable to be used for windows and linux VM
  2. I can encrypt sensitive data in Ansible, which I cannot do in Cloudinit

vRA Blueprint

The blueprint in vRA looks something like this

resources:
  JoinDomain:
    type: Cloud.Ansible
    properties:
      host: '${resource.vm1.*}'
      osType: '${starts_with(input.project_os, "windows") ? "windows" : "linux"}'
      account: ansible2
      username: cloudadmin
      maxConnectionRetries: 3
      groups:
        - windows
      playbooks:
        provision:
          - /etc/ansible/WINjoindomain.yaml
      hostVariables: |
        domain: ${input.project_domain}
        ansible_winrm_cert_pem: /home/cloudadmin/windowscert/cert.pem
        ansible_winrm_cert_key_pem: /home/cloudadmin/windowscert/cert_key.pem
        ansible_winrm_transport: certificate
        ansible_winrm_server_cert_validation: ignore
  vm1:
    type: Cloud.vSphere.Machine
    properties:
      customizationSpec: '${starts_with(input.project_os, "windows") ? "windows" : "linux"}'
      osprefix: '${starts_with(input.project_os, "windows") ? "w" : "l"}'
      image: '${input.project_os}'
      flavor: small
      networks:
        - assignment: static
          network: '${resource.Cloud_vSphere_Network_1.id}'
      constraints:
        - tag: 'location:sydney'

Few parts you can do differently with the blueprint, with this section here

      playbooks:
        provision:
          - /etc/ansible/WINjoindomain.yaml

I only do provision; you can insert de-provision playbook here too.

I am passing host variable from my blueprint, you can hardcode this in Ansible host variable instead of getting it from blueprint

      hostVariables: |
        domain: ${input.project_domain}
        ansible_winrm_cert_pem: /home/cloudadmin/windowscert/cert.pem
        ansible_winrm_cert_key_pem: /home/cloudadmin/windowscert/cert_key.pem
        ansible_winrm_transport: certificate
        ansible_winrm_server_cert_validation: ignore

If somehow, ansible playbook failed during provisioning, you can easily fix the playbook yaml, and re-run the ansible playbook again from vRA UI, by running the update action, this action will try to run the playbook again on existing VM, not re-provision from the beginning

Conclusion

vRA integration to Ansible requires more steps to setup compared to vSphere Custom Spec and Cloud Init approach.  There are also few small bugs with this integration. But other than those, the vRA integration to Ansible looks very solid to me. Although, the steps to configure are longer, the benefit of using Ansible or any other Config Management tools in future, outweigh the initial config we need to do. Once we configured this, we can use it for other features we want to implement to the VM.

In term of security, we can now have the password and all sensitive data securely store in the ansible vault using encryption. We can even secure this further, if we have other secret management solution.

There are also other solutions to join VM to AD such as the use of REST API directly to public cloud or we can use Puppet. But for my use case, vRA integration to Ansible have ticked all my requirements for AD join.

This Post Has One Comment

  1. Mike Triana

    “VM template need to be configured to use either Basic or Certificate Authentication. Kerberos will not work at this stage, because windows has not joined domain yet. For my environment, I’m using certificate authentication”

    How are generating a certificate for the VM if its purpose is to be used as a template? What do you specify for the host name? I would assume that if vRA is provisioning new VMs from this template, they would each get assigned a unique host name, which means they each need their own certificate.

Leave a Reply