API documentation

bonsai

LDAPClient

class bonsai.LDAPClient(url, tls=False)

A class for configuring the connection to the directory server.

Parameters:
  • url (str|LDAPURL) – an LDAP URL.
  • tls (bool) – Set True to use TLS connection.
Raises:

TypeError – if the url parameter is not string or not a valid LDAP URL.

LDAPClient.connect(is_async=False, timeout=None, **kwargs)

Open a connection to the LDAP server.

Parameters:
  • is_async (bool) – Set True to use asynchronous connection.
  • timeout (float) – time limit in seconds for the operation.
  • **kwargs – additional keyword arguments that are passed to the async connection object (e.g. an eventloop object as loop parameter).
Returns:

an LDAP connection.

Return type:

LDAPConnection

LDAPClient.get_rootDSE()

Returns the server’s root DSE entry. The root DSE may contain information about the vendor, the naming contexts, the request controls the server supports, the supported SASL mechanisms, features, schema location, and other information.

Returns:the root DSE entry.
Return type:LDAPEntry

An example of getting the root DSE:

>>> client = bonsai.LDAPClient()
>>> client.get_rootDSE()
{'namingContexts': ['dc=bonsai,dc=test'], 'supportedControl': ['2.16.840.1.113730.3.4.18',
'2.16.840.1.113730.3.4.2', '1.3.6.1.4.1.4203.1.10.1', '1.2.840.113556.1.4.319',
'1.2.826.0.1.3344810.2.3', '1.3.6.1.1.13.2', '1.3.6.1.1.13.1', '1.3.6.1.1.12'],
'supportedLDAPVersion': ['3'], 'supportedExtension': ['1.3.6.1.4.1.1466.20037',
'1.3.6.1.4.1.4203.1.11.1', '1.3.6.1.4.1.4203.1.11.3', '1.3.6.1.1.8'],
'supportedSASLMechanisms': ['DIGEST-MD5', 'NTLM', 'CRAM-MD5']}
LDAPClient.set_async_connection_class(conn)

Set the LDAP connection class for asynchronous connection. The default connection class is bonsai.asyncio.AIOLDAPConnection that uses the asyncio event loop.

Parameters:conn (BaseLDAPConnection) – the new asynchronous connection class that is a subclass of LDAPConnection.
Raises:TypeError – if conn parameter is not a subclass of BaseLDAPConnection.

An example to change the default async connection class to a Gevent-based one:

>>> import bonsai
>>> from bonsai.gevent import GeventLDAPConnection
>>> client = bonsai.LDAPClient()
>>> client.set_async_connection_class(GeventLDAPConnection)
>>> client.connect(True)
<bonsai.gevent.geventconnection.GeventLDAPConnection object at 0x7f9b1789c6d8>
LDAPClient.set_auto_page_acquire(val)

Turn on or off the automatic page acquiring during a paged LDAP search. By turning automatic page acquiring on, it is unnecessary to call ldapsearchiter.acquire_next_page(). It will be implicitly called during iteration.

Parameters:val (bool) – enabling/disabling auto page acquiring.
Raises:TypeError – If the parameter is not a bool type.
LDAPClient.set_ca_cert(name)

Set the name of CA certificate. If the underlying libldap library uses the Mozilla NSS as TLS library the name should be the same one in the cert/key database (that specified with LDAPClient.set_ca_cert_dir()), otherwise it can be the name of the CA cert file.

Note

This method has no effect on MS Windows, because WinLDAP searches for the corresponding CA certificate in the cert store. This means that the necessary certificates have to be installed manually in to the cert store.

Parameters:name (str) – the name of the CA cert.
Raises:TypeError – if name parameter is not a string or not None.
LDAPClient.set_ca_cert_dir(path)

Set the directory of the CA cert. If the underlying libldap library uses the Mozilla NSS as TLS library the path should be the path to the existing cert/key database, otherwise it can be the path of the CA cert file.

Note

This method has no effect on MS Windows, because WinLDAP searches for the corresponding CA certificate in the cert store. This means that the necessary certifications have to be installed manually in to the cert store.

Parameters:path (str) – the path to the CA directory.
Raises:TypeError – if path parameter is not a string or not None.
LDAPClient.set_cert_policy(policy)

Set policy about server certification.

Parameters:

policy (str) –

the cert policy could be one of the following strings:

  • try or demand: the server cert will be verified, and if it fail, then the LDAPClient.connect() will raise an error.
  • never or allow: the server cert will be used without any verification.

Raises:
  • TypeError – if the policy parameter is not a string.
  • ValueError – if the policy not one of the four above.

Warning

Set off the cert verification is dangerous. Without verification there is a chance of man-in-the-middle attack.

LDAPClient.set_client_cert(name)

Set the name of client certificate. If the underlying libldap library uses the Mozilla NSS as TLS library the name should be the same one in the cert/key database (that specified with LDAPClient.set_ca_cert_dir()), otherwise it can be the name of the client certificate file.

Note

This method has no effect on MS Windows, because WinLDAP searches for the corresponding client certificate based on the servert’s CA cert in the cert store. This means that the necessary certificates have to be installed manually in to the cert store.

Parameters:name (str) – the name of the client cert.
Raises:TypeError – if name parameter is not a string or not None.
LDAPClient.set_client_key(name)

Set the file that contains the private key that matches the certificate of the client that specified with LDAPClient.set_client_cert()).

Note

This method has no effect on MS Windows, because WinLDAP searches for the corresponding client certificate based on the servert’s CA cert in the cert store. This means that the necessary certificates have to be installed manually in to the cert store.

Parameters:name (str) – the name of the CA cert.
Raises:TypeError – if name parameter is not a string or not None.
LDAPClient.set_credentials(mechanism, user=None, password=None, realm=None, authz_id=None, keytab=None)

