Basic ldap search
This commit is contained in:
parent
2e6288e835
commit
abb4c7391e
3
.gitignore
vendored
3
.gitignore
vendored
@ -22,4 +22,5 @@ Cargo.lock
|
||||
#.idea/
|
||||
|
||||
# Manually added
|
||||
/scratchpad/
|
||||
/scratchpad/
|
||||
dprint.json
|
||||
|
||||
13
Cargo.toml
13
Cargo.toml
@ -1,8 +1,12 @@
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = [
|
||||
"crates/config","crates/ldap","crates/password",
|
||||
"tools/lk-pswdreset", "tools/lk-search"
|
||||
"crates/config",
|
||||
"crates/ldap",
|
||||
"crates/password",
|
||||
|
||||
"tools/lk-pswdreset",
|
||||
"tools/lk-search",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
@ -12,7 +16,8 @@ repository = "https://git.candifloss.cc/candifloss/ldap-kit.git"
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0.104"
|
||||
clap = { version = "4.6.4", features = ["derive"] }
|
||||
clap = { version = "4.6.7", features = ["derive"] }
|
||||
ldap3 = "0.12.1"
|
||||
serde = { version = "1.0.229", features = ["derive"] }
|
||||
toml = "1.1.4"
|
||||
tokio = { version = "1.53.1", features = ["macros", "rt-multi-thread"] }
|
||||
toml = "1.1.6"
|
||||
|
||||
@ -8,5 +8,5 @@ repository.workspace = true
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
clap.workspace = true
|
||||
config = { path = "../../crates/config" }
|
||||
ldap3.workspace = true
|
||||
config = { path = "../../crates/config" }
|
||||
@ -1,3 +1,69 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
use anyhow::{Result, bail};
|
||||
use clap::{ArgGroup, Parser};
|
||||
use ldap3::{LdapConn, Scope, SearchEntry};
|
||||
|
||||
use config::ConnectionConfig;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(name = "lk-search", about = "Search an LDAP user")]
|
||||
#[command(group(
|
||||
ArgGroup::new("user")
|
||||
.required(true)
|
||||
.args(["username", "id_number"])
|
||||
))]
|
||||
struct Args {
|
||||
/// Search by username.
|
||||
#[arg(short = 'u', long = "username", value_name = "USERNAME")]
|
||||
username: Option<String>,
|
||||
|
||||
/// Search by ID number.
|
||||
#[arg(short = 'n', long = "id-number", value_name = "ID")]
|
||||
id_number: Option<String>,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let args = Args::parse();
|
||||
let config = ConnectionConfig::load()?;
|
||||
|
||||
let (search_attribute, search_value) = match (&args.username, &args.id_number) {
|
||||
(Some(username), None) => ("uid", username),
|
||||
(None, Some(id_number)) => ("uidNumber", id_number),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let filter = format!("({search_attribute}={search_value})");
|
||||
|
||||
let mut ldap = LdapConn::new(&config.ldap.url)?;
|
||||
|
||||
ldap.simple_bind(&config.read.bind_dn, &config.read.bind_pw)?
|
||||
.success()?;
|
||||
|
||||
let (entries, _result) = ldap
|
||||
.search(&config.ldap.base_dn, Scope::Subtree, &filter, vec!["*"])?
|
||||
.success()?;
|
||||
|
||||
if entries.is_empty() {
|
||||
bail!("User not found.");
|
||||
}
|
||||
|
||||
if entries.len() > 1 {
|
||||
bail!(
|
||||
"Search returned {} entries. Expected exactly one.",
|
||||
entries.len()
|
||||
);
|
||||
}
|
||||
|
||||
let entry = SearchEntry::construct(entries.into_iter().next().unwrap());
|
||||
|
||||
println!("DN: {}", entry.dn);
|
||||
|
||||
for (attribute, values) in entry.attrs {
|
||||
println!("{attribute}:");
|
||||
|
||||
for value in values {
|
||||
println!(" {value}");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user