T-SQL & Active Directory – Abfragen mit ADSI, Linked Server & OpenQuery

ADSI · Linked Server · OpenQuery · Benutzer, Gruppen, Organisationseinheiten direkt aus SQL Server

📖 Grundlagen: Wie verbindet man SQL Server mit Active Directory?

ÜBERBLICK
SQL Server kann über den OLE DB-Anbieter ADSDSOObject (auch als "ADSI" bekannt) auf Active Directory zugreifen. Dazu wird ein Linked Server eingerichtet, der die LDAP-Abfragen über OPENQUERY oder direkt mit SELECT ... FROM LinkedServer... ausführt. So lassen sich Benutzer, Gruppen, Kontakte und Organisationsstrukturen direkt in T‑SQL abfragen – ideal für Berechtigungssynchronisation, Monitoring oder Berichte.
-- Voraussetzung: Der SQL Server-Dienst muss über ausreichende Rechte im AD verfügen. 
-- Typische LDAP-Basis: LDAP://DC=contoso,DC=com 
-- Filter (z.B. (objectClass=user)) holt alle Benutzerobjekte.
💡 Hinweis: Der Zugriff erfolgt nur lesend. Für Schreiboperationen (z. B. Benutzer anlegen) sind andere Techniken (PowerShell, .NET) besser geeignet. Die Abfragen nutzen die ADSI-Provider-Syntax.

🔗 1. Linked Server für ADSI erstellen

KONFIGURATION
Bevor Sie Active Directory abfragen können, muss ein Linked Server vom Typ "OLE DB Provider for Microsoft Directory Services" eingerichtet werden. Dies geschieht einmalig durch einen Systemadministrator.
-- Linked Server "ADSI" erstellen (Provider: ADSDSOObject) 
EXEC sp_addlinkedserver  
@server = 'ADSI',  
@srvproduct = 'Active Directory Services',  
@provider = 'ADSDSOObject',  
@datasrc = 'LDAP://DC=contoso,DC=com'; 
 
-- Optional: Mapping für die aktuelle Anmeldung (für integrierte Sicherheit) 
EXEC sp_addlinkedsrvlogin @rmtsrvname = 'ADSI', @useself = 'true'; 
 
-- Abfrage der Domänenbenutzer über den Linked Server 
SELECT *  
FROM OPENQUERY(ADSI,  
'SELECT Name, sAMAccountName, mail, distinguishedName, title, department 
FROM ''LDAP://DC=contoso,DC=com'' 
WHERE objectClass = ''user'' AND objectCategory = ''person''');
⚙️ Erklärung: Mit sp_addlinkedserver wird ein virtueller Server "ADSI" erstellt. Die LDAP-Pfadangabe muss an Ihre Domäne angepasst werden. Nach erfolgreicher Konfiguration können Sie über OPENQUERY LDAP-Suchanfragen absetzen.

⚡ 2. Active Directory mit OPENQUERY abfragen

STANDARD
Die sicherste und flexibelste Methode ist OPENQUERY. Die LDAP-Anweisung wird als String übergeben – Achten Sie auf einfache Anführungszeichen (doppelte Escaping).
-- Basisabfrage: Alle Benutzer mit Vor- und Nachname, E-Mail, Login 
SELECT  
sAMAccountName AS Loginname, 
Name AS Vollname, 
mail AS Email, 
telephoneNumber AS Telefon, 
department AS Abteilung 
FROM OPENQUERY(ADSI,  
'SELECT sAMAccountName, Name, mail, telephoneNumber, department 
 FROM ''LDAP://DC=contoso,DC=com'' 
 WHERE objectClass = ''user'' AND objectCategory = ''person''  
 AND sAMAccountName IS NOT NULL') 
ORDER BY Name; 
 
-- Ausgabe als Tabelle – kann direkt mit lokalen Tabellen verknüpft werden
📌 Erklärung: Innerhalb der OPENQUERY-Klammer steht eine LDAP-SELECT-Anweisung. Der FROM-Teil enthält den (doppelt gequoteten) Distinguished Name des Root-Suchpfads. Die Attributnamen entsprechen den LDAP-Attributen (z. B. sAMAccountName, mail). Sie können die Abfrage wie ein normales SQL-Select behandeln.

👥 3. Details zu Benutzern – Filtern und erweiterte Attribute

PRAXIS
Mit spezifischen LDAP-Filtern lassen sich nur aktive Benutzer, bestimmte Abteilungen oder Mitarbeiter mit Telefonnummer extrahieren.
-- Nur Benutzer, die nicht deaktiviert sind (userAccountControl: 512 = aktiv) 
SELECT sAMAccountName, Name, mail, userAccountControl 
FROM OPENQUERY(ADSI,  
'SELECT sAMAccountName, Name, mail, userAccountControl 
 FROM ''LDAP://DC=contoso,DC=com'' 
 WHERE objectClass = ''user''  
 AND (userAccountControl = 512 OR userAccountControl = 514) 
 AND sAMAccountName = ''mustermann'''); 
 
