ADMIN

2023

07

2023-06-29T12:00:00

Optimiertes Rechenzentrum

PRAXIS

038

Netzwerkmanagement

Active Directory

Python

Active Directory mit Python verwalten

Schnelle Schlange

von Tam Hanna

Veröffentlicht in Ausgabe 07/2023 - PRAXIS

Mit der Python-Bibliothek PyAD steht Windows-Admins ein Werkzeug zur Verfügung, um die Konfiguration und Verwaltung des Active Directory zu automatisieren. Dabei ist die Bereitstellung von PyAD auf einem Windows-Server im Handumdrehen erledigt und ebnet den Weg für das Verbannen lästiger Routineaufgaben in Python-Skripte.

Bei der Active-Directory-Automatisierung mit Python arbeitet "PyAD" [1] in vielen Umgebungen erfolgreich. Allerdings hat sich der Entwickler vor rund zwei Jahren entschieden, das quelloffene Produkt nicht weiter zu pflegen. Das Fehlen von Pull Requests im Git-Repositorium zeigt jedoch, dass die Bibliothek im Allgemeinen problemlos funktioniert. Aus Platzgründen ist es unmöglich, hier die PyAD-Bibliothek komplett vorzustellen. Wer mehr erfahren will, dem hilft die Dokumentation [2], und der Quellcode ist in GitHub einsehbar. Sehr hilfreich ist auch die Webseite Stack Overflow [3], wo eine Suche nach dem Tag PyAD Dutzende zum Thema passende Fragen samt Antworten liefert.
In der Praxis gilt aber auch, dass die Bibliothek als potenzielles technisches Risiko einzuschätzen ist – sie wirkt immerhin auf das Active Directory. Administratoren, die nicht unbedingt auf Python setzen müssen, sollten Alternativen evaluieren. Außerdem ist ein sorgfältiger Test vor dem Roll-out einer neuen Windows-Server-Version dringend anzuraten.
Python und PyAD-Bibliothek einrichten
Während Unix-Betriebssysteme von Haus aus eine Python-Runtime aufweisen, bringt der in den folgenden Beispielen verwendete Windows Server 2022 keine Python-Unterstützung mit. Das also notwendige Python finden Sie unter [4]. Wir nutzen für unseren Workshop die aktuelle Version 3.11.3 der Skriptsprache und den Windows Installer für 64-Bit-Architekturen. Zwecks einfacherem Handling ist es empfehlenswert, dem Installationsassistenten das Einpflegen der Python-EXE-Datei in den Pfad des Servers zu erlauben. Ansonsten können Sie mit der Option "Install Now" arbeiten – es ist nicht notwendig, die Standardeinstellungen des Installationsassistenten anzupassen. Am Ende der Installation sollten Sie die "Path Limitations" aufheben und danach einen Neustart des Servers durchführen, um die Installation abzuschließen.
Bei der Active-Directory-Automatisierung mit Python arbeitet "PyAD" [1] in vielen Umgebungen erfolgreich. Allerdings hat sich der Entwickler vor rund zwei Jahren entschieden, das quelloffene Produkt nicht weiter zu pflegen. Das Fehlen von Pull Requests im Git-Repositorium zeigt jedoch, dass die Bibliothek im Allgemeinen problemlos funktioniert. Aus Platzgründen ist es unmöglich, hier die PyAD-Bibliothek komplett vorzustellen. Wer mehr erfahren will, dem hilft die Dokumentation [2], und der Quellcode ist in GitHub einsehbar. Sehr hilfreich ist auch die Webseite Stack Overflow [3], wo eine Suche nach dem Tag PyAD Dutzende zum Thema passende Fragen samt Antworten liefert.
In der Praxis gilt aber auch, dass die Bibliothek als potenzielles technisches Risiko einzuschätzen ist – sie wirkt immerhin auf das Active Directory. Administratoren, die nicht unbedingt auf Python setzen müssen, sollten Alternativen evaluieren. Außerdem ist ein sorgfältiger Test vor dem Roll-out einer neuen Windows-Server-Version dringend anzuraten.
Python und PyAD-Bibliothek einrichten
Während Unix-Betriebssysteme von Haus aus eine Python-Runtime aufweisen, bringt der in den folgenden Beispielen verwendete Windows Server 2022 keine Python-Unterstützung mit. Das also notwendige Python finden Sie unter [4]. Wir nutzen für unseren Workshop die aktuelle Version 3.11.3 der Skriptsprache und den Windows Installer für 64-Bit-Architekturen. Zwecks einfacherem Handling ist es empfehlenswert, dem Installationsassistenten das Einpflegen der Python-EXE-Datei in den Pfad des Servers zu erlauben. Ansonsten können Sie mit der Option "Install Now" arbeiten – es ist nicht notwendig, die Standardeinstellungen des Installationsassistenten anzupassen. Am Ende der Installation sollten Sie die "Path Limitations" aufheben und danach einen Neustart des Servers durchführen, um die Installation abzuschließen.
Das Python-Entwicklerteam achtet darauf, die Integration von Erweiterungen einfach zu gestalten. Alle aktuellen Python-Runtimes bringen einen Paketmanager mit, der sich von der Struktur her an den aus Linux bekannten Vorgaben orientiert. Daher lässt sich im Weiteren der pip-Befehl nutzen. Doch aufgepasst: Im Rahmen der erstmaligen Ausführung bietet pip an, ein Update von Version 22.3.1 auf 23.1.2 durchzuführen. Diesem Begehren dürfen Sie für den Einsatz von PyAD auf keinen Fall zustimmen, weil die Bibliothek einen veralteten Installationsbefehl verwendet, der in der neuen Version nicht mehr funktioniert.
Zur Benutzung von PyAD ist die Erweiterung "PyWIN32" erforderlich, die Sie durch Eingabe des Befehls pip install pywin32 einspielen. Die Installation der PyAD-Bibliothek erledigen Sie per pip install PyAD. Das vorherige manuelle Herunterladen von PyWIN32 war erforderlich, weil das PyAD-Entwicklerteam im Bereich der Abhängigkeiten etwas schlampt. Das Repositorium weist keine Abhängigkeit zu PyWIN32 auf, weshalb pip die Unterstützungsbibliothek beim Deployment des Active-Directory-Zugriffsmoduls nicht installiert.
Erste Schritte im Active Directory mit PyAD
Nach dem Neustart des Servers ist eine Arbeitsdatei im PY-Format erforderlich. Als erster Test dient uns dabei folgendes Beispielprogramm:
import pyad
from pyad import aduser
nutzer = pyad.aduser.ADUser.from_cn("Administrator");
print (nutzer);
Dabei repräsentiert "ADUser" ein AD-Nutzerobjekt. Die Methode "PyAD.ad-user.ADUser.from_cn" beschafft das Benutzerobjekt aus dem Domaincontroller, der mit dem gerade aktuellen Benutzerkonto verbunden ist.
Zur Anpassung der Standardeinstellungen für den Verbindungsaufbau zu AD-Instanzen bietet sich die Methode "PyAD.set_defaults" an. Sie erlaubt Konfigurationen, die die Bibliothek danach bei Aufrufen implizit annimmt und für den Verbindungsaufbau einsetzt:
import pyad
from pyad import *
pyad.set_defaults(ldap_server="<Addresse des Domaincontrollers>", username="<Account>", password="<Passwort>")
nutzer = pyad.aduser.ADUser. from_cn("<Benutzer>")
Es ist auch erlaubt, Einstellungen im Rahmen des Verbindungsaufbaus festzulegen. Die Syntax hierzu sieht folgendermaßen aus:
import pyad
from pyad import aduser
nutzer = aduser.ADUser.from_cn ("<Userkonto>", options=dict (ldap_server="<Addresse des Domaincontrollers>"))
Die Bibliothek unterstützt hierbei die Parameter "ldap_server", "gc_server", "ldap_ port", "gc_port", "username", "password" und "ssl". Zu beachten ist, dass die Datenübertragung zwischen Python-Run-time und Active-Directory-Server normalerweise verschlüsselt erfolgt. Ist dies nicht erwünscht, setzen Sie den Wert "SSL" manuell auf "False".
Bild 1: Für PyWIN32 ist die Deprecation-Warnung in pip von Relevanz, daher sollten Sie das Update nicht durchführen.
Benutzer im Active Directory verwalten
Das zurückgelieferte ADUser-Objekt erlaubt nicht nur Einsicht in die für das jeweilige Benutzerkonto geltenden Einstellungen. Die Klasse bietet Methoden an, das Konto zu beeinflussen. Ein gutes Beispiel dafür ist das Ermitteln des Alters des Passworts. Die Methode "nutzer.get_ password_last_set()" liefert ein Date-Time-Objekt zurück, weshalb wir nun den Rückgabewert direkt per Print in die Kommandozeile wandern lassen. Folgender Zweizeiler liefert das Alter des Administratorpassworts:
nutzer = pyad.aduser.ADUser.from_cn ("Administrator");
print (nutzer.get_password_ last_set());
In der Dokumentation unter [5] finden Sie weitere Optionen – interessant ist die Methode "set_expiration(dt)", die das Festlegen des Ablaufdatums des Passworts für Benutzer erlaubt.
Da wir die PyWin-Bibliothek nutzen, sind gewöhnliche Python-DateTime-Objekte nicht kompatibel. Entsprechende Aufrufe scheitern daher mit der Fehlermeldung "TypeError: must be a pywintypes time object (got datetime.date)". Das Konvertieren von Python-Datentypen in PyWin-Zeittypen bringt jedoch einige Probleme mit sich, die Sie mithilfe von [6] lösen.
In der Praxis ist es in vielen Fällen jedoch bequemer, stattdessen eine direkte Instanz eines DateTime-Objekts anzulegen. Dieses lässt sich danach direkt übergeben:
import time
import pywintypes
from pyad import aduser
 
