
Um cliente prático para ADWS em Golang.
Um cliente prático para ADWS em Golang.
Sopa implementa a pilha de protocolos ADWS (MS-NNS + MC-NMF + SOAP), expondo os seguintes recursos de linha de comando:
query: executa buscas por filtro LDAP via loop Enumerate + Pull do WS-Enumeration com projeção de atributos, controle de escopo (Base/OneLevel/Subtree) e paginaçãoget: obtém um único objeto por DN via WS-Transfer Getcreate: cria objetos via ResourceFactory do WS-Transfer (tipos internos: user, computer, group, OU, container; ou objetos personalizados a partir de um template YAML via IMDA AddRequest)delete: remove um objeto por DN via WS-Transfer Deleteattr: adiciona, substitui ou remove valores individuais de atributos em um objeto existente via WS-Transfer Putset-password: define uma senha de conta via MS-ADCAP SetPasswordchange-password: altera a senha de uma conta (requer a senha antiga) via MS-ADCAP ChangePasswordtranslate-name: converte entre formatos DN e nome canônico via TranslateNamegroups: lista associações a grupos ou grupos de autorização de um principal via GetADPrincipalGroupMembership / GetADPrincipalAuthorizationGroupmembers: enumera membros de um grupo (opcionalmente recursivo) via GetADGroupMemberoptfeature: ativa/desativa recursos opcionais do AD (ex.: Lixeira) via ChangeOptionalFeatureinfo: recupera metadados de topologia (versão, domínio, floresta, lista de DCs) via GetVersion, GetADDomain, GetADForest, GetADDomainControllersmex: obtém metadados do endpoint do serviço ADWS via uma requisição WS-MetadataExchange não autenticada$ go install github.com/Macmod/sopa/cmd/sopa@latest
# Auth flags (-u, -p, -d, -k, -H, -c, ...) are omitted for brevity - see Authentication section.
# Search objects by LDAP filter
$ sopa [auth_flags] query --dc <DC> --filter '(objectClass=*)'
# Fetch a single object by DN
$ sopa [auth_flags] get --dc <DC> --dn '<DN>'
# Delete an object by DN
$ sopa [auth_flags] delete --dc <DC> --dn '<DN>'
# Edit attribute values
$ 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>
# Create objects
$ 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>
# Set / change account passwords (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>
# Translate DN <-> canonical name (MS-ADCAP)
# (this call is mostly useless but kept for completeness 😄)
$ sopa [auth_flags] translate-name --dc <DC> --offered DistinguishedName --desired CanonicalName '<DN>'
# Principal group memberships (MS-ADCAP)
$ sopa [auth_flags] groups --dc <DC> --dn '<DN>' --membership --authz
# Group members (MS-ADCAP)
$ sopa [auth_flags] members --dc <DC> --dn '<GROUP_DN>' --recursive
# Toggle optional AD feature, e.g. Recycle Bin (MS-ADCAP)
$ sopa [auth_flags] optfeature --dc <DC> --feature-id <FEATURE_GUID> --enable
# Topology info (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 service endpoint metadata (unauthenticated - auth flags not needed)
$ sopa mex --dc <DC>
Execute sopa sem um subcomando para abrir um shell interativo. Ele reutiliza uma única conexão para todos os comandos e oferece preenchimento com tab.
$ 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 ou Ctrl-D para sair do shell.
Exemplo de template: examples/custom-create.example.yaml
Esquema do template (YAML):
parentDN (string, obrigatório): DN do contêinerrdn (string, obrigatório): DN relativo para o novo objeto (ex.: CN=Foo)attributes (lista, obrigatório): cada item possui:
name (string, obrigatório): nome do atributo (cn ou addata:cn)type (string, opcional): string|int|bool|base64|hex (ou xsd:* explícito), padrão stringvalue (string) ou values (lista de strings)Notas:
ad:relativeDistinguishedName ou ad:container-hierarchy-parent no template (são injetados automaticamente).hex são convertidos para xsd:base64Binary.value: "".--dc aceita um FQDN, um endereço IP ou pode ser omitido.
Como o hostname do DC às vezes não está disponível no DNS padrão da rede, é fortemente recomendado passar sempre --dns <IP-DO-DC> para que o sopa use o próprio servidor DNS do DC para todas as consultas:
# Opção 1: deixar o sopa resolver tudo através do DNS do DC
$ sopa query --dns 192.168.1.10 -d corp.local -u user -p pass --filter '(objectClass=user)'
Quando --dc é omitido e --domain é fornecido, o sopa descobre um DC
automaticamente consultando registros SRV:
_ldap._tcp.<domain> (tentado primeiro)
_kerberos._tcp.<domain> (fallback)
O destino do registro de maior prioridade é usado. Isso exige que o
servidor DNS apontado por --dns consiga responder a essas consultas SRV – o próprio
servidor DNS integrado do DC (quando presente) deve ser capaz disso.
# Opção 2: fornecer DC explicitamente sem Kerberos
$ sopa info version --dc 192.168.1.10 --domain corp.local -u user -p pass