Set binding mechanism and credential information. All parameters are optional except the mechanism. Different mechanism applies different credential information and ignores the rest. For example:

  • SIMPLE uses the user (as bind DN) and password.
  • EXTERNAL only uses the authz_id as authorization ID.

For other use-cases see this section about authentication mechanisms.

Parameters:
  • mechanism (str) – the name of the binding mechanism.
  • user (str) – the identification of the binding user.
  • password (str) – the password of the user.
  • realm (str) – the (Kerberos) realm of the user.
  • authz_id (str) – the authorization ID for the user.
  • keytab (str) – path to a Kerberos keytab for authentication.
Raises:

TypeError – if mechanism is not string, or any of the other parameters are not string or None.

>>> from bonsai import LDAPClient
>>> client = LDAPClient()
>>> client.set_credentials("SIMPLE", user="cn=user,dc=bonsai,dc=test", password="secret")
>>> client.connect()
<bonsai.LDAPConnection object at 0x7fadf8976440>
LDAPClient.set_extended_dn(extdn_format)

Set the format of extended distinguished name for LDAP_SERVER_EXTENDED_DN_OID control which extends the entries’ distingushed name with GUID and SID attributes. If the server supports the control, the LDAPEntry objects’ extended_dn attribute will be set (as a string) and the dn attribute will be kept in the simple format.

Setting 0 specifies that the GUID and SID values be returned in hexadecimal string format, while setting 1 will return the GUID and SID values in standard string format. Passing None will remove the control in a format of <GUID=xxxx>;<SID=yyyy>;distinguishedName.

Parameters:

extdn_format (int) – the format of the extended dn. It can be 0, 1 or None.

Raises:
  • TypeError – if the parameter is not int or None.
  • ValueError – if the parameter is not 0, 1 or None.

An example:

>>> client = bonsai.LDAPClient()
>>> client.set_extended_dn(1)
>>> result = conn.search("ou=nerdherd,dc=bonsai,dc=test", 1)
>>> result[0].extended_dn
<GUID=899e4e01-e88d-4dea-ba64-119ed386b61c>;<SID=S-1-5-21-101232111302-1767724339-724445543-12345>;cn=chuck,ou=nerdherd,dc=bonsai,dc=test
>>> result[0].dn
<LDAPDN cn=chuck,ou=nerdherd,dc=bonsai,dc=test>

Note

If the extended dn control is not supported the LDAPEntry’s extended_dn attribute will be None. The LDAP_SERVER_EXTENDED_DN_OID is defined as ‘1.2.840.113556.1.4.529’.

LDAPClient.set_managedsait(val)

Set ManageDsaIT control for LDAP operations. With ManageDsaIT an LDAP referral can be searched, added and modified as a common LDAP entry.

Parameters:val (bool) – enabling/disabling ManageDsaIT control.
Raises:TypeError – If the parameter is not a bool type.
LDAPClient.set_password_policy(ppolicy)

Enable password policy control, if it is provided by the directory server. Setting it True will change the return value of LDAPClient.connect() and LDAPConnection.open() to a tuple of (conn, ctrl) where the conn is an LDAPConnection, the ctrl is a dict of returned password policy control response that contains the oid, the remaining seconds of password expiration, and the number of remaining grace logins. If the password policy control is not available on the server or not supported by the platform the second item in the returned tuple is None, instead of a dictionary.

By enabling the password policy control the server can send additional error messages related to the user’s account and password during conneting to the server and changing entries.

Parameters:ppolicy (bool) – enabling/disabling password policy control.
Raises:TypeError – If the parameter is not a bool type.

An example:

>>> import bonsai
>>> client = bonsai.LDAPClient()
>>> client.set_credentials("SIMPLE", "cn=user,dc=bonsai,dc=test", "secret")
>>> client.set_password_policy(True)
>>> conn, ctrl = client.connect()
>>> conn
<bonsai.ldapconnection.LDAPConnection object at 0x7fa552ab4e28>
>>> ctrl
{'grace': 1, 'expire': 3612, 'oid': '1.3.6.1.4.1.42.2.27.8.5.1'})

Note

Password policy control cannot be used on MS Windows with WinLDAP. In this case after opening a connection the control dictionary will always be None.

LDAPClient.set_raw_attributes(raw_list)

By default the values of the LDAPEntry are in string format. The values of the listed LDAP attribute’s names in raw_list will be kept in bytearray format.

Parameters:

raw_list (list) – a list of LDAP attribute’s names. The elements must be string and unique.

Raises:
  • TypeError – if any of the list’s element is not a string.
  • ValueError – if the item in the lit is not a unique element.

An example:

>>> client = bonsai.LDAPClient()
>>> client.set_raw_attributes(["cn", "sn"])
>>> conn = client.connect()
>>> conn.search("cn=jeff,ou=nerdherd,dc=bonsai,dc=test", 0, attrlist=['cn', 'sn', 'gn'])
[{'dn': <LDAPDN cn=jeff,ou=nerdherd,dc=bonsai,dc=test>, 'sn': [b'Barnes'], 'cn': [b'jeff'],
'givenName': ['Jeff']}]
LDAPClient.set_server_chase_referrals(val)

Turn on or off chasing LDAP referrals by the server. By turning off server-side referral chasing search result can contain LDAPReference objects along with LDAPEntry objects.

Parameters:val (bool) – enabling/disabling LDAP referrals chasing.
Raises:TypeError – If the parameter is not a bool type.
LDAPClient.set_url(url)

Set LDAP url for the client.

Parameters:url (LDAPURL|str) – the LDAP url.
LDAPClient.auto_page_acquire

The status of automatic page acquiring.

LDAPClient.ca_cert

The name of the CA certificate.

LDAPClient.ca_cert_dir

The path to the CA certificate.

LDAPClient.cert_policy

The certification policy.

LDAPClient.client_cert

The name of the client certificate.

LDAPClient.client_key

The key file to the client’s certificate.

LDAPClient.credentials

A dict with the credential information. It cannot be set.

LDAPClient.extended_dn_format

Format of the extended distinguished name. 0 means hexadecimal string format, 1 standard string format. If it is None, then it’s not set.

LDAPClient.managedsait

The status of using ManageDsaIT control.

LDAPClient.mechanism

The chosen mechanism for authentication. It cannot be set.

LDAPClient.password_policy

The status of using password policy.

LDAPClient.raw_attributes

A list of attributes that should be kept in byte format.

LDAPClient.server_chase_referrals

The status of chasing referrals by the server.

LDAPClient.tls

A bool about TLS connection is required. It cannot be set.

LDAPClient.url

The URL of the directory server.

LDAPConnection

class bonsai.LDAPConnection(client: LDAPClient)

Handles synchronous connection to an LDAP server.

Parameters:client (LDAPClient) – a client object.
LDAPConnection.abandon(msg_id)

Abandon an ongoing asynchronous operation associated with the given message id. Note that there is no guarantee that the LDAP server will be able to honor the request, which means the operation could be performed anyway. Nevertheless, it is a good programming paradigm to abandon unwanted operations (e.g after a timeout is exceeded).

Parameters:msg_id (int) – the ID of an ongoing LDAP operation.
LDAPConnection.add(entry, timeout=None)

Add new entry to the directory server.

Parameters:
  • entry (LDAPEntry) – the new entry.
  • timeout (float) – time limit in seconds for the operation.
Returns:

True, if the operation is finished.

Return type:

bool

LDAPConnection.close()

Close LDAP connection.

LDAPConnection.delete(dname, timeout=None, recursive=False)

Remove entry from the directory server.

Parameters:
  • dname (str|LDAPDN) – the string or LDAPDN format of the entry’s DN.
  • timeout (float) – time limit in seconds for the operation.
  • recursive (bool) – remove every entry of the given subtree recursively.
Returns:

True, if the operation is finished.

Return type:

bool

LDAPConnection.fileno()

Return the file descriptor of the underlying socket that is used for the LDAP connection.

Returns:The file descriptor.
Return type:int
LDAPConnection.get_result(msg_id, timeout=None)

Get the result of an ongoing asynchronous operation associated with the given message id. The method blocks the caller until the given timeout parameter is passed or the result is arrived. If the operation is not finished until the timeout, it returns None. If the timeout is None, it returns immediately.

Parameters:
  • msg_id (int) – the ID of an ongoing LDAP operation.
  • timeout (float) – time limit in seconds for waiting on the result.
Returns:

the result of the operation.

Return type:

depending on the type of the operation.

Raises:

bonsai.InvalidMessageID – if the message ID is invalid or the associated operation is already finished

LDAPConnection.open(timeout=None)

Open the LDAP connection.

Parameters:timeout (float) – time limit in seconds for the operation.
Returns:The LDAPConnection object itself.
Return type:LDAPConnection.
LDAPConnection.modify_password(user=None, new_password=None, old_password=None, timeout=None)

Set a new password for the given user.

Parameters:
  • user (str|LDAPDN) – the identification of the user. If not set, the owner of the current LDAP session will be associated.
  • new_password (str) – the new password. If not set, the server will generate one and the new password will be returned by this method.
  • old_password (str) – the current password of the user.
  • timeout (float) – time limit in seconds for the operation.
Returns:

if the new_password is not set, then the generated password, None otherwise.

Return type:

str|None

See also

RFC about the LDAP Password Modify extended operation RFC3062.

LDAPConnection.search(base=None, scope=None, filter_exp=None, attrlist=None, timeout=None, sizelimit=0, attrsonly=False, sort_order=None)

Perform a search on the directory server. A base DN and a search scope is always necessary to perform a search, but these values - along with the attribute’s list and search filter - can also be set with the LDAPClient LDAP URL parameter. The parameters, which are passed to the LDAPConnection.search() method will overrule the previously set ones with the LDAP URL.

Setting sort_order will invoke server side sorting LDAP control, based on the provided attribute list.

>>> from bonsai import LDAPClient
>>> client = LDAPClient("ldap://localhost") # without additional parameters
>>> conn = client.connect()
>>> conn.search("ou=nerdherd,dc=bonsai,dc=test", 1, "(cn=ch*)", ["cn", "sn", "gn"])
[{'dn': <LDAPDN cn=chuck,ou=nerdherd,dc=bonsai,dc=test>, 'sn': ['Bartowski'], 'cn': ['chuck'],
'givenName': ['Chuck']}]
>>> client = LDAPClient("ldap://localhost/ou=nerdherd,dc=bonsai,dc=test?cn,sn,gn?one?(cn=ch*)") # with additional parameters
>>> conn = client.connect()
>>> conn.search()
[{'dn': <LDAPDN cn=chuck,ou=nerdherd,dc=bonsai,dc=test>, 'sn': ['Bartowski'], 'cn': ['chuck'],
'givenName': ['Chuck']}]
>>> conn.search(filter_exp="(cn=j*)")
[{'dn': <LDAPDN cn=jeff,ou=nerdherd,dc=bonsai,dc=test>, 'sn': ['Barnes'], 'cn': ['jeff'],
'givenName': ['Jeff']}]
Parameters:
  • base (str) – the base DN of the search.
  • scope (int) – the scope of the search. An LDAPSearchScope also can be used as value.
  • filter_exp (str) – string to filter the search in LDAP search filter syntax.
  • attrlist (list) – list of attribute’s names to receive only those attributes from the directory server.
  • timeout (float) – time limit in seconds for the search.
  • sizelimit (int) – the number of entries to limit the search.
  • attrsonly (bool) – if it’s set True, search result will contain only the name of the attributes without their values.
  • sort_order (list) – list of attribute’s names to use for server-side ordering, start name with ‘-‘ for descending order.