now_seconds = time.time ()
now_pytime = pywintypes.Time (now_seconds+60*60*24*2)
 
nutzer = pyad.aduser.ADUser.from_cn ("Administrator");
print (nutzer.set_expiration( now_pytime));
In unseren Tests kam es beim Versuch, dem Administratorkonto einen Ablaufzeitpunkt zu setzen, gelegentlich zum Fehler "A device attached to the system is not functioning.\r\n". Es ist daher empfehlenswert, Skripte mit Exception Handling auszustatten, um von PyAD verursachte Fehler abzufangen.
Auch neue Benutzer lassen sich mit PyAD in das AD einpflegen. Im einfachsten Fall sieht das folgendermaßen aus:
from pyad import aduser
 
from pyad import *
 
ou = pyad.adcontainer.ADContainer. from_dn("<test.tamoggemon.com>");
new_user = pyad.aduser.ADUser.create("<Neuer Benutzer>", ou, password="<Passwort>")
print (new_user)
Die Methode "PyAD.aduser.ADUser.cre-ate" benötigt neben Benutzernamen und Passwort eine AD-Organisationseinheit (OU), die Sie am einfachsten mit "PyAD. adcontainer.ADContainer.from_dn" beschaffen. Der hierbei übergebene Parameter ist der Distinguished Name des anzusprechenden OU-Containers.
Wichtigster Hemmschuh beim Ausführen des obigen Skripts ist, dass auch für per PyAD eingepflegte Benutzer die im Win-dows-Server hinterlegten Passwortkriterien gelten. Erfüllt das mitgelieferte Passwort diese nicht , verweigert das Ac-tive Directory die Übernahme mit einer Fehlermeldung. Klappt hingegen alles, finden Sie die angelegten Konten wie in Bild 2 zu sehen in "Active Directory Benutzer und Computer".
Bild 2: Ausreichend komplizierte Passwörter führen zur Anzeige der in Python angelegten Benutzerkonten.
Ressourcen im Active Directory suchen
PyAD ist nicht nur zum Erzeugen neuer Inhalte fähig. Die Bibliothek ist auch in der Lage, im Active Directory befindliche Informationen zu extrahieren, um sie über die diversen PyAD-Bearbeitungsfunktionen ansprechbar zu machen. Wie schon zuvor gilt auch hier, dass von PyAD zurückgelieferte Ressourcen von den Berechtigungen abhängen, mit denen das Skript läuft. Die erwähnte Methode zum Festlegen von Verbindungsparametern erlaubt in diesem Bereich das Durchführen von Anpassungen. Beachten Sie allerdings, dass das Speichern von Credentials in Skriptdateien hinsichtlich der Sicherheit nicht empfehlenswert ist.
Der einfachste Weg zur Lokalisierung von Ressourcen führt über die GUIDs (Globally Unique Identifier). Das Active Directory benötigt diese für seine Objekte, aber auch bei der Installation von Programmen werden sie verwendet, um diese eindeutig zu identifizieren. Bei einer GUID handelt sich um eine 16-Byte-Zahl (128 Bit), die zahlreiche Informationen enthält. So etwa die MAC-Adresse der Netzwerkkarte, um sicherzustellen, dass die GUID weltweit eindeutig ist. Wichtig ist, dass Sie in "Active Directory Benutzer und Computer" die in Bild 3 gezeigte Option aktivieren müssen. An eine GUID gelangen Sie dann mit diesem Code:
nutzer = aduser.ADUser.from_guid ("<XXX-XXX-XXX>")
Weil der in Windows Server enthaltene GUID-Editor den Export in die Zwischenablage nicht direkt unterstützt, ist es in vielen Fällen bequemer, konstante Elemente des Active Directory unter Nutzung von Distinguished Names zu ermitteln:
testuser = aduser.ADUser.from_dn ("CN=<tamstester>,DC=<test>,DC=<tamoggemon>,DC=<com>");
print (<testuser>)
Dies führt zur Ausgabe der zum AD-User-Objekt gehörenden Eigenschaften in der Kommandozeile. Alternativ dazu stehen die zuvor besprochenen Methoden zur Verfügung, um den Betriebszustand des Benutzerkontos an die gewünschte Konfiguration anzunähern.
Bild 3: GUIDs erscheinen in "Active Directory Benutzer und Computer" erst nach Aktivierung der Option "Advanced Features".
In der Praxis sind Situationen, in denen Distinguished Name oder GUID zur Verfügung stehen, jedoch vergleichsweise selten. Die Suche im AD ist in PyAD insofern schwierig, als der Suchvorgang zweistufig erfolgt. ADQuery-Objekte verwenden eine an SQL angelehnte Abfragesprache, die die gegen den AD-Server auszuführende Query aufnimmt. Für einen ersten Anlauf bietet sich folgende Parametrisierung an:
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>"
)
Wichtig ist hier, den in "q.execute_query" übergebenen String an die Bedingungen der vorliegenden Domäne anzupassen. Der Rückgabewert ist ein Datenfeld, dessen Werte über einen For-Iterator in die Kommandozeile wandern. So ermitteln Sie wie in Bild 4 gezeigt beispielsweise AD-Gruppen:
for row in q.get_results():
      print (row["<Distinguished-Name>"])
Im nächsten Schritt bietet sich eine fortgeschrittene Analyse an. Hierzu müssen Sie die einzelnen ADGroup-Objekte durch einen weiteren Iterator in ihre Mitglieder zerlegen:
for row in q.get_results():
      group =
    pyad.adgroup.ADGroup.from_dn (row["<DistinguishedName>"])
      print (group)
      for item in group.get_members():
               print (item)
Sie sollten get_results()-Befehle ebenfalls mit Exception Handling absichern. Die zugrundeliegende Bibliothek wirft beim Antreffen leerer AD-Gruppen eine Exception vom Typ "(0, 'Active Directory', 'There is no such object on the server.\r\n', None, 0, -2147217865)" aus, die die Programmausführung normalerweise beendet.
Angemerkt sei, dass das Active Directory in den von PyAD verwendeten Abfragefunktionen "Rate Limiting" implementiert [7, 8]. Dies ist von Bedeutung, wenn eine Anfrage mehr als 1500 Resultate zurückliefert.
Bild 4: PyAD ermittelt eine Liste der Active-Directory-Gruppen.
Bewegung von Objekten im Active Directory
PyAD beschränkt Sie nicht auf das Generieren und Abfragen von AD-Objekten, die Bibliothek ist auch in der Lage, verschiedene Elemente zu erzeugen. Im Allgemeinen kommt dabei eine nach folgendem Schema aufgebaute Methode zum Einsatz:
ou = ADContainer.from_dn("ou=<workstations>, dc=<domain>, dc=<com>")
Dabei ist es wichtig, dass die Variable "OU" eine ADContainer-Instanz ermittelt. Diese legt fest, in welchem Container die vom Python-Code angewiesenen Änderungen zur Ausführung kommen. AD-Container-Objekte unterstützen Sie an dieser Stelle außerdem durch eine Gruppe von Create-Methoden. Die folgende würde beispielsweise einen neuen Computer in die angelegte ADContainer-Gruppe schreiben:
new_computer = ADComputer.create ("<WS-489>", ou)
 