-- Alle Benutzer einer bestimmten Organisationseinheit (OU) – Path direkt angeben 
SELECT Name, sAMAccountName, mail 
FROM OPENQUERY(ADSI,  
'SELECT Name, sAMAccountName, mail 
 FROM ''LDAP://OU=IT,DC=contoso,DC=com'' 
 WHERE objectClass = ''user''');
🔍 Wichtige Attribute: userAccountControl gibt den Kontostatus an (2 = deaktiviert, 512 = aktiv, 514 = deaktiviert + Passwort nie abläuft). distinguishedName liefert den kompletten AD-Pfad, manager gibt den Vorgesetzten (DN) zurück.

📁 4. Gruppen & Mitglieder

ERWEITERT
Mit ADSI können Sie auch Gruppenmitgliedschaften ermitteln. Dazu fragt man die Gruppe ab und nutzt das Attribut member (Array von Distinguished Names). Eine vollständige rekursive Auflösung ist auf T‑SQL‑Ebene jedoch schwierig; oft holt man zuerst die DN aller Mitglieder und führt dann eine zweite Abfrage durch.
-- Alle direkten Mitglieder einer Gruppe (z.B. "Domänen-Admins") 
SELECT member AS MemberDN 
FROM OPENQUERY(ADSI,  
'SELECT member  
 FROM ''LDAP://CN=Domain Admins,CN=Users,DC=contoso,DC=com'' 
 WHERE objectClass = ''group'''); 
 
-- Mitglieder auflösen: Mit einer zweiten OPENQUERY die Benutzerdaten laden 
-- (Dazu werden die ausgegebenen DNs in eine IN-Klausel überführt – praktisch über eine Tabelle oder dynamisches SQL) 
 
-- Beispiel für einen festen Benutzer: Mitgliedschaft prüfen 
SELECT * 
FROM OPENQUERY(ADSI,  
'SELECT sAMAccountName, memberOf  
 FROM ''LDAP://CN=maxmustermann,CN=Users,DC=contoso,DC=com'' 
 WHERE objectClass = ''user''');
🌟 Tipp: Die Spalte memberOf eines Benutzerobjekts liefert alle Gruppen (als DN-Liste). Sie kann direkt ausgelesen werden. Mit CTEs und String-Funktionen können Sie die DNs parsen, aber das ist aufwendig. Für tiefgehende Auswertungen empfehlen sich PowerShell (Get-ADGroupMember) oder spezialisierte Tools.

⚙️ 5. Performance, Limits & bewährte Methoden

BEST PRACTICES
ADSI-Abfragen über SQL Server sind nicht für sehr große Domänen (10.000+ Objekte) optimiert. Ein ungefiltertes SELECT * kann Timeouts oder langsame Ausführungen verursachen. Daher immer WHERE-Filter verwenden und nur benötigte Attribute abfragen.
-- Paging und Filter verbessern Performance 
-- Tokenbasierte Suche (z.B. sAMAccountName wie 'adm%') 
SELECT sAMAccountName, Name 
FROM OPENQUERY(ADSI,  
'SELECT sAMAccountName, Name 
 FROM ''LDAP://DC=contoso,DC=com'' 
 WHERE objectClass = ''user''  
 AND sAMAccountName = ''admin*'''); 
 