Returns:

the search result.

Return type:

list

Perform a search that returns a paged search result. The number of entries on a page is limited with the page_size parameter. The return value is an ldapsearchiter which is an iterable object. By default, after returning the last entry on the page it automatically requests the next page from the server until the final page is delivered. This functionality can be disabled by setting the LDAPClient.auto_page_acquire to false. Then the next page can be acquired manually by calling the ldapsearchiter.acquire_next_page() method.

Parameters:
  • base (str) – the base DN of the search.
  • scope (int) – the scope of the search. An LDAPSearchScope also can be used as value.
  • filter_exp (str) – string to filter the search in LDAP search filter syntax.
  • attrlist (list) – list of attribute’s names to receive only those attributes from the directory server.
  • timeout (float) – time limit in seconds for the search.
  • sizelimit (int) – the number of entries to limit the search.
  • attrsonly (bool) – if it’s set True, search result will contain only the name of the attributes without their values.
  • sort_order (list) – list of attribute’s names to use for server-side ordering, start name with ‘-‘ for descending order.
  • page_size (int) – the number of entries on a page.
Returns:

the search result.

Return type:

ldapsearchiter

Perform a search using virtual list view control. To perform the search the server side sort control has to be set with sort_order. The result set will be shifted to the offset or attrvalue and contains the specific number of entries after and before, set with after_count and before_count. The est_list_count is an estimation of the entire searched list that helps to the server to position the target entry.

The result of the operation is a tuple of a list and a dictionary. The dictionary contains the VLV server response: the target position and the real list size. Thi list contains the searched entries.

For further details using these controls please see LDAP controls.

Parameters:
  • base (str) – the base DN of the search.
  • scope (int) – the scope of the search. An LDAPSearchScope also can be used as value.
  • filter_exp (str) – string to filter the search in LDAP search filter syntax.
  • attrlist (list) – list of attribute’s names to receive only those attributes from the directory server.
  • timeout (float) – time limit in seconds for the search.
  • sizelimit (int) – the number of entries to limit the search.
  • attrsonly (bool) – if it’s set True, search result will contain only the name of the attributes without their values.
  • sort_order (list) – list of attribute’s names to use for server-side ordering, start name with ‘-‘ for descending order.
  • offset (int) – an offset of the search result to select a target entry for virtual list view (VLV).
  • before_count (int) – the number of entries before the target entry for VLV.
  • after_count (int) – the number of entries after the target entry for VLV.
  • est_list_count (int) – the estimated content count of the entire list for VLV.
  • attrvalue – an attribute value (of the attribute that is used for sorting) for identifying the target entry for VLV.
Returns:

the search result.

Return type:

(list, dict)

LDAPConnection.whoami(timeout=None)

This method can be used to obtain authorization identity.

Parameters:timeout (float) – time limit in seconds for the operation.
Returns:the authorization ID.
Return type:str

See also

RFC about the LDAP Who am I extended operation RFC4532.

LDAPConnection.closed

A readonly attribute about the connection’s state.

LDAPConnection.is_async

A readonly attribute to define that the connections is asynchronous.

LDAPDN

Class for representing LDAP distinguished names.

See also

RFC about LDAP: String Representation of Distinguished Names RFC4514.

Example for working with LDAPDN objects.

>>> import bonsai
>>> dn = bonsai.LDAPDN("cn=testuser,dc=bonsai,dc=test")
>>> dn
<LDAPDN cn=testuser,dc=bonsai,dc=test>
>>> dn.rdns # Get RDNs in tuple format.
((('cn', 'testuser'),), (('dc', 'bonsai'),), (('dc', 'test'),))
>>> str(dn) # Convert to string.
'cn=testuser,dc=bonsai,dc=test'
>>> dn[1] # Get the second RDN.
'dc=bonsai'
>>> dn[0] # Get the first RDN.
'cn=testuser'
>>> dn[1] = "ou=nerdherd,dc=bonsai" # Change the second RDN.
>>> dn
<LDAPDN cn=testuser,ou=nerdherd,dc=bonsai,dc=test>
>>> other_dn = bonsai.LDAPDN("cn=testuser,ou=nerdherd,dc=bonsai,dc=test")
>>> dn == other_dn
True
>>> dn[1:3] # Get the second and third RDN.
'ou=nerdherd,dc=bonsai'
>>> dn[1:3] = 'ou=buymore,dc=bonsai' # Change them.
>>> dn
<LDAPDN cn=testuser,ou=buymore,dc=bonsai,dc=test>
class bonsai.LDAPDN(strdn: str)

A class for handling valid LDAP distinguished name.

Parameters:strdn (str) – a string representation of LDAP distinguished name.
LDAPDN.__getitem__(idx)

Return the string format of the relative distinguished names in the LDAPDN.

Parameters:idx (int) – the indices of the RDNs.
Returns:the string format of the RDNs.
Return type:str
LDAPDN.__setitem__(idx, value)

Set the string format of the relative distinguished names in the LDAPDN.

Parameters:
  • idx (int) – the indices of the RDNs.
  • value (str) – the new RDNs.
LDAPDN.__eq__(other)

Check equality of two LDAPDN by their string format or their sanitized string format.

LDAPDN.__str__() → str

Return the full string format of the distinguished name.

LDAPDN.rdns

The tuple of relative distinguished name.

LDAPEntry

class bonsai.LDAPEntry(dn[, conn])
LDAPEntry.change_attribute(name, optype, *values)

Change an attribute of the entry with explicit LDAP modification type by listing the values as parameters. An attribute can be removed entirely if the optype is delete and no values are passed. This method can be useful for changing write-only attributes (e.g. passwords).

Parameters:
  • name (str) – the name of the attribute.
  • optype (int) – the operation type, 0 for adding, 1 for deleting and 2 for replacing. An LDAPModOp also can be used as value.
  • *values – the new value or values of the attribute.

Note

It is possible to create an inconsistent state that the server will reject. To get a clean state use LDAPEntry.clear_attribute_changes().

LDAPEntry.clear() → None

Remove all items from the dictionary.

LDAPEntry.clear_attribute_changes(name)

Clear all added and deleted changes of an attribute.

Parameters:name (str) – the name of the attribute.
LDAPEntry.delete(timeout=None, recursive=False)

Remove LDAP entry from the dictionary server.

Parameters:
  • timeout (float) – time limit in seconds for the operation.
  • recursive (bool) – remove every entry of the given subtree recursively.
Returns:

True, if the operation is finished.

Return type:

bool

LDAPEntry.get(key, default=None)

Return the value for key if key is in the LDAPEntry, else default. (Same as dict’s get method.)

LDAPEntry.items(exclude_dn=False)

Same functionality as dict.items() but with an optional exclude_dn keyword-only argument. When exclude_dn is True it returns a generator of the LDAPEntry’s key-value pairs without the dn key and value.

Parameters:exclude_dn (bool) – exclude dn key from the list.
Returns:sequence of key-value pairs.
Return type:dict_items, generator
LDAPEntry.keys(exclude_dn=False)

Same functionality as dict.keys() but with an optional exclude_dn keyword-only argument. When exclude_dn is True it returns a generator of the LDAPEntry’s keys without the dn key.

Parameters:exclude_dn (bool) – exclude dn key from the list.
Returns:sequence of keys.
Return type:dict_keys, generator

Note

Be aware when the exclude_dn argument of LDAPEntry.items(), LDAPEntry.keys() or LDAPEntry.values() is set to True you lose the benefits of dict views and get a generator object that will be sensitive of adding and removing items to the entry.

LDAPEntry.modify(timeout=None)

Send entry’s modifications to the dictionary server.

Parameters:timeout (float) – time limit in seconds for the operation.
Returns:True, if the operation is finished.
Return type:bool
LDAPEntry.rename(newdn, timeout=None, delete_old_rdn=True)

Change the entry’s distinguished name.

Parameters:
  • newdn (str|LDAPDN) – the new DN of the entry.
  • timeout (float) – time limit in seconds for the operation.
  • delete_old_rdn (bool) – remove old RDN with renaming.
Returns:

True, if the operation is finished.

Return type:

bool

LDAPEntry.update(*args, **kwds)

Update the LDAPEntry with the key/value pairs from other, overwriting existing keys. (Same as dict’s update method.)

LDAPEntry.values(exclude_dn=False)

Same functionality as dict.values() but with an optional exclude_dn keyword-only argument. When exclude_dn is True it returns a generator of the LDAPEntry’s values without the value of the dn key.

Parameters:exclude_dn (bool) – exclude dn key from the list.
Returns:sequence of values.
Return type:dict_values, generator
LDAPEntry.connection

The LDAPConnection object of the entry. Needs to be set for any LDAP operations.

LDAPEntry.dn

The distinguished name of the entry.

>>> from bonsai import LDAPEntry
>>> anna = LDAPEntry('cn=anna,ou=nerdherd,dc=bonsai,dc=test')
>>> anna.dn
<LDAPDN cn=anna,ou=nerdherd,dc=bonsai,dc=test>
>>> str(anna.dn)
'cn=anna,ou=nerdherd,dc=bonsai,dc=test'
LDAPEntry.extended_dn

The extended DN of the entry. It is None, if the extended DN control is not set or not supported. The attribute is read-only.

LDAPModOp

class bonsai.LDAPModOp

Enumeration for LDAP modification operations.

LDAPModOp.ADD = 0

For adding new values to the attribute.

LDAPModOp.DELETE = 1

For deleting existing values from the attribute list.

LDAPModOp.REPLACE = 2

For replacing the existing attribute values.

LDAPReference

class bonsai.LDAPReference(client, references)

Object for handling an LDAP reference.

Parameters:
  • client (LDAPClient) – a client object.
  • references (list) – list of valid LDAP URLs (as string or LDAPURL objects).
LDAPReference.client

The LDAP client.

LDAPReference.references

The list of LDAPURLs of the references.

LDAPSearchScope

class bonsai.LDAPSearchScope

Enumeration for LDAP search scopes.

LDAPSearchScope.BASE = 0

For searching only the base DN.

LDAPSearchScope.ONELEVEL = 1

For searching one tree level under the base DN.

LDAPSearchScope.ONE = 1

Alias for LDAPSearchScope.ONELEVEL.

LDAPSearchScope.SUBTREE = 2

For searching the entire subtree, including the base DN.

LDAPSearchScope.SUB = 2

Alias for LDAPSearchScope.SUBTREE.

LDAPURL

See also

RFC about LDAP: Uniform Resource Locator RFC4516.

class bonsai.LDAPURL(str)

LDAP URL object for handling LDAP connection informations, such as hostname, port, LDAP bind DN, search attributes, scope (base,sub or one) filter, and extensions. If strurl is None, then the default url is ldap://localhost:389.

Parameters:strurl (str) – string representation of a valid LDAP URL. Must be started with ldap://, ldaps:// or ldapi://.
Raises:ValueError – if the string parameter is not a valid LDAP URL.

