src/ldaptool | ||
.gitignore | ||
.pycodestyle | ||
fmt.sh | ||
LICENSE | ||
lints.sh | ||
pyproject.toml | ||
README.md |
ldaptool
CLI tool to query LDAP/AD servers
- Configuration file to configure "realms"
- DNS domain (mapping to ldap search base as DC labels)
- LDAP servers in that domain
- Bind account
- Integration with password managers
- Various output formats
- Classic LDIF
- JSON stream (with simplified or detailed attribute values)
- CSV
- Markdown table with stretched columns (for viewing in CLI/for monospaces fonts); requires csvlook from csvkit
- HTML
- Decodes certain well-known attributes (UUIDs, Timestamps, SID, userAccountControl)
- Requires server to support RFC 2696: Simple Paged Results for proper pagination
- By default the first 1000 entries are shown, and it errors if there are more results
- Use
--all
to show all results
Virtual attributes
ldaptool
supports constructing new values from existing attributes by adding a :<postprocess>
suffix (which can be chained apart from the length limit).
- Some suffixes support an argument as
:<postprocess>[<arg>]
. - A single integer as postprocess suffix limits the length of the value; it replaces the last character of the output with
…
if it cut something off. - Multi-valued attributes generate multiple virtual attrites; each value is processed individually. (The values are joined afterwards for table output if needed.)
DN handling
DNs are decoded into lists of lists of (name, value)
pairs (the inner list usually contains exactly one entry).
Attributes with a DC
name are considered part of the "domain", everything else belongs to the "path".
(Usually a DN will start with path segments and end with domain segments.)
The path is read from back to front.
The following postprocess hooks are available:
domain
: extracts the domain as DNS FQDN (CN=Someone,OU=Dep1,DC=example,DC=com
becomesexample.com
)path
: extracts the non-domain parts without names and separates them by/
(CN=Someone,OU=Dep1,DC=example,DC=com
becomesDep1/Someone
)fullpath
: uses thedomain
as first segment in a path (CN=Someone,OU=Dep1,DC=example,DC=com
becomesexample.com/Dep1/Someone
)dnslice
: extracts a "slice" from a DN (outer list only); the result is still in DN format.
path
, fullpath
and dnslice
take an optional index/slice as argument, written in python syntax.
For path
and fullpath
this extracts only the given index/slice from the path (fullpath
always includes the full FQDN as first segment), dnslice
operates on the outer list of decoded (lists of) pairs:
dn:dnslice[1:]
ondn: CN=Someone,OU=Dep1,DC=example,DC=com
returnsOU=Dep1,DC=example,DC=com
dn:fullpath[:-1]
ondn: CN=Someone,OU=Dep1,DC=example,DC=com
returnsexample.com/Dep1
dn:path[-1]
ondn: CN=Someone,OU=Dep1,DC=example,DC=com
returnsSomeone
Authentication, Protocol, Ports
ldaptool
always uses TLS for password based authentication, and SASL GSS-API over non-TLS for Kerberos ones.
Config file
Location: ~/.config/ldaptool.yaml
Realms
realms:
EXAMPLE:
domain: "example.com"
servers: server1 server2
account: "bind@example.com"
password_folder: mainaccounts
EXAMPLE.admin:
domain: "example.com"
servers: server1 server2
account: "CN=admin,OU=Admins,DC=example,DC=com"
password_folder: adminaccounts
EXAMPLE.admin2:
domain: "example.com"
servers: server1 server2
account: "CN=admin,OU=Admins,DC=example,DC=com"
password_file: localadmin2
password_folder: adminaccounts
SUB:
domain: "sub.example.com"
servers: subserver1 subserver2
forest_root_domain: "example.com"
The servers
field is a whitespace separates list of hostnames in the domain.
If a password manager is used, the password_file
(defaults to names derived from account
) and password_folder
fields determine the name of the file ("secret") queried from the password manager. Here the following file names would be used:
EXAMPLE
:mainaccounts/bind
EXAMPLE.admin
:adminaccounts/example.com/Admins/admin
EXAMPLE.admin2
:adminaccounts/localadmin2
If the account
field isn't present ldaptool
always uses kerberos; if --krb
is used, account
is ignored.
Windows AD has a concept of a "global catalog" across all domains in a AD Forest; it uses separate ports (3268 without TLS and 3269 with TLS).
The forest_root_domain
field can be used to set a search base for global catalog (--gc
) queries (usually the forest root should be parent domain).
Unless specified with --base
the search base is derived from domain
(or forest_root_domain
with --gc
) as DC=...
for each DNS label.
Script as password manager
password-script: keyring local decrypt
This configures a script as password manager.
Either takes a string (split by shlex.split
) or a list of strings.
The password name is appended as last argument.
keyringer
keyringer:
keyring: yourkeyringname
folder: ldapquery
This configures keyringer
(based on GPG) as password manager.
keyringer
need a "keyring" to search in, and you can (optionally) specify a folder to be
prefixed to the password names created from the realm.
keepass
keepass: /home/me/mypasswords.kdbx
This configures KeePass as password manager; it will prompt for your master password every time.