Dynamic Inventory using Active Directory / LDAP

Does anyone have code that can pull a dynamic inventory from list of AD OUs? Want to use the windows_update module to patch our servers only in specific OUs.

Maybe I missed it, but I don’t see Windows Active Directory inventory here: https://github.com/ansible/ansible/tree/devel/contrib/inventory

aaron@klep.net wrote:

Does anyone have code that can pull a dynamic inventory from list of AD
OUs? Want to use the windows_update module to patch our servers only in
specific OUs.

Maybe I missed it, but I don't see Windows Active Directory inventory
here: https://github.com/ansible/ansible/tree/devel/contrib/inventory

I've never used it myself but you could try to tweak this one to match
your specific needs:

https://github.com/vincentvdk/ansible_inventory/tree/master/ldap

Ciao, Michael.

We do exactly that: We run ansible in pull mode with AD as inventory.

Maybe you can take a look at the dynamic inventory script we use: https://github.com/ANTS-Framework/ants/blob/master/antslib/inventory/inventory_ad
(Because it is used for ansible-pull, it will only return the current host, but it should give you some ideas.)

Here’s a rather basic and unfinished script which might be of use to you too.

By the way inventory plugins are a thing now, might be worth while making into a inventory plugin rather than a simple inventory script

`

#!/usr/bin/env python

-- coding: utf-8 --

‘’’

Example dynamic inventory script which queries active directory.

Likely to need modification for each environment as there are likely
to be different versions of active directory in use needing different
connection parameters.

To use, create a configuration file in users’s home dir
called .ansible_inventory.cfg

must contain a [domain] section
and then settings for the following values
domain_controller
connect_to_dc_with_ssl (either True or False)
query_domain
query_user
query_pass

‘’’

import class and constants

from ldap3 import Server, Connection, ALL, NTLM, Tls
import json
import ssl
import pprint
import re
import ConfigParser, os

config = ConfigParser.ConfigParser()
user_dir = os.path.expanduser(“~”)
config.read(user_dir + ‘/.ansible_inventory.cfg’)

domain_controller = config.get(‘domain’, ‘domain_controller’)
connect_to_dc_with_ssl= config.getboolean(‘domain’, ‘connect_to_dc_with_ssl’)
query_domain = config.get(‘domain’, ‘query_domain’)
query_user = config.get(‘domain’, ‘query_user’)
query_cred = config.get(‘domain’, ‘query_pass’)

user = query_domain + “\” + query_user

define the server and the connection

TODO see if not doing get_info speeds things up

server = Server(domain_controller, use_ssl=connect_to_dc_with_ssl, get_info=‘ALL’)

TODO remove debug statements

print “showing server information”

print (server.info)

TODO determine if it is quicker to use auto_bind=True

#conn = Connection(server, user=“playnetwork.com\ldapusr”, password=ldappwd, authentication=NTLM, auto_bind=True)

conn = Connection(server, user=user, password=query_cred, authentication=NTLM)

conn.open()
conn.bind()

conn.entries

print(conn)

conn.search(‘CN=Computers, DC=subdomain, DC=yourorg, DC=yourcompany, DC=com’, ‘(objectclass=computer)’, attributes=[“name”,“OperatingSystem”])

#pp = pprint.PrettyPrinter(indent=4)
#pp.pprint (conn.response)

print conn.entries

generate list of all servers (replace ‘HOST’ with something that matches machines you want to be part of inventory

names =
for x in conn.response:
atts = x[‘attributes’]
if ‘operatingSystem’ in atts:
if atts[“operatingSystem”] == ‘Windows Server 2012 R2 Standard’:
if re.match(‘HOST’, atts[‘name’] ):
names.append(atts[‘name’])

TODO add group. This ought to be doable via a server naming convention

TODO add _meta for speed as mentioned here: http://docs.ansible.com/ansible/developing_inventory.html

TODO add vars

conn.unbind()

hosts = {}
hosts[‘hosts’] = names
var = {‘a’:True}

export = {}
export[‘main_group’] = hosts
export[‘main_group_win’] = hosts
#export[‘vars’] = var
`

Hi,

Thanks for sharing, I spent sometime trying to make it work … but I am getting an error about Python module:

python

Python 2.7.5 (default, Oct 30 2018, 23:45:53)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.

import ants

but I still get:

Traceback (most recent call last):
File “/tmp/tt”, line 32, in
from antslib import configer
ImportError: No module named antslib

any ideas ?

Thanks
Sam

Hey Sam

I never tried to import ants directly. Depending on your use case, it might be easier to 1) call it using subprocess or 2) copy the inventory file and adapt it to your needs.

Regards,
Balz

Can you share the script you have so far? I’m not aware of ‘ants’ but sounds like its a problem locating something that you are importing.

Jon