An example of a valid LDAP URL with port number, base DN, list of attributes and search filter:

>>> from bonsai import LDAPURL
>>> url = LDAPURL("ldap://localhost:789/ou=nerdherd,dc=bonsai,dc=test?cn,sn,gn?sub?(cn=c*)")
>>> url
<LDAPURL ldap://localhost:789/ou=nerdherd,dc=bonsai,dc=test?cn,sn,gn?sub?(cn=c*)>
>>> url.basedn
<LDAPDN ou=nerdherd,dc=bonsai,dc=test>
>>> url.attributes
['cn', 'sn', 'gn']
LDAPURL.get_address() → str

Return the full address of the host.

>>> import bonsai
>>> url = bonsai.LDAPURL("ldaps://example.com/cn=test,dc=bonsai,dc=test??sub")
>>> url
<LDAPURL ldaps://example.com:636/cn=test,dc=bonsai,dc=test??sub>
>>> url.get_address()
'ldaps://example.com:636'
LDAPURL.__str__() → str

Returns the full format of LDAP URL.

LDAPURL.attributes

The searching attributes.

LDAPURL.basedn

The LDAP distinguished name for binding.

LDAPURL.host

The hostname.

LDAPURL.port

The portnumber.

LDAPURL.filter_exp

The searching filter expression.

LDAPURL.scope

The searching scope.

LDAPURL.scope_num

Return the searching scope number.

LDAPURL.scheme

The URL scheme.

LDAPValueList

class bonsai.LDAPValueList(items)

Modified list that tracks added and deleted values. It also contains only unique elements. The elements are compared to their lower-cased string representations.

A new LDAPValueList can be created optionally from an existing sequence object.

Parameters:items – a sequence object.
Raises:ValueError – if items has a non-unique element.
LDAPValueList.__contains__(item)

Return key in self.

LDAPValueList.__delitem__(idx)

Delete self[key].

LDAPValueList.__setitem__(idx, value)

Set self[key] to value.

LDAPValueList.__add__(other)

Return self+value.

LDAPValueList.__iadd__(other)

Implement self+=value.

LDAPValueList.__mul__(value)

Return self*value.

LDAPValueList.append(item)

Add a unique item to the end of the LDAPValueList.

Parameters:item – New item.
Raises:ValueError – if the item is not unique.
LDAPValueList.extend(items)

Extend the LDAPValueList by appending all the items in the given list. All element in items must be unique and also not represented in the LDAPValueList.

Parameters:items – List of new items.
Raises:ValueError – if any of the items is already in the list.
LDAPValueList.insert(idx, value)

Insert a unique item at a given position.

Parameters:
  • idx (int) – the position.
  • value – the new item.
Raises:

ValueError – if the item is not unique.

LDAPValueList.remove(value)

Remove the first item from the LDAPValueList whose value is value.

Parameters:value – the item to be removed.
Raises:ValueError – if value is not int the list.
LDAPValueList.pop(idx=-1)

Remove the item at the given position in the LDAPValueList, and return it. If no index is specified, pop() removes and returns the last item in the list.

Parameters:idx (int) – optional index.
LDAPValueList.clear() → None

Remove all items from the LDAPValueList.

LDAPValueList.copy() → src.bonsai.ldapvaluelist.LDAPValueList

Return a shallow copy of the LDAPValueList. This includes the status and the previously added and deleted items.

Return type:LDAPValueList
Returns:The copy of the LDAPValueList.
LDAPValueList.status
The status of the LDAPValueList. The status can be:
  • 0: unchanged.
  • 1: added or deleted item to list.
  • 2: replaced the entire list.

bonsai.asyncio

AIOLDAPConnection

class bonsai.asyncio.AIOLDAPConnection(client, loop=None)

Asynchronous LDAP connection object that works with asyncio. It has the same methods and properties as bonsai.LDAPConnection, but with the exception of bonsai.LDAPConnection.close() and bonsai.LDAPConnection.fileno() all of them are awaitable.

Parameters:
  • client (LDAPClient) – a client object.
  • loop – an asyncio IO loop.

Note

The default asyncio event loop is changed with Python 3.8 on Windows to ProactorEventLoop. Unfortunately, bonsai’s asynio connection requires the old SelectorEventLoop. Make sure to change it back before using the module:

if sys.platform == 'win32':
    import asyncio
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

Getting NotImplementedError from the add_reader method of the event loop may indicate that it has not been properly set.

AIOConnectionPool

class bonsai.asyncio.AIOConnectionPool(client: LDAPClient, minconn: int = 1, maxconn: int = 10, loop=None, **kwargs)

A connection pool that can be used with asnycio tasks. It’s inherited from bonsai.pool.ConnectionPool.

Parameters:
  • client (LDAPClient) – the bonsai.LDAPClient that’s used to create connections.
  • minconn (int) – the minimum number of connections that’s created after the pool is opened.
  • maxconn (int) – the maximum number of connections in the pool.
  • **kwargs – additional keyword arguments that are passed to the bonsai.LDAPClient.connect() method.
Raises:

ValueError – when the minconn is negative or the maxconn is less than the minconn.

bonsai.gevent

GeventLDAPConnection

class bonsai.gevent.GeventLDAPConnection(client: LDAPClient)

Asynchronous LDAP connection object that works with Gevent. It has the same methods and properties as bonsai.LDAPConnection.

Parameters:client (LDAPClient) – a client object.

bonsai.ldif

LDIFReader

class bonsai.LDIFReader(input_file, autoload=True, max_length=76)

Create an object for reading LDAP entries from an LDIF format file as described in RFC 2849.

Parameters:
  • input_file (TextIO) – a file-like input object in text mode.
  • autoload (bool) – allow to automatically load external sources from URL.
  • max_length (int) – the maximal line length of the LDIF file.
