Skip to content

Instantly share code, notes, and snippets.

@maglub
Last active May 24, 2019 17:49
Show Gist options
  • Save maglub/6bcb00f5389b512797c14424c4673b99 to your computer and use it in GitHub Desktop.
Save maglub/6bcb00f5389b512797c14424c4673b99 to your computer and use it in GitHub Desktop.
Ansible inventory file - AD integration

Introduction

  • 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

Integration with AD

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

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment