Metadata-Version: 2.4
Name: cmem-plugin-ldap
Version: 0.5.0
Summary: Query LDAP directory services such as OpenLDAP or Active Directory.
License: Apache-2.0
License-File: LICENSE
Keywords: eccenca Corporate Memory,plugin
Author: eccenca GmbH
Author-email: cmempy-developer@eccenca.com
Requires-Python: >=3.13,<4.0
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Plugins
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Dist: cmem-plugin-base (>=4.20.0,<5.0.0)
Requires-Dist: ldap3 (>=2.10.2rc4,<3.0.0)
Description-Content-Type: text/markdown

# cmem-plugin-ldap

Query LDAP directory services such as OpenLDAP or Active Directory.

[![eccenca Corporate Memory][cmem-shield]][cmem-link]

This is a plugin for [eccenca Corporate Memory](https://documentation.eccenca.com). You can install it with the [cmemc](https://eccenca.com/go/cmemc) command line client like this:

```
cmemc admin workspace python install cmem-plugin-ldap
```
 [![pypi version](https://img.shields.io/pypi/v/cmem-plugin-ldap)](https://pypi.org/project/cmem-plugin-ldap) [![license](https://img.shields.io/pypi/l/cmem-plugin-ldap)](https://pypi.org/project/cmem-plugin-ldap)
[![poetry][poetry-shield]][poetry-link] [![ruff][ruff-shield]][ruff-link] [![mypy][mypy-shield]][mypy-link] [![copier][copier-shield]][copier] 

## Search LDAP directory

Searches a directory server over LDAP and returns each matching entry as an entity, so that the
people, groups and devices a directory holds can be mapped into a Knowledge Graph. It works with
any LDAPv3 directory, among them OpenLDAP, Active Directory and Apple Open Directory.

### Configuring a search

A search needs the URL of the directory, where to start, what to match and what to return:

| Parameter | Example |
|---|---|
| LDAP URL | `ldaps://directory.example.org:636` |
| Bind DN | `cn=reader,ou=services,dc=example,dc=org` |
| Search base | `ou=people,dc=example,dc=org` |
| Search filter | `(&(objectClass=person)(mail=*))` |
| Attributes | `cn, mail, memberOf` |

Leaving the bind name and password empty binds anonymously. The attributes have to be named one
by one: the entities are described to the workflow while it is being drawn, and `*` would only be
resolved by the directory once the search runs.

### What comes out

One entity per entry, identified by the LDAP URL of that entry as defined by RFC 4516:

```
ldaps://directory.example.org/uid%3Djdoe%2Cou%3Dpeople%2Cdc%3Dexample%2Cdc%3Dorg
```

Each entity carries the distinguished name of the entry, followed by the values of the requested
attributes in the order they were requested. An attribute an entry does not carry produces no
value, which keeps it distinguishable from an attribute that is present and empty, and an
attribute holding several values keeps all of them.

Values arrive in the lexical form a Knowledge Graph expects - timestamps as ISO 8601, booleans as
`true` and `false` - and a value which is not text, such as `jpegPhoto` or `objectSid`, is Base64
encoded. The schema of the directory is read while connecting to make that possible, since a
directory sends every value as text and only its schema says which of them is a timestamp.

### Large directories

Searching is always paged, so a result set is not cut short by the maximum result size of the
directory, which is 1000 entries on a default Active Directory installation. A search which
reaches the configured maximum number of entries stops there and reports a warning saying so.

References to other directory servers are not followed unless this is asked for, since following
one opens an anonymous connection to a server named by the directory rather than by the task.

### Connecting securely

`ldaps://` is encrypted from the start, and an `ldap://` connection can be upgraded with StartTLS
before authenticating. Certificates are validated in both cases. Where the directory uses an
internal certificate authority, configure that authority rather than switching validation off.


[cmem-link]: https://documentation.eccenca.com
[cmem-shield]: https://img.shields.io/endpoint?url=https://documentation.eccenca.com/latest/badge.json
[poetry-link]: https://python-poetry.org/
[poetry-shield]: https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json
[ruff-link]: https://docs.astral.sh/ruff/
[ruff-shield]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json&label=Code%20Style
[mypy-link]: https://mypy-lang.org/
[mypy-shield]: https://www.mypy-lang.org/static/mypy_badge.svg
[copier]: https://copier.readthedocs.io/
[copier-shield]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-purple.json


