#ldap #high-level #ldap-3 #async #user-group

simple-ldap

A high-level LDAP client for Rust

6 stable releases

1.6.1 Apr 17, 2024
1.5.1 Mar 29, 2024
1.4.1 Dec 26, 2023
1.2.0 Nov 10, 2023
0.0.4 Jun 4, 2023

#135 in Authentication

Download history 98/week @ 2024-02-19 43/week @ 2024-02-26 7/week @ 2024-03-04 175/week @ 2024-03-11 143/week @ 2024-03-25 34/week @ 2024-04-01 136/week @ 2024-04-08 315/week @ 2024-04-15

628 downloads per month

MIT/Apache

85KB
1.5K SLoC

Simple LDAP client library for Ldap3

A ldap client library that wraps ldap3 to make it easy to use.

Status of the project

Currently this is in early alpha stage. Library only support use asynchronously.

Usage

cargo add simple-ldap

Examples

Authenticate a user

use simple-ldap::{LdapClient,Error,EqFilter};
use simple-ldap::ldap3::Scope;

#[tokio::main]
async fn main() -> Result<()> {
    let ldap_config = LdapConfig {
            bind_dn: "cn=manager".to_string(),
            bind_pw: "password".to_string(),
            ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
            pool_size: 10,
            // By default, simple-ldap uses the "entryDN" attribute to get a record's distinguished name.
            // In case the attribute containing the DN is named differently, you can use `dn_attribute` to
            // provide the correct attribute.
            dn_attribute: Some("distinguishedName"),
        };

    let pool = pool::build_connection_pool(&ldap_config).await;
    let mut ldap = pool.pool.get_connection().await.unwrap();
    let name_filter = EqFilter::from("cn".to_string(), "Ada".to_string());

    ldap.authenticate("ou=users,dc=example,dc=org", "Ada", "password", Box::new(name_filter))
        .await
        .expect("Authentication unsuccessful");
}

Create a new record

use simple-ldap::{LdapClient,Error,EqFilter};
use simple-ldap::ldap3::Scope;

#[tokio::main]
async fn main() -> Result<()> {
    let ldap_config = LdapConfig {
            bind_dn: "cn=manager".to_string(),
            bind_pw: "password".to_string(),
            ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
            pool_size: 10,
            dn_attribute: None,
        };
        
    let pool = pool::build_connection_pool(&ldap_config).await;
    let mut ldap = pool.pool.get_connection().await.unwrap();

        let data = vec![
            (
                "objectClass",
                HashSet::from(["organizationalPerson", "inetorgperson", "top", "person"]),
            ),
            (
                "uid",
                HashSet::from(["bd9b91ec-7a69-4166-bf67-cc7e553b2fd9"]),
            ),
            ("cn", HashSet::from(["Kasun"])),
            ("sn", HashSet::from(["Ranasingh"])),
        ];
        let result = ldap
            .create(
                "bd9b91ec-7a69-4166-bf67-cc7e553b2fd9",
                "ou=people,dc=example,dc=com",
                data,
            )
            .await;
    Ok(ldap.unbind().await?)
}

Search records

use simple-ldap::{LdapClient,Error,EqFilter};
use simple-ldap::ldap3::Scope;

#[tokio::main]
async fn main() -> Result<()> {
    let ldap_config = LdapConfig {
            bind_dn: "cn=manager".to_string(),
            bind_pw: "password".to_string(),
            ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
            pool_size: 10,
            dn_attribute: None,
        };
        
    let pool = pool::build_connection_pool(&ldap_config).await;
    let mut ldap = pool.pool.get_connection().await.unwrap();
        let name_filter = EqFilter::from("cn".to_string(), "Sam".to_string());
        let user = ldap
            .search::<User>(
                "ou=people,dc=example,dc=com",
                self::ldap3::Scope::OneLevel,
                &name_filter,
                vec!["cn", "sn", "uid"],
            )
            .await;
        assert!(user.is_ok());
        let user = user.unwrap();
    Ok(ldap.unbind().await?)
}

Search Stream records

use simple-ldap::{LdapClient,Error,EqFilter};
use simple-ldap::ldap3::Scope;

#[tokio::main]
async fn main() -> Result<()> {
    let ldap_config = LdapConfig {
            bind_dn: "cn=manager".to_string(),
            bind_pw: "password".to_string(),
            ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
            pool_size: 10,
            dn_attribute: None,
        };
        
    let pool = pool::build_connection_pool(&ldap_config).await;
    let mut ldap = pool.pool.get_connection().await.unwrap();

        let name_filter = EqFilter::from("cn".to_string(), "James".to_string());
        let result = ldap
            .streaming_search::<User>(
                "ou=people,dc=example,dc=com",
                self::ldap3::Scope::OneLevel,
                &name_filter,
                2,
                vec!["cn", "sn", "uid"],
            )
            .await;
        assert!(result.is_ok());
        let result = result.unwrap();
        assert!(result.len() == 2);
    Ok(ldap.unbind().await?)
}

Update a record

async fn main() -> Result<()> {
    let ldap_config = LdapConfig {
            bind_dn: "cn=manager".to_string(),
            bind_pw: "password".to_string(),
            ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
            pool_size: 10,
            dn_attribute: None,
        };
        
    let pool = pool::build_connection_pool(&ldap_config).await;
    let mut ldap = pool.pool.get_connection().await.unwrap();
        let data = vec![
            Mod::Replace("cn", HashSet::from(["Jhon_Update"])),
            Mod::Replace("sn", HashSet::from(["Eliet_Update"])),
        ];
        let result = ldap
            .update(
                "e219fbc0-6df5-4bc3-a6ee-986843bb157e",
                "ou=people,dc=example,dc=com",
                data,
                Option::None,
            )
            .await;
    Ok(ldap.unbind().await?)
}

Delete a record

async fn main() -> Result<()> {
    let ldap_config = LdapConfig {
            bind_dn: "cn=manager".to_string(),
            bind_pw: "password".to_string(),
            ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
            pool_size: 10,
            dn_attribute: None,
        };
        
    let pool = pool::build_connection_pool(&ldap_config).await;
    let mut ldap = pool.pool.get_connection().await.unwrap();

        let result = ldap
            .delete(
                "4d9b08fe-9a14-4df0-9831-ea9992837f0d",
                "ou=people,dc=example,dc=com",
            )
            .await;
    Ok(ldap.unbind().await?)
}

Create a group

use simple_ldap::LdapClient;
use simple_ldap::pool::LdapConfig;
     
let ldap_config = LdapConfig {
    bind_dn: "cn=manager".to_string(),
    bind_pw: "password".to_string(),
    ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
    pool_size: 10,
    dn_attribute: None,
};
     
let pool = pool::build_connection_pool(&ldap_config).await;
let mut ldap = pool.pool.get_connection().await.unwrap();
let result = ldap.create_group("test_group", "ou=groups,dc=example,dc=com", "test group").await;

Ok(ldap.unbind().await?)

Add user to a group

use simple_ldap::LdapClient;
use simple_ldap::pool::LdapConfig;

let ldap_config = LdapConfig {
    bind_dn: "cn=manager".to_string(),
    bind_pw: "password".to_string(),
    ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
    pool_size: 10,
    dn_attribute: None,
};

let pool = pool::build_connection_pool(&ldap_config).await;
let mut ldap = pool.pool.get_connection().await.unwrap();
let result = ldap.add_user_to_group("test_group", "ou=groups,dc=example,dc=com", "test_user").await;

Ok(ldap.unbind().await?)

Get users in a group

use simple_ldap::LdapClient;
use simple_ldap::pool::LdapConfig;

#[derive(Debug, Deserialize)]
struct User {
    uid: String,
    cn: String,
    sn: String,
}
let ldap_config = LdapConfig {
    bind_dn: "cn=manager".to_string(),
    bind_pw: "password".to_string(),
    ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
    pool_size: 10,
    dn_attribute: None,
};

let pool = pool::build_connection_pool(&ldap_config).await;
let mut ldap = pool.pool.get_connection().await.unwrap();
let result = ldap.get_members::<User>("cn=test_group,ou=groups,dc=example,dc=com", "ou=people,dc=example,dc=com", self::ldap3::Scope::OneLevel, vec!["cn", "sn", "uid"]).await;

Ok(ldap.unbind().await?)

Remove user from a group

use simple_ldap::LdapClient;
use simple_ldap::pool::LdapConfig;

let ldap_config = LdapConfig {
    bind_dn: "cn=manager".to_string(),
    bind_pw: "password".to_string(),
    ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
    pool_size: 10,
    dn_attribute: None,
};

let pool = pool::build_connection_pool(&ldap_config).await;
let mut ldap = pool.pool.get_connection().await.unwrap();
let result = pool.pool.get_connection().await.unwrap().remove_users_from_group(
                "cn=test_group_2,dc=example,dc=com",
                vec![
                    "uid=f92f4cb2-e821-44a4-bb13-b8ebadf4ecc5,ou=people,dc=example,dc=com",
                    "uid=e219fbc0-6df5-4bc3-a6ee-986843bb157e,ou=people,dc=example,dc=com",
                ],).await;

Ok(ldap.unbind().await?)

Get Associated Groups for a user

use simple_ldap::LdapClient;
use simple_ldap::pool::LdapConfig;

let ldap_config = LdapConfig {
    bind_dn: "cn=manager".to_string(),
    bind_pw: "password".to_string(),
    ldap_url: "ldap://ldap_server:1389/dc=example,dc=com".to_string(),
    pool_size: 10,
    dn_attribute: None,
};

let pool = pool::build_connection_pool(&ldap_config).await;
let mut ldap = pool.pool.get_connection().await.unwrap();
let result = ldap.get_associtated_groups("ou=group,dc=example,dc=com","uid=e219fbc0-6df5-4bc3-a6ee-986843bb157e,ou=people,dc=example,dc=com",).await;

Ok(ldap.unbind().await?)

Dependencies

~7–42MB
~687K SLoC