
Un cliente práctico para ADWS en Golang.
Un cliente práctico para ADWS en Golang.
Sopa implementa la pila de protocolos ADWS (MS-NNS + MC-NMF + SOAP), exponiendo las siguientes funcionalidades desde línea de comandos:
query: ejecuta búsquedas por filtro LDAP mediante el bucle WS-Enumeration Enumerate + Pull con proyección de atributos, control de alcance (Base/OneLevel/Subtree) y paginación.get: obtiene un único objeto por DN mediante WS-Transfer Getcreate: crea objetos mediante ResourceFactory de WS-Transfer (tipos incorporados: user, computer, group, OU, container; u objetos personalizados desde una plantilla YAML mediante IMDA AddRequest)delete: elimina un objeto por DN mediante WS-Transfer Deleteattr: añade, reemplaza o elimina valores de atributos individuales en un objeto existente mediante WS-Transfer Putset-password: establece una contraseña de cuenta mediante MS-ADCAP SetPasswordchange-password: cambia una contraseña de cuenta (requiere la contraseña anterior) mediante MS-ADCAP ChangePasswordtranslate-name: convierte entre DN y nombre canónico mediante TranslateNamegroups: lista membresías de grupo o grupos de autorización de un principal mediante GetADPrincipalGroupMembership / GetADPrincipalAuthorizationGroupmembers: enumera miembros de un grupo (opcionalmente recursivos) mediante GetADGroupMemberoptfeature: activa o desactiva características opcionales de AD (ej. Papelera de reciclaje) mediante ChangeOptionalFeatureinfo: recupera metadatos de topología (versión, dominio, bosque, lista de DC) mediante GetVersion, GetADDomain, GetADForest, GetADDomainControllersmex: obtiene metadatos del endpoint del servicio ADWS mediante una solicitud WS-MetadataExchange no autenticada$ go install github.com/Macmod/sopa/cmd/sopa@latest
# Los flags de autenticación (-u, -p, -d, -k, -H, -c, ...) se omiten por brevedad - consulte la sección Autenticación.
# Buscar objetos por filtro LDAP
$ sopa [auth_flags] query --dc <DC> --filter '(objectClass=*)'
# Obtener un solo objeto por DN
$ sopa [auth_flags] get --dc <DC> --dn '<DN>'
# Eliminar un objeto por DN
$ sopa [auth_flags] delete --dc <DC> --dn '<DN>'
# Editar valores de atributos
$ 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>
# Crear objetos
$ 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>
# Establecer / cambiar contraseñas de cuenta (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>
# Traducir DN <-> nombre canónico (MS-ADCAP)
# (esta llamada es mayormente inútil pero se mantiene por completitud 😄)
$ sopa [auth_flags] translate-name --dc <DC> --offered DistinguishedName --desired CanonicalName '<DN>'
# Membresías de grupo de un principal (MS-ADCAP)
$ sopa [auth_flags] groups --dc <DC> --dn '<DN>' --membership --authz
# Miembros de un grupo (MS-ADCAP)
$ sopa [auth_flags] members --dc <DC> --dn '<GROUP_DN>' --recursive
# Activar/desactivar característica opcional de AD, ej. Papelera de reciclaje (MS-ADCAP)
$ sopa [auth_flags] optfeature --dc <DC> --feature-id <FEATURE_GUID> --enable
# Información de topología (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>
# Metadatos del endpoint del servicio ADWS (no autenticado - no se necesitan flags de autenticación)
$ sopa mex --dc <DC>
Ejecute sopa sin un subcomando para abrir un shell interactivo. Reutiliza una única conexión para todos los comandos y proporciona autocompletado con tabulación.
$ 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
Use exit, quit o Ctrl-D para salir del shell.
Plantilla de ejemplo: examples/custom-create.example.yaml
Esquema de la plantilla (YAML):
parentDN (cadena, obligatorio): DN del contenedorrdn (cadena, obligatorio): DN relativo para el nuevo objeto (ej. CN=Foo)attributes (lista, obligatorio): cada elemento tiene:
name (cadena, obligatorio): nombre del atributo (cn o addata:cn)type (cadena, opcional): string|int|bool|base64|hex (o xsd:* explícito), por defecto stringvalue (cadena) o values (lista de cadenas)Notas:
ad:relativeDistinguishedName ni ad:container-hierarchy-parent en la plantilla (se inyectan automáticamente).hex se convierten a xsd:base64Binary.value: "".--dc acepta un FQDN, una dirección IP, o puede omitirse.
Debido a que el nombre de host del DC a veces no está disponible desde el DNS predeterminado de la red, se recomienda encarecidamente pasar siempre --dns <DC-IP> para que sopa use el propio servidor DNS del DC para todas las resoluciones:
# Opción 1: dejar que sopa resuelva todo a través del DNS del DC
$ sopa query --dns 192.168.1.10 -d corp.local -u user -p pass --filter '(objectClass=user)'
Cuando se omite --dc y se proporciona --domain, sopa descubre un DC
automáticamente consultando registros SRV:
_ldap._tcp.<domain> (intentado primero)
_kerberos._tcp.<domain> (fallback)
Se utiliza el destino del registro de mayor prioridad. Esto requiere que el
servidor DNS apuntado por --dns pueda responder esas consultas SRV; el propio
servidor DNS integrado del DC (cuando está presente) debería ser capaz de ello.