Raises:

TypeError – if the input_file is not a file-like object or max_length is not an int.

Example of reading an LDIF file:

import bonsai

with open("./users.ldif") as fileobj:
    reader = bonsai.LDIFReader(fileobj)
    for entry in reader:
        print(entry.dn)
LDIFReader.autoload

Enable/disable autoloading resources in LDIF files.

LDIFReader.input_file

The file-like object of an LDIF file.

LDIFReader.resource_handlers

A dictionary of supported resource types. The keys are the schemes, while the values are functions that expect the full URL parameters and return the loaded content in preferably bytes format.

LDIFWriter

class bonsai.LDIFWriter(output_file, max_length=76)

Create an object for serialising LDAP entries in LDIF format as described in RFC 2849.

Parameters:
  • output_file (TextIO) – a file-like output object in text mode.
  • max_length (int) – the maximal line length of the LDIF file.
Raises:

TypeError – if the output_file is not a file-like object or max_length is not an int.

LDIFWriter.write_entry(entry)

Write an LDAP entry to the file in LDIF format.

Parameters:entry (LDAPEntry) – the LDAP entry to serialise.
>>> import bonsai
>>> output = open("./out.ldif", "w")
>>> writer = bonsai.LDIFWriter(output)
>>> entry = bonsai.LDAPEntry("cn=test")
>>> entry["cn"] = "test"
>>> writer.write_entry(entry)
LDIFWriter.write_entries(entries, write_version=True)

Write multiple LDAP entry to file in LDIF format, separated with newline and with optional version header.

Parameters:
  • entries (list) – list of LDAP entries.
  • write_version (bool) – if it’s True, write version header.
>>> client = bonsai.LDAPClient()
>>> conn = client.connect()
>>> res = conn.search("ou=nerdherd,dc=bonsai,dc=test", bonsai.LDAPSearchScope.ONE)
>>> output = open("./out.ldif", "w")
>>> writer = bonsai.LDIFWriter(output)
>>> writer.write_entries(res)
LDIFWriter.write_changes(entry)

Write an LDAP entry’s changes to file in an LDIF-CHANGE format. Only attribute modifications are serialised.

Parameters:entry (LDAPEntry) – the LDAP entry to serialise.
LDIFWriter.output_file

The file-like object for an LDIF file.

bonsai.pool

ConnectionPool

class bonsai.pool.ConnectionPool(client: LDAPClient, minconn: int = 1, maxconn: int = 10, **kwargs)

A connection pool object for managing multiple open connections.

Parameters:
  • client (LDAPClient) – the bonsai.LDAPClient that’s used to create connections.
  • minconn (int) – the minimum number of connections that’s created after the pool is opened.
  • maxconn (int) – the maximum number of connections in the pool.
  • **kwargs – additional keyword arguments that are passed to the bonsai.LDAPClient.connect() method.
Raises:

ValueError – when the minconn is negative or the maxconn is less than the minconn.

>>> import bonsai
>>> from bonsai.pool import ConnectionPool
>>> client = bonsai.LDAPClient()
>>> pool = ConnectionPool(client, 1, 2)
>>> pool.open()
>>> conn = pool.get()
>>> conn.whomai()
'anonymus'
>>> pool.put(conn)
>>> pool.close()
ConnectionPool.close() → None

Close the pool and all of its managed connections.

ConnectionPool.get()

Get a connection from the connection pool.

Raises:
  • EmptyPool – when the pool is empty.
  • ClosedPool – when the method is called on a closed pool.
Returns:

an LDAP connection object.

ConnectionPool.open() → None

Open the connection pool by initialising the minimal number of connections.

ConnectionPool.put(conn) → None

Put back a connection to the connection pool.

Parameters:

conn (LDAPConnection) – the connection managed by the pool.

Raises:
  • ClosedPool – when the method is called on a closed pool.
  • PoolError – when tying to put back an object that’s not managed by this pool.
ConnectionPool.spawn(*args, **kwargs)

Context manager method that acquires a connection from the pool and returns it on exit. It also opens the pool if it hasn’t been opened before.

Params *args:the positional arguments passed to bonsai.pool.ConnectionPool.get().
Params **kwargs:
 the keyword arguments passed to bonsai.pool.ConnectionPool.get().

Example usage:

import bonsai
from bonsai.pool import ConnectionPool

client = bonsai.LDAPClient()
pool = ConnectionPool(client)
with pool.spawn() as conn:
    print(conn.whoami())

ThreadedConnectionPool

class bonsai.pool.ThreadedConnectionPool(client: LDAPClient, minconn: int = 1, maxconn: int = 10, block: bool = True, **kwargs)

A connection pool that can be shared between threads. It’s inherited from bonsai.pool.ConnectionPool.

Parameters:
  • client (LDAPClient) – the bonsai.LDAPClient that’s used to create connections.
  • minconn (int) – the minimum number of connections that’s created after the pool is opened.
  • maxconn (int) – the maximum number of connections in the pool.
  • block (bool) – when it’s True, the get method will block when no connection is available in the pool.
  • **kwargs – additional keyword arguments that are passed to the bonsai.LDAPClient.connect() method.
Raises:

ValueError – when the minconn is negative or the maxconn is less than the minconn.

ThreadedConnectionPool.get(timeout: Optional[float] = None)

Get a connection from the connection pool.

Parameters:

timeout (float) – a timeout until waiting for free connection.

Raises:
  • EmptyPool – when the pool is empty.
  • ClosedPool – when the method is called on a closed pool.
Returns:

an LDAP connection object.

bonsai.tornado

TornadoLDAPConnection

_bonsai

ldapsearchiter

Helper class for paged search result.

ldapsearchiter.acquire_next_page()

