Skip to main content

A Python utility library for working with Lightweight Directory Access Protocol (LDAP) filters.

Project description

Python LDAP Filter · Latest Version License

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=*)
  • Attribute.equal_to(value) - Tests if an attribute is equal to the provided value.

    • Output: (attribute=value)
  • Attribute.contains(value) - Tests if an attribute contains the provided value.

    • Output: (attribute=*value*)
  • Attribute.starts_with(value) - Tests if an attribute starts with the provided value.

    • Output: (attribute=value*)
  • Attribute.ends_with(value) - Tests if an attribute ends with the provided value.

    • Output: (attribute=*value)
  • Attribute.approx(value) - Tests if an attribute is an approximate match to the provided value.

    • Output: (attribute~=value)
  • Attribute.gte(value) - Tests if an attribute is greater than or equal to the provided value.

    • Output: (attribute>=value)
  • Attribute.lte(value) - Tests if an attribute is less than or equal to the provided value.

    • Output: (attribute<=value)
  • Attribute.raw(value) - Allows for a custom filter with escaped value output.

    • Output: (attribute=value)

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, or Group objects.

    • Output: (&(filt=1)(filt=2)..)
  • Filter.OR(filt) - Accepts a list of Filter, Attribute, or Group objects.

    • Output: (|(filt=1)(filt=2)..)
  • Filter.NOT(filt) - Accepts a single Attribute object.

    • Output: (!(filt=1))

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

ldap_filter-1.0.1.tar.gz (17.7 kB view details)

Uploaded Source

Built Distribution

ldap_filter-1.0.1-py2.py3-none-any.whl (12.9 kB view details)

Uploaded Python 2 Python 3

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

Hashes for ldap_filter-1.0.1.tar.gz
Algorithm Hash digest
SHA256 b0b0b51ff8b681459dc9cb958c1238cb941b39d03280213c2d1f2cd142acbedf
MD5 7fb577d3a066a5a3e5aae510298a00c4
BLAKE2b-256 356c54b3c28c1431c7c64c4b610fb5c83721a5598a59f38c59a45db9518a80b1

See more details on using hashes here.

File details

Details for the file ldap_filter-1.0.1-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for ldap_filter-1.0.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 d0691b58d7fc867e3c24663122773e7ebccdda35b2f35caa9bff30357a9807ab
MD5 cf1b8b03a5e9d20923e5b3b4bcdb06b1
BLAKE2b-256 d1d4f2213e236d78937e2636dcf7d40cdaf6cdd53e760415512e1302677022c4

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page