Automate Active Directory management with the Python PyAD library

Snappy Python

Searching for Resources

PyAD is not limited to generating new content. The library can also extract information from Active Directory and make it accessible by the various PyAD editing functions. As before, the resources returned by PyAD depend on the permissions with which the script is running. The method referred to earlier for setting connection parameters lets you make some adjustments in this area. Note, however, that storing credentials in script files is not the preferred approach in terms of security.

The simplest way to find resources is by their globally unique identifiers (GUIDs). Active Directory needs them for its objects, but they are also used during the installation of programs for unique identification. A GUID is a 16-byte (128-bit) number that contains a large amount of information (e.g., the MAC address of the network card to ensure that the GUID is globally unique). Make sure you enable the option shown in Figure 3 in Active Directory Users and Computers. You can then get a GUID using:

user = aduser.ADUser.from_guid ("<XXX-XXX-XXX>")
Figure 3: GUIDs appear in the Active Directory Users and Computers window if you enable the Advanced Features option.

Because the GUID editor included in Windows Server does not directly support exporting to the clipboard, it is more convenient in many cases to use distinguished names to determine immutable Active Directory elements:

testuser = aduser.ADUser.from_dn ("CN=tamstester, DC=test, DC=tamoggemon, DC=com");
print (testuser)

At the command line, these lines output the properties belonging to the AD user object. Alternatively, the methods discussed previously are available to adapt the user account's status to something closer to the desired configuration.

In practice, however, the distinguished name or GUID are rarely available. Searching AD is difficult in PyAD because the search process comprises two steps. ADQuery objects use a query language similar to SQL that records the query you want to run against the AD server. The following parameters are useful for an initial attempt:

import pyad.adquery
q = pyad.adquery.ADQuery()
q.execute_query(attributes = ["<Distinguished-Name>","<Description>"], where_clause = "objectClass = '*'",base_dn = "CN=<users>, DC=test, DC=tamoggemon, DC=com"
)

What is important here is to adapt the string passed in q.execute_query to match the current domain. The return value is a data field whose values are pushed to the command line with a for iterator:

for row in q.get_results():
  print (row["<Distinguished-Name>"])

For example, you can determine AD groups as shown in Figure 4.

Figure 4: PyAD finds a list of Active Directory groups.

The next step is a more advanced analysis. You need to break down the AD group objects into their members with another iterator:

for row in q.get_results():
  group = pyad.adgroup.ADGroup.from_dn (row["<DistinguishedName>"])
  print (group)
  for item in group.get_members():
    print (item)

You will also want to protect the get_results() functions with exception handling. The underlying library throws an exception of the type (0, 'Active Directory', 'There is no such object on the server.\r\n', None, 0, -2147217865) if it encounters empty AD groups, and this error usually terminates the program run.

Note that Active Directory implements rate limiting in the query functions used by PyAD [5] [6], which is significant when a query returns more than 1,500 results.

Moving Objects in AD

PyAD does not limit you to generating and querying AD objects. The library can also generate various elements. In general, a method that follows this pattern is used:

ou = ADContainer.from_dn ("ou=<workstations>, dc=<domain>, dc=com")

The ou variable must find an AD container instance, which determines the container in which the changes requested by the Python code will be executed. AD container objects also support you at this point with a number of create methods. For example, the following lines add a new computer to the created AD container group:

new_computer = ADComputer.create ("WS-489", ou)
new_group = ADGroup.create ("<IT Department>", security_enabled=True, scope='UNIVERSAL', optional_attributes = {"description":"<All IT employeees in the company>"})

If your access authorizations are sufficient, you can rename objects or change their locations in Active Directory:

computer = ou.create_computer ("WS-490")
computer.move(ADContainer.from_dn ("ou=<Workstations>, ou=HR, dc=<Company>, dc=com"))
computer.rename("WS-501")

In this case, you are customizing the name of a workstation. The next command deletes Active Directory objects with Python:

ADComputer.from_cn ("WS-500").delete()

in this case, a workstation.

Conclusions

The PyAD Python tool facilitates interaction with Active Directory. With the appropriate know-how, you can integrate AD configurations in Python workflows. However, because PyAD is no longer under active development, you need to consider carefully whether you want to start using it. If you have not used Python scripts thus far, and if you exclusively want to use Python for AD automation, it makes sense to check out the alternatives. However, for experienced Python script writers, PyAD is a useful, customized administration tool.

Because of space limitations, I couldn't cover the PyAD library completely. If you want to learn more, the documentation [7] is a big help, and the source code is available on GitHub [1]. The Stack Overflow [8] website is also very helpful: A search for the "PyAD" tag returns dozens of questions on the topic, along with the answers.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus