
Security News
Vite Releases Technical Preview of Rolldown-Vite, a Rust-Based Bundler
Vite releases Rolldown-Vite, a Rust-based bundler preview offering faster builds and lower memory usage as a drop-in replacement for Vite.
A Python utility library for working with Lightweight Directory Access Protocol (LDAP) filters.
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.
Install via pip:
pip install ldap-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 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)
Attribute.present() - Tests if an attribute is present.
(attribute=*)
Attribute.equal_to(value) - Tests if an attribute is equal to the provided value
.
(attribute=value)
Attribute.contains(value) - Tests if an attribute contains the provided value
.
(attribute=*value*)
Attribute.starts_with(value) - Tests if an attribute starts with the provided value
.
(attribute=value*)
Attribute.ends_with(value) - Tests if an attribute ends with the provided value
.
(attribute=*value)
Attribute.approx(value) - Tests if an attribute is an approximate match to the provided value
.
(attribute~=value)
Attribute.gte(value) - Tests if an attribute is greater than or equal to the provided value
.
(attribute>=value)
Attribute.lte(value) - Tests if an attribute is less than or equal to the provided value
.
(attribute<=value)
Attribute.raw(value) - Allows for a custom filter with escaped value
output.
(attribute=value)
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))
Filter.AND(filt) - Accepts a list of Filter
, Attribute
, or Group
objects.
(&(filt=1)(filt=2)..)
Filter.OR(filt) - Accepts a list of Filter
, Attribute
, or Group
objects.
(|(filt=1)(filt=2)..)
Filter.NOT(filt) - Accepts a single Attribute
object.
(!(filt=1))
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)
^
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)
There are a few options for getting a string output from your Filter
object with optional custom formatting.
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))
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)
..)
)
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
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
Project home page is https://github.com/SteveEwell/python-ldap-filter
The Python LDAP Filter project is open source software released under the MIT licence. Copyright 2024 Stephen Ewell
FAQs
A Python utility library for working with Lightweight Directory Access Protocol (LDAP) filters.
We found that ldap-filter demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Vite releases Rolldown-Vite, a Rust-based bundler preview offering faster builds and lower memory usage as a drop-in replacement for Vite.
Research
Security News
A malicious npm typosquat uses remote commands to silently delete entire project directories after a single mistyped install.
Research
Security News
Malicious PyPI package semantic-types steals Solana private keys via transitive dependency installs using monkey patching and blockchain exfiltration.