
Ein praktischer Client für ADWS in Golang.
Ein praktischer Client für ADWS in Golang.
Sopa implementiert den ADWS-Protokollstack (MS-NNS + MC-NMF + SOAP) und stellt die folgenden Befehlszeilenfunktionen zur Verfügung:
query: führt LDAP-Filtersuchen über WS-Enumeration Enumerate + Pull-Schleife mit Attributprojektion, Bereichskontrolle (Base/OneLevel/Subtree) und Paginierung durchget: ruft ein einzelnes Objekt anhand des DN über WS-Transfer Get abcreate: erstellt Objekte über WS-Transfer ResourceFactory (eingebaute Typen: user, computer, group, OU, container; oder benutzerdefinierte Objekte aus einer YAML-Vorlage über IMDA AddRequest)delete: entfernt ein Objekt anhand des DN über WS-Transfer Deleteattr: fügt einzelne Attributwerte zu einem vorhandenen Objekt hinzu, ersetzt oder entfernt sie über WS-Transfer Putset-password: setzt ein Kontokennwort über MS-ADCAP SetPasswordchange-password: ändert ein Kontokennwort (erfordert das alte Kennwort) über MS-ADCAP ChangePasswordtranslate-name: konvertiert zwischen DN- und kanonischem Namensformat über TranslateNamegroups: listet Gruppenmitgliedschaften oder Autorisierungsgruppen eines Prinzipals über GetADPrincipalGroupMembership / GetADPrincipalAuthorizationGroup aufmembers: zählt Gruppenmitglieder auf (optional rekursiv) über GetADGroupMemberoptfeature: schaltet optionale AD-Funktionen um (z.B. Papierkorb) über ChangeOptionalFeatureinfo: ruft Topologie-Metadaten (Version, Domäne, Gesamtstruktur, DC-Liste) über GetVersion, GetADDomain, GetADForest, GetADDomainControllers abmex: ruft ADWS-Dienstendpunkt-Metadaten über eine nicht authentifizierte WS-MetadataExchange-Anfrage ab$ go install github.com/Macmod/sopa/cmd/sopa@latest
# Auth-Flags (-u, -p, -d, -k, -H, -c, ...) werden aus Gründen der Übersichtlichkeit weggelassen – siehe Abschnitt Authentifizierung.
# Objekte nach LDAP-Filter durchsuchen
$ sopa [auth_flags] query --dc <DC> --filter '(objectClass=*)'
# Ein einzelnes Objekt nach DN abrufen
$ sopa [auth_flags] get --dc <DC> --dn '<DN>'
# Ein Objekt nach DN löschen
$ sopa [auth_flags] delete --dc <DC> --dn '<DN>'
# Attributwerte bearbeiten
$ sopa [auth_flags] attr add --dc <DC> --dn '<DN>' --attr <ATTR> --value <VALUE>
$ sopa [auth_flags] attr replace --dc <DC> --dn '<DN>' --attr <ATTR> --value <VALUE>
$ sopa [auth_flags] attr delete --dc <DC> --dn '<DN>' --attr <ATTR>
# Objekte erstellen
$ sopa [auth_flags] create user --dc <DC> --name <CN> --pass <INITIAL_PASS>
$ sopa [auth_flags] create computer --dc <DC> --name <CN>
$ sopa [auth_flags] create group --dc <DC> --name <CN> --type GlobalSecurity
$ sopa [auth_flags] create ou --dc <DC> --name <CN>
$ sopa [auth_flags] create container --dc <DC> --name <CN>
$ sopa [auth_flags] create custom --dc <DC> --template <TEMPLATE.yaml>
# Kontokennwörter setzen / ändern (MS-ADCAP)
$ sopa [auth_flags] set-password --dc <DC> --dn '<DN>' --new <NEW_PASS>
$ sopa [auth_flags] change-password --dc <DC> --dn '<DN>' --old <OLD_PASS> --new <NEW_PASS>
# DN <-> kanonischen Namen übersetzen (MS-ADCAP)
# (dieser Aufruf ist größtenteils nutzlos, aber der Vollständigkeit halber beibehalten 😄)
$ sopa [auth_flags] translate-name --dc <DC> --offered DistinguishedName --desired CanonicalName '<DN>'
# Gruppenmitgliedschaften des Prinzipals (MS-ADCAP)
$ sopa [auth_flags] groups --dc <DC> --dn '<DN>' --membership --authz
# Gruppenmitglieder (MS-ADCAP)
$ sopa [auth_flags] members --dc <DC> --dn '<GROUP_DN>' --recursive
# Optionale AD-Funktion umschalten, z.B. Papierkorb (MS-ADCAP)
$ sopa [auth_flags] optfeature --dc <DC> --feature-id <FEATURE_GUID> --enable
# Topologie-Informationen (MS-ADCAP)
$ sopa [auth_flags] info version --dc <DC>
$ sopa [auth_flags] info domain --dc <DC>
$ sopa [auth_flags] info forest --dc <DC>
$ sopa [auth_flags] info dcs --dc <DC>
# ADWS-Dienstendpunkt-Metadaten (nicht authentifiziert – Auth-Flags nicht erforderlich)
$ sopa mex --dc <DC>
Führen Sie sopa ohne Unterbefehl aus, um eine interaktive Shell zu öffnen. Sie verwendet eine einzige Verbindung für alle Befehle und bietet Tab-Vervollständigung.
$ sopa --dc <DC> -u <USER> -p <PASS> -d <DOMAIN>
sopa v1.1.0
Connected dc.corp.local domain=corp.local user=Administrator
Type 'help' for commands or 'exit' to quit.
[corp.local]> query --filter '(objectClass=user)' --attrs sAMAccountName
[corp.local]> get --dn 'CN=Administrator,CN=Users,DC=corp,DC=local'
[corp.local]> exit
Verwenden Sie exit, quit oder Ctrl-D, um die Shell zu verlassen.
Beispielvorlage: examples/custom-create.example.yaml
Vorlagenschema (YAML):
parentDN (Zeichenkette, erforderlich): Container-DNrdn (Zeichenkette, erforderlich): Relativer DN für das neue Objekt (z.B. CN=Foo)attributes (Liste, erforderlich): jedes Element hat:
name (Zeichenkette, erforderlich): Attributname (cn oder addata:cn)type (Zeichenkette, optional): string|int|bool|base64|hex (oder explizit xsd:*), Standardwert stringvalue (Zeichenkette) oder values (Liste von Zeichenketten)Hinweise:
ad:relativeDistinguishedName oder ad:container-hierarchy-parent nicht in die Vorlage ein (sie werden automatisch eingefügt).hex-Werte werden in xsd:base64Binary konvertiert.value: "".--dc akzeptiert einen FQDN, eine IP-Adresse oder kann weggelassen werden.
Da der Hostname des DC manchmal nicht über das Standard-DNS des Netzwerks verfügbar ist, wird dringend empfohlen, immer --dns <DC-IP> zu verwenden, damit sopa für alle Lookups den eigenen DNS-Server des DC verwendet:
# Option 1: sopa alles über das DNS des DC auflösen lassen
$ sopa query --dns 192.168.1.10 -d corp.local -u user -p pass --filter '(objectClass=user)'
Wenn --dc weggelassen wird und --domain angegeben ist, entdeckt sopa automatisch einen DC durch Abfrage von SRV-Einträgen:
_ldap._tcp.<domain> (zuerst versucht)
_kerberos._tcp.<domain> (Fallback)
Das Ziel des Eintrags mit der höchsten Priorität wird verwendet. Dies erfordert, dass der mit --dns angegebene DNS-Server diese SRV-Abfragen beantworten kann – der eigene integrierte DNS-Server des DC (falls vorhanden) sollte dazu in der Lage sein.