A Python utility library for working with Lightweight Directory Access Protocol (LDAP) filters.
Project description
Python LDAP Filter ·
Build, generate, and validate LDAP filters
A Python 3 utility library for working with Lightweight Directory Access Protocol (LDAP) filters.
This project is a Python port of the node-ldap-filters project. The filters produced by the library are based on RFC 4515.
Note: This project is currently only compatible with Python 3.4 or higher.
Usage
Installation
Install via pip:
pip install ldap-filter
Building a Filter
This library exposes a number of APIs that allow you to build filters programmatically. The logical and attribute methods of the Filter
object can be combined in a number of ways to generate filters ranging from very simple to very complex.
The following is a quick example of how you might build a filter programmatically:
from ldap_filter import Filter
output = Filter.AND([
Filter.attribute('name').equal_to('bob'),
Filter.attribute('mail').ends_with('@example.com'),
Filter.OR([
Filter.attribute('dept').equal_to('accounting'),
Filter.attribute('dept').equal_to('operations')
])
])
print(output.to_string()) # (&(name=bob)(mail=*@example.com)(|(dept=accounting)(dept=operations)))
Attribute Methods
Attribute methods are used to create LDAP attribute filter strings. The Filter.attribute(name)
method returns an Attribute
object that the following filter methods can be applied to.
output = Filter.attribute('name').equal_to('bob') # (name=bob)
Methods:
-
Attribute.present() - Tests if an attribute is present.
- Output:
(attribute=*)
- Output:
-
Attribute.equal_to(value) - Tests if an attribute is equal to the provided
value
.- Output:
(attribute=value)
- Output:
-
Attribute.contains(value) - Tests if an attribute contains the provided
value
.- Output:
(attribute=*value*)
- Output:
-
Attribute.starts_with(value) - Tests if an attribute starts with the provided
value
.- Output:
(attribute=value*)
- Output:
-
Attribute.ends_with(value) - Tests if an attribute ends with the provided
value
.- Output:
(attribute=*value)
- Output:
-
Attribute.approx(value) - Tests if an attribute is an approximate match to the provided
value
.- Output:
(attribute~=value)
- Output:
-
Attribute.gte(value) - Tests if an attribute is greater than or equal to the provided
value
.- Output:
(attribute>=value)
- Output:
-
Attribute.lte(value) - Tests if an attribute is less than or equal to the provided
value
.- Output:
(attribute<=value)
- Output:
-
Attribute.raw(value) - Allows for a custom filter with escaped
value
output.- Output:
(attribute=value)
- Output:
Logical Methods
Logical methods are used to aggregate simple attribute filters. You can nest as many logical methods as needed to produce complex filters.
output = Filter.OR([
Filter.attribute('name').equal_to('bob'),
Filter.attribute('name').equal_to('bill')
])
print(output) # (|(name=bob)(name=bill))
Methods:
-
Filter.AND(filt) - Accepts a list of
Filter
,Attribute
, orGroup
objects.- Output:
(&(filt=1)(filt=2)..)
- Output:
-
Filter.OR(filt) - Accepts a list of
Filter
,Attribute
, orGroup
objects.- Output:
(|(filt=1)(filt=2)..)
- Output:
-
Filter.NOT(filt) - Accepts a single
Attribute
object.- Output:
(!(filt=1))
- Output:
Filter Parsing
The Filter.parse(input)
method can be used to create a Filter
object from an existing LDAP filter. This method can also be used to determine if a string is a valid LDAP filter or not.
input = '(|(name=bob)(name=bill))'
Filter.parse(input)
If an invalid LDAP filter string is passed a ParseError
exception will be thrown.
from ldap_filter import Filter, ParseError
input = '(|(name=bob)name=bill))'
try:
Filter.parse(input)
except ParseError as e:
print(e)
Error Output:
Line 1: expected [\x20], [\x09], "\r\n", "\n", '(', ')'
(|(name=bob)name=bill)
^
Simplifying Filters
The Filter.simplify()
method can be used to eliminate unnecessary AND/OR filters that only have one child node.
input = '(&(name=bob))'
complex = Filter.parse(input)
print(complex.simplify()) # (name=bob)
Filter Output
There are a few options for getting a string output from your Filter
object with optional custom formatting.
Simple String
You can get simple filter string by calling the Filter.to_string()
method. The Filter
class also implements Python's __str__
method, allowing you to type cast the Filter
object directly to a string or concatenate with other strings.
output = Filter.AND([
Filter.attribute('name').equal_to('bob'),
Filter.attribute('mail').ends_with('@example.com'),
])
# Filter.to_string() output.
print(output.to_string()) # (&(name=bob)(mail=*@example.com))
# Typecast output.
print(str(output)) # (&(name=bob)(mail=*@example.com))
# String concatenate output
print('LDAP Filter: ' + output) # LDAP Filter: (&(name=bob)(mail=*@example.com))
Beautified String
The Filter.to_string()
method provides additional formatting options to produce beautified filter strings.
You can get the default beautified format by passing True
to the Filter.to_string(indent)
method
output = Filter.AND([
Filter.attribute('name').equal_to('bob'),
Filter.attribute('mail').ends_with('@example.com'),
Filter.OR([
Filter.attribute('dept').equal_to('accounting'),
Filter.attribute('dept').equal_to('operations')
])
])
print(output.to_string(True))
Default Beautified Output:
(&
(name=bob)
(mail=*@example.com)
(|
(dept=accounting)
(dept=operations)
)
)
or you can customize the output by passing the indent
and/or indt_char
parameters to Filter.to_string(indent, indt_char)
. The indent
parameter accepts an integer value while the indt_char
parameter accepts any string or character value.
output = Filter.AND([
Filter.attribute('name').equal_to('bob'),
Filter.attribute('mail').ends_with('@example.com'),
Filter.OR([
Filter.attribute('dept').equal_to('accounting'),
Filter.attribute('dept').equal_to('operations')
])
])
print(output.to_string(2, '.'))
Custom Beautified Output:
(&
..(name=bob)
..(mail=*@example.com)
..(|
....(dept=accounting)
....(dept=operations)
..)
)
Filter Matching
The Filter.match(data)
method allows you to evaluate a Python dictionary with attributes against an LDAP filter. The method will return True
if a match is found or False
if there is no match (or if an attribute matches a NOT exclusion).
filt = Filter.AND([
Filter.attribute('department').equal_to('accounting'),
Filter.NOT(
Filter.attribute('status').equal_to('terminated')
)
])
employee1 = {
'name': 'Bob Smith',
'department': 'Accounting',
'status': 'Active'
}
print(filt.match(employee1)) # True
employee2 = {
'name': 'Jane Brown',
'department': 'Accounting',
'status': 'Terminated'
}
print(filt.match(employee2)) # False
employee3 = {
'name': 'Bob Smith',
'department': 'Marketing',
'status': 'Active'
}
print(filt.match(employee3)) # False
Unit Tests
In order to run the test suite the pytest library is required. You can install pytest by running:
pip install pytest
To run the unit tests simply type pytest
in the projects root directory
Home Page
Project home page is https://github.com/SteveEwell/python-ldap-filter
License
The Python LDAP Filter project is open source software released under the MIT licence. Copyright 2024 Stephen Ewell
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file ldap_filter-1.0.1.tar.gz
.
File metadata
- Download URL: ldap_filter-1.0.1.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | b0b0b51ff8b681459dc9cb958c1238cb941b39d03280213c2d1f2cd142acbedf |
|
MD5 | 7fb577d3a066a5a3e5aae510298a00c4 |
|
BLAKE2b-256 | 356c54b3c28c1431c7c64c4b610fb5c83721a5598a59f38c59a45db9518a80b1 |
File details
Details for the file ldap_filter-1.0.1-py2.py3-none-any.whl
.
File metadata
- Download URL: ldap_filter-1.0.1-py2.py3-none-any.whl
- Upload date:
- Size: 12.9 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d0691b58d7fc867e3c24663122773e7ebccdda35b2f35caa9bff30357a9807ab |
|
MD5 | cf1b8b03a5e9d20923e5b3b4bcdb06b1 |
|
BLAKE2b-256 | d1d4f2213e236d78937e2636dcf7d40cdaf6cdd53e760415512e1302677022c4 |