- An ansible inventory file that is set as executable will be executed instead of read as a normal inventory. This is called Dynamic Inventory.
- The stdout of the executable should be a JSON file
The dynamic inventory will be called a number of times.
- Once to get a list of hosts
- Once per host with the option "--host HOSTNAME" - to get eventual host variables
I use the following tools to help me create the JSON output.
- ldapsearch - to talk to the AD server
- yq - to get the credentials for a user that can query AD/LDAP
- jq - to format the output as a JSON string
Please verify the following variables:
- ansible_user_vars_file - the file in which you will find the user variable
- ansible_password_vault_file - the vault file in which you will find the password variable
- ansible_user_variable - you can use any variable you like, which resolves to an AD user, but the ansible_user is usually is an AD user
- vault_ansible_password_variable - in our environment we set "ansible_password: {{vault_ansible_password}}" and put the vault_ansible_password in a vault file. Pick a variable that you have in a vault file, that contains the password for a user that can query the AD/LDAP.
- ansible_group_name - The group name that your resulting list will be member of. Default: windows_PC
#!/bin/bash
#====================================================
# Script: inventory.ad
# Description: Fetch a list of computers from an OU
# Author: Magnus Luebeck, KMG Group GmbH
# Date: 2018-11-07
#
# Pre-reqs:
#
# This script heavily depends on jq and yq
#
# sudo apt-get install jq ldap-utils
# sudo pip install yq
#
# * https://yq.readthedocs.io/en/latest/
#
#====================================================
this_dir=$(cd $(dirname $0); pwd)
ldap_server=corp.somewhere.ch
ldap_search_base="OU=Workstations,OU=SOMEWHERE,DC=example,DC=com"
ansible_user_vars_file=$this_dir/group_vars/all/all.yml
ansible_password_vault_file=$this_dir/group_vars/all/vault.yml
ansible_user_variable=ansible_user
ansible_password_variable=vault_ansible_password
ansible_group_name=windows_pc
#--- when ansible calls this script with "--host" to get the host variables,
#--- just ignore it and reply with an empty dictionary "{ }"
[ "x$1" = "x--host" ] && { echo "{ }" ; exit ; }
#--- get the AD user and the password from the ansible_user variable
#--- and the ansible_password from a vault
ldap_user=$( cat $ansible_user_vars_file | yq -r .${ansible_user_variable} )
ldap_password=$( ansible-vault view $ansible_password_vault_file | yq -r .${ansible_password_variable} )
#---jq -R . <=== -R will convert the strings to JSON strings
#---jq -s <=== -s will slurp the input and make it an array,
# which we add to the dictionary key in the variable $ansible_group_name
ldapsearch -H ldap://${ldap_server} -D "$ldap_user" -w $ldap_password -b "${ldap_search_base}" "(objectClass=computer)" name \
| grep "^name" \
| awk '{print $NF}' \
| jq -R . \
| jq -s "{ $ansible_group_name : . }"
Example output:
ops@adm-01:~/ansible-pc$ ./inventories/inventory.ad
{
"windows_pc": [
"MY-COMPUTER-01",
"MY-COMPUTER-02"
]
}
ops@adm-01:~/ansible-pc$ ansible -i inventories/inventory.ad windows_pc --list-hosts
hosts (18):
MY-COMPUTER-01
MY-COMPUTER-02