
Un client pratique pour ADWS en Golang.
Un client pratique pour ADWS en Golang.
Sopa implémente la pile de protocoles ADWS (MS-NNS + MC-NMF + SOAP), exposant les fonctionnalités en ligne de commande suivantes :
query : exécute des recherches par filtre LDAP via une boucle WS-Enumeration Enumerate + Pull avec projection d'attributs, contrôle de portée (Base/OneLevel/Subtree) et paginationget : récupère un seul objet par DN via WS-Transfer Getcreate : crée des objets via WS-Transfer ResourceFactory (types intégrés : user, computer, group, OU, container ; ou objets personnalisés à partir d'un modèle YAML via IMDA AddRequest)delete : supprime un objet par DN via WS-Transfer Deleteattr : ajoute, remplace ou supprime des valeurs d'attributs individuelles sur un objet existant via WS-Transfer Putset-password : définit un mot de passe de compte via MS-ADCAP SetPasswordchange-password : change un mot de passe de compte (nécessite l'ancien mot de passe) via MS-ADCAP ChangePasswordtranslate-name : convertit entre les formats DN et nom canonique via TranslateNamegroups : liste les appartenances aux groupes ou les groupes d'autorisation d'un principal via GetADPrincipalGroupMembership / GetADPrincipalAuthorizationGroupmembers : énumère les membres d'un groupe (optionnellement récursif) via GetADGroupMemberoptfeature : active/désactive les fonctionnalités AD optionnelles (ex. Corbeille) via ChangeOptionalFeatureinfo : récupère les métadonnées de topologie (version, domaine, forêt, liste des DC) via GetVersion, GetADDomain, GetADForest, GetADDomainControllersmex : récupère les métadonnées du point de terminaison du service ADWS via une requête WS-MetadataExchange non authentifiée$ go install github.com/Macmod/sopa/cmd/sopa@latest
# Les flags d'authentification (-u, -p, -d, -k, -H, -c, ...) sont omis par souci de concision - voir la section Authentification.
# Rechercher des objets par filtre LDAP
$ sopa [auth_flags] query --dc <DC> --filter '(objectClass=*)'
# Récupérer un seul objet par DN
$ sopa [auth_flags] get --dc <DC> --dn '<DN>'
# Supprimer un objet par DN
$ sopa [auth_flags] delete --dc <DC> --dn '<DN>'
# Modifier les valeurs d'attributs
$ 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>
# Créer des objets
$ 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>
# Définir / changer les mots de passe des comptes (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>
# Traduire DN <-> nom canonique (MS-ADCAP)
# (cet appel est surtout inutile mais conservé pour l'exhaustivité 😄)
$ sopa [auth_flags] translate-name --dc <DC> --offered DistinguishedName --desired CanonicalName '<DN>'
# Appartenances aux groupes d'un principal (MS-ADCAP)
$ sopa [auth_flags] groups --dc <DC> --dn '<DN>' --membership --authz
# Membres d'un groupe (MS-ADCAP)
$ sopa [auth_flags] members --dc <DC> --dn '<GROUP_DN>' --recursive
# Activer/désactiver une fonctionnalité AD optionnelle, ex. Corbeille (MS-ADCAP)
$ sopa [auth_flags] optfeature --dc <DC> --feature-id <FEATURE_GUID> --enable
# Informations de topologie (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>
# Métadonnées du point de terminaison du service ADWS (non authentifié - les flags d'auth ne sont pas nécessaires)
$ sopa mex --dc <DC>
Lancez sopa sans sous-commande pour ouvrir un shell interactif. Il réutilise une seule connexion pour toutes les commandes et fournit l'autocomplétion par tabulation.
$ sopa --dc <DC> -u <USER> -p <PASS> -d <DOMAIN>
sopa v1.1.0
Connecté dc.corp.local domaine=corp.local utilisateur=Administrator
Tapez 'help' pour les commandes ou 'exit' pour quitter.
[corp.local]> query --filter '(objectClass=user)' --attrs sAMAccountName
[corp.local]> get --dn 'CN=Administrator,CN=Users,DC=corp,DC=local'
[corp.local]> exit
Utilisez exit, quit ou Ctrl-D pour quitter le shell.
Exemple de modèle : examples/custom-create.example.yaml
Schéma du modèle (YAML) :
parentDN (chaîne, obligatoire) : DN du conteneurrdn (chaîne, obligatoire) : DN relatif pour le nouvel objet (ex. CN=Foo)attributes (liste, obligatoire) : chaque élément a :
name (chaîne, obligatoire) : nom de l'attribut (cn ou addata:cn)type (chaîne, optionnel) : string|int|bool|base64|hex (ou explicite xsd:*), par défaut stringvalue (chaîne) soit values (liste de chaînes)Remarques :
ad:relativeDistinguishedName ou ad:container-hierarchy-parent dans le modèle (ils sont injectés automatiquement).hex sont converties en xsd:base64Binary.value: "".--dc accepte un FQDN, une adresse IP, ou peut être omis.
Comme le nom d'hôte du DC n'est parfois pas disponible depuis le DNS par défaut du réseau, il est fortement recommandé de toujours passer --dns <DC-IP> afin que sopa utilise le propre serveur DNS du DC pour toutes les résolutions :
# Option 1 : laisser sopa tout résoudre via le DNS du DC
$ sopa query --dns 192.168.1.10 -d corp.local -u user -p pass --filter '(objectClass=user)'
Lorsque --dc est omis et que --domain est fourni, sopa découvre un DC
automatiquement en interrogeant les enregistrements SRV :
_ldap._tcp.<domain> (essayé en premier)
_kerberos._tcp.<domain> (solution de repli)