Skip to content

Instantly share code, notes, and snippets.

@fedir
Created February 25, 2026 16:28
Show Gist options
  • Select an option

  • Save fedir/080f98758dd81426426d433c6db5ef32 to your computer and use it in GitHub Desktop.

Select an option

Save fedir/080f98758dd81426426d433c6db5ef32 to your computer and use it in GitHub Desktop.
LDAP search and modify in Rust
use ldap3::{LdapConnAsync, Mod, SearchEntry, Scope};
use std::collections::HashSet;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. Connect to the server
let (conn, mut ldap) = LdapConnAsync::new("ldap://localhost:389").await?;
ldap3::drive!(conn);
// 2. Bind (Authenticate)
ldap.simple_bind("cn=admin,dc=example,dc=org", "adminpassword").await?;
let user_uid = "jdoe";
let new_role = "Engineering_Lead";
// 3. Search for the user's DN
let (rs, _res) = ldap.search(
"dc=example,dc=org",
Scope::Subtree,
&format!("(uid={})", user_uid),
vec!["dn", "description"] // description often holds roles/notes
).await?.success()?;
if rs.is_empty() {
println!("User not found.");
return Ok(());
}
// Get the first match
let entry = SearchEntry::construct(rs[0].clone());
let user_dn = entry.dn;
println!("Found DN: {}", user_dn);
// 4. Update (Add a role)
// We use Mod::Add to append to an existing multi-valued attribute
let mods = vec![
Mod::Add("description", HashSet::from([new_role.to_string()]))
];
let modify_res = ldap.modify(&user_dn, mods).await?.success();
match modify_res {
Ok(_) => println!("Successfully added role: {}", new_role),
Err(e) => eprintln!("Failed to update: {:?}", e),
}
ldap.unbind().await?;
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment