
Un client pratico per ADWS in Golang.
Un client pratico per ADWS in Golang.
Sopa implementa lo stack di protocollo ADWS (MS-NNS + MC-NMF + SOAP), esponendo le seguenti funzionalità da riga di comando:
query: esegue ricerche con filtro LDAP tramite il loop WS-Enumeration Enumerate + Pull con proiezione di attributi, controllo dello scope (Base/OneLevel/Subtree) e paginazioneget: recupera un singolo oggetto per DN tramite WS-Transfer Getcreate: crea oggetti tramite WS-Transfer ResourceFactory (tipi incorporati: user, computer, group, OU, container; oppure oggetti personalizzati da un template YAML tramite IMDA AddRequest)delete: rimuove un oggetto per DN tramite WS-Transfer Deleteattr: aggiunge, sostituisce o rimuove singoli valori di attributo su un oggetto esistente tramite WS-Transfer Putset-password: imposta una password dell'account tramite MS-ADCAP SetPasswordchange-password: cambia una password dell'account (richiede la vecchia password) tramite MS-ADCAP ChangePasswordtranslate-name: converte tra formati DN e nome canonico tramite TranslateNamegroups: elenca le appartenenze ai gruppi o i gruppi di autorizzazione di un principal tramite GetADPrincipalGroupMembership / GetADPrincipalAuthorizationGroupmembers: enumera i membri del gruppo (opzionalmente ricorsivi) tramite GetADGroupMemberoptfeature: attiva/disattiva le funzionalità AD opzionali (es. Cestino) tramite ChangeOptionalFeatureinfo: recupera metadati di topologia (versione, dominio, foresta, elenco DC) tramite GetVersion, GetADDomain, GetADForest, GetADDomainControllersmex: recupera metadati dell'endpoint del servizio ADWS tramite una richiesta WS-MetadataExchange non autenticata$ go install github.com/Macmod/sopa/cmd/sopa@latest
# I flag di autenticazione (-u, -p, -d, -k, -H, -c, ...) sono omessi per brevità - vedere la sezione Autenticazione.
# Cerca oggetti per filtro LDAP
$ sopa [auth_flags] query --dc <DC> --filter '(objectClass=*)'
# Recupera un singolo oggetto per DN
$ sopa [auth_flags] get --dc <DC> --dn '<DN>'
# Elimina un oggetto per DN
$ sopa [auth_flags] delete --dc <DC> --dn '<DN>'
# Modifica valori degli attributi
$ 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>
# Crea oggetti
$ 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>
# Imposta / cambia password dell'account (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>
# Traduci DN <-> nome canonico (MS-ADCAP)
# (questa chiamata è per lo più inutile ma mantenuta per completezza 😄)
$ sopa [auth_flags] translate-name --dc <DC> --offered DistinguishedName --desired CanonicalName '<DN>'
# Appartenenze ai gruppi del principal (MS-ADCAP)
$ sopa [auth_flags] groups --dc <DC> --dn '<DN>' --membership --authz
# Membri del gruppo (MS-ADCAP)
$ sopa [auth_flags] members --dc <DC> --dn '<GROUP_DN>' --recursive
# Attiva/disattiva funzionalità AD opzionale, es. Cestino (MS-ADCAP)
$ sopa [auth_flags] optfeature --dc <DC> --feature-id <FEATURE_GUID> --enable
# Informazioni sulla topologia (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>
# Metadati dell'endpoint del servizio ADWS (non autenticato - i flag di autenticazione non sono necessari)
$ sopa mex --dc <DC>
Esegui sopa senza un sottocomando per aprire una shell interattiva. Riutilizza una singola connessione per tutti i comandi e fornisce completamento tramite tab.
$ sopa --dc <DC> -u <USER> -p <PASS> -d <DOMAIN>
sopa v1.1.0
Connesso a dc.corp.local domain=corp.local user=Administrator
Digita 'help' per i comandi o 'exit' per uscire.
[corp.local]> query --filter '(objectClass=user)' --attrs sAMAccountName
[corp.local]> get --dn 'CN=Administrator,CN=Users,DC=corp,DC=local'
[corp.local]> exit
Usa exit, quit o Ctrl-D per uscire dalla shell.
Esempio di template: examples/custom-create.example.yaml
Schema del template (YAML):
parentDN (stringa, obbligatorio): DN del contenitorerdn (stringa, obbligatorio): DN relativo per il nuovo oggetto (es. CN=Foo)attributes (lista, obbligatorio): ogni elemento ha:
name (stringa, obbligatorio): nome dell'attributo (cn o addata:cn)type (stringa, opzionale): string|int|bool|base64|hex (oppure esplicito xsd:*), predefinito stringvalue (stringa) o values (lista di stringhe)Note:
ad:relativeDistinguishedName o ad:container-hierarchy-parent nel template (vengono inseriti automaticamente).hex vengono convertiti in xsd:base64Binary.value: "".--dc accetta un FQDN, un indirizzo IP, o può essere omesso.
Poiché il nome host del DC a volte non è disponibile dal DNS predefinito della rete, si consiglia vivamente di passare sempre --dns <DC-IP> in modo che sopa utilizzi il proprio server DNS del DC per tutte le ricerche:
# Opzione 1: lascia che sopa risolva tutto tramite il DNS del DC
$ sopa query --dns 192.168.1.10 -d corp.local -u user -p pass --filter '(objectClass=user)'
Quando --dc viene omesso e --domain viene fornito, sopa scopre automaticamente un DC
interrogando i record SRV:
_ldap._tcp.<domain> (provato per primo)
_kerberos._tcp.<domain> (fallback)
Viene utilizzato il target del record con priorità più alta. Ciò richiede che il
server DNS indicato da --dns possa rispondere a quelle query SRV - il server DNS
integrato del DC (quando presente) dovrebbe essere in grado di farlo.