Request the next page of result. Returns with the message ID of the search operation. This method can only be used if the LDAPClient.auto_page_acquire is False.

Returns:an ID of the next search operation.
Return type:int.

Errors

class bonsai.LDAPError

General LDAP error.

class bonsai.LDIFError

General exception that is raised during reading or writing an LDIF file.

class bonsai.AffectsMultipleDSA

Raised, when multiple directory server agents are affected.

class bonsai.AlreadyExists

Raised, when try to add an entry and it already exists in the dictionary.

class bonsai.AuthenticationError

Raised, when authentication is failed with the server.

class bonsai.AuthMethodNotSupported

Raised, when the chosen authentication method is not supported.

class bonsai.ConnectionError

Raised, when client is not able to connect to the server.

class bonsai.ClosedConnection

Raised, when try to perform LDAP operation with closed connection.

class bonsai.InsufficientAccess

Raised, when the user has insufficient access rights.

class bonsai.InvalidDN

Raised, when dn string is not a valid distinguished name.

class bonsai.InvalidMessageID

Raised, when try to get the result with a message ID that belongs to an unpending or already finished operation.

class bonsai.NoSuchAttribute

Raised, when the given attribute of an entry does not exist.

class bonsai.NoSuchObjectError

Raised, when operation (except search) is performed on an entry that is not found in the directory.

class bonsai.NotAllowedOnNonleaf

Raised, when the operation is not allowed on a nonleaf object.

class bonsai.ObjectClassViolation

Raised, when try to add or modify an LDAP entry and it violates the object class rules.

class bonsai.ProtocolError

Raised, when protocol error is happened.

class bonsai.SizeLimitError

Raised, when the search operation exceeds the client side size limit or server side size limit that’s applied to the bound user.

class bonsai.TimeoutError

Raised, when the specified timeout is exceeded.

class bonsai.TypeOrValueExists

Raised, when the attribute already exists or the value has been already assigned.

class bonsai.UnwillingToPerform

Raised, when the server is not willing to handle requests.

class bonsai.PasswordPolicyError

General exception for password policy errors.

class bonsai.AccountLocked

Raised, when the password policy is set, available on the server and the user’s account is locked.

class bonsai.ChangeAfterReset

Raised, when the password policy is set, available on the server and it signifies that the password must be changed before the user will be allowed to perform any operation (except bind and modify).

class bonsai.InsufficientPasswordQuality

Raised, when the password policy is set, available on the server and the user’s password is not strong enough.

class bonsai.MustSupplyOldPassword

Raised, when the password policy is set, available on the server and the existing password is not specified.

class bonsai.PasswordExpired

Raised, when the password policy is set, available on the server and the user’s password is expired.

class bonsai.PasswordInHistory

Raised, when the password policy is set, available on the server and the user’s password is in the history.

class bonsai.PasswordModNotAllowed

Raised, when the password policy is set, available on the server and the user is restricted from changing her password.

class bonsai.PasswordTooShort

Raised, when the password policy is set, available on the server and the user’s password is too short to be set.

class bonsai.PasswordTooYoung

Raised, when the password policy is set, available on the server and the user’s password is too young to be modified.

class bonsai.pool.PoolError

Connection pool related errors.

class bonsai.pool.ClosedPool

Raised, when the connection pool is closed.

class bonsai.pool.EmptyPool

Raised, when the connection pool is empty.

Utility functions

bonsai.utils.escape_attribute_value(attrval)

Escapes the special character in an attribute value based on RFC 4514.

Parameters:attrval (str) – the attribute value.
Returns:The escaped attribute value.
Return type:str
>>> import bonsai
>>> bonsai.escape_attribute_value(",cn=escaped")
'\\,cn\\=escaped'
bonsai.utils.escape_filter_exp(filter_exp)

Escapes the special characters in an LDAP filter based on RFC 4515.

Parameters:filter_exp (str) – the unescaped filter expression.
Returns:the escaped filter expression.
Return type:str
>>> import bonsai
>>> bonsai.escape_filter_exp("(objectclass=*)")
'\\28objectclass=\\2A\\29'
bonsai.get_tls_impl_name()

Return the identification of the underlying TLS implementation that is used by the LDAP library:

>>> bonsai.get_tls_impl_name()
"MozNSS"

The possible return values are: GnuTLS, OpenSSL, MozNSS and SChannel.

Returns:A identification of TLS implementation.
Return type:str
bonsai.get_vendor_info()

Return the vendor’s name and the version number of the LDAP library:

>>> bonsai.get_vendor_info()
("OpenLDAP", 20440)
Returns:A tuple of the vendor’s name and the library’s version.
Return type:tuple
bonsai.has_krb5_support()
Returns:True if the module is built with the optional Kerberos/GSSAPI headers.
Return type:bool
bonsai.set_connect_async(allow)

Disable/enable asynchronous connection for the underlying socket, which means that the socket is set to be non-blocking when it’s enabled. The default setting is True on Linux with newer OpenLDAP library version than 2.4.43, False in any other case. This is an OpenLDAP specific setting (see LDAP_OPT_CONNECT_ASYNC option in the OpenLDAP documentation for further details).

Parameters:allow (bool) – Enabling/disabling async connect mode.

Warning

Experience shows that this is a delicate setting. Even with a newer OpenLDAP, the TLS library version used by libldap might be unable to handle non-blocking sockets correctly.

bonsai.set_debug(debug, level=0)

Set debug mode for the module. Turning it on will provide traceback information of C function calls on the standard output.

If the module uses OpenLDAP, then setting the level parameter to a non-zero integer will also give additional info about the libldap function calls.

Parameters:
  • debug (bool) – Enabling/disabling debug mode.
  • level (int) – The debug level (for OpenLDAP only).