-- Query-Timeout für Linked Server anpassen (falls nötig) 
EXEC sp_serveroption 'ADSI', 'query timeout', 300; 
 
-- Sicherheit: Vermeiden Sie xp_cmdshell mit Directory Services – nutzen Sie den Linked Server. 
-- Benötigte Berechtigung: Das SQL Server-Servicekonto muss Leseberechtigung in der Domäne haben.
Fazit für die Praxis: Nutzen Sie den Linked Server sparsam. Legen Sie lokale Zwischentabellen an, wenn Sie die AD-Daten wiederholt benötigen (z. B. täglicher Import). Verwenden Sie OPENQUERY mit festen Filtern und vermeiden Sie verteilte Transaktionen (SET XACT_ABORT ON;). Prüfen Sie die Ausführung mit SET FMTONLY OFF, um tatsächliche Metadaten zu erhalten.

🧪 Alternative: Active Directory mit PowerShell (xp_cmdshell)

FÜR FORTGESCHRITTENE
Falls der ADSDSOObject-Provider nicht funktioniert oder Sie komplexe AD-Abfragen (Rekursion, erweiterte Attribute) brauchen, können Sie ein PowerShell-Skript über xp_cmdshell aufrufen und die Ergebnisse in eine temporäre Tabelle schreiben – allerdings ist dies mit zusätzlichen Sicherheitsrisiken verbunden.
-- Aktivieren von xp_cmdshell nur temporär (erfordert Sysadmin-Rechte) 
EXEC sp_configure 'show advanced options', 1; RECONFIGURE; 
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; 
 
-- PowerShell-Befehl, der AD-User als CSV exportiert und in Tabelle lädt 
CREATE TABLE #ADUsers (SamName VARCHAR(100), FullName NVARCHAR(200), Email VARCHAR(200)); 
INSERT INTO #ADUsers 
EXEC xp_cmdshell 'powershell -Command "Get-ADUser -Filter * -Properties Name,SamAccountName,mail | Select SamAccountName,Name,mail | ConvertTo-Csv -NoTypeInformation"'; 
 
-- Nach Gebrauch xp_cmdshell wieder deaktivieren 
EXEC sp_configure 'xp_cmdshell', 0; RECONFIGURE; 
 
-- Vorsicht: Diese Methode ist weniger performant und stellt ein Sicherheitsrisiko dar.
🔐 Sicherheitshinweis: xp_cmdshell sollte nur in kontrollierten Umgebungen und vorübergehend aktiviert werden. Die PowerShell-Variante bietet zwar mehr Flexibilität, ist aber meist langsamer als ein gut konfigurierter ADSI Linked Server.
📌 Wichtig: Die genauen Attributnamen können von Ihrer AD-Struktur abweichen. Testen Sie die Abfragen zuerst mit einem Tool wie Softerra LDAP Browser oder dem ADSI-Editor. Die LDAP-Pfade müssen immer die vollständige Domäne enthalten (z. B. LDAP://DC=meinefirma,DC=local).

📌 Alle Abfragen setzen einen konfigurierten Linked Server "ADSI" voraus. Ersetzen Sie die Domänenbezeichnungen (DC=contoso,DC=com) mit Ihren eigenen Werten.
Mit T‑SQL + ADSI erhalten Sie eine leistungsfähige, direkte LDAP-Schnittstelle ohne zusätzliche Middleware.

© 2025 · Active Directory & T‑SQL · Layout inspiriert von powershelldba.de