ldaptool/README.md

128 lines
5.4 KiB
Markdown
Raw Normal View History

2023-04-28 02:45:32 +02:00
# 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)
2023-04-28 02:45:32 +02:00
* CSV
2023-04-28 19:29:59 +02:00
* Markdown table with stretched columns (for viewing in CLI/for monospaces fonts); requires csvlook from [csvkit](https://csvkit.readthedocs.io/)
2023-04-28 19:27:40 +02:00
* HTML
2023-04-28 02:45:32 +02:00
* Decodes certain well-known attributes (UUIDs, Timestamps, SID, userAccountControl)
* Requires server to support [RFC 2696: Simple Paged Results](https://www.rfc-editor.org/rfc/rfc2696) for proper pagination
* By default the first 1000 entries are shown, and it errors if there are more results
2023-04-28 16:04:18 +02:00
* Use `--all` to show all results
2023-04-28 02:45:32 +02:00
## 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` becomes `example.com`)
* `path`: extracts the non-domain parts without names and separates them by `/` (`CN=Someone,OU=Dep1,DC=example,DC=com` becomes `Dep1/Someone`)
* `fullpath`: uses the `domain` as first segment in a path (`CN=Someone,OU=Dep1,DC=example,DC=com` becomes `example.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:]` on `dn: CN=Someone,OU=Dep1,DC=example,DC=com` returns `OU=Dep1,DC=example,DC=com`
* `dn:fullpath[:-1]` on `dn: CN=Someone,OU=Dep1,DC=example,DC=com` returns `example.com/Dep1`
* `dn:path[-1]` on `dn: CN=Someone,OU=Dep1,DC=example,DC=com` returns `Someone`
2023-04-28 02:45:32 +02:00
## 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
```yaml
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
```yaml
password-script: keyring local decrypt
```
This configures a script as password manager.
Either takes a string (split by [`shlex.split`](https://docs.python.org/3/library/shlex.html#shlex.split)) or a list of strings.
The password name is appended as last argument.
#### keyringer
```yaml
keyringer:
keyring: yourkeyringname
folder: ldapquery
```
This configures [`keyringer`](https://0xacab.org/rhatto/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.
2023-04-28 14:37:24 +02:00
#### keepass
```yaml
keepass: /home/me/mypasswords.kdbx
```
This configures KeePass as password manager; it will prompt for your master password every time.