new_group = ADGroup.create("<IT-Abteilung>", security_enabled=True, scope='UNIVERSAL', optional_attributes = {"description":"<Alle IT-Mitarbeiter der Firma>"})
Verfügen Sie über ausreichende Zugriffsrechte, ist es erlaubt, Objekte nach folgendem Schema umzubenennen oder ihren Aufenthaltsort im Active Directory zu verändern. Hier passen wir den Namen einer Workstation an:
computer = ou.create_computer("<WS-490>")
computer.move(ADContainer.from_dn ("ou=<Workstations>, ou=<HR>, dc=<Firma>, dc=<com>"))
computer.rename("<WS-501>")
Und um mit Python Objekte aus dem Active Directory zu löschen, steht Ihnen folgender Befehl zur Verfügung – hier löschen wir eine Workstation:
ADComputer.from_cn ("<WS-500>").delete()
Fazit
Mit PyAD steht ein Python-Werkzeug zur Verfügung, das die Interaktion mit dem Active Directory erleichtert. Mit dem entsprechenden Know-how, in das dieser Workshop den Einstieg liefert, ist die Integration von AD-Konfigurationen in den Python-Workflows umsetzbar. Da allerdings PyAD kaum weiterentwickelt wird, ist ein Neueinstieg sorgfältig abzuwägen. Nutzen Sie bisher keine Python-Skripte und soll Python ausschließlich zur AD-Automatisierung dienen, ist eine Prüfung von Alternativen empfehlenswert. Erfahrene Python-Skriptschreiber erhalten jedoch mit PyAD ein maßgeschneidertes Administrationswerkzeug.
(jp)
Link-Codes
[2] PyAD-Dokumentation: https://zakird.github.io/pyad/
[3] Stack Overflow-Website: https://stackoverflow.com/