diff --git a/Cargo.lock b/Cargo.lock index c25b395..c19cc83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,6 +210,7 @@ version = "0.1.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "ldap3 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -262,6 +263,11 @@ dependencies = [ "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "maplit" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "matches" version = "0.1.6" @@ -834,6 +840,7 @@ dependencies = [ "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2" +"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4fcfcb32d63961fb6f367bfd5d21e4600b92cd310f71f9dca25acae196eb1560" diff --git a/Cargo.toml b/Cargo.toml index a490f24..bb1caf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,7 @@ authors = ["Gregory Ballantine "] version = "2.32" [dependencies.ldap3] version = "0.6" +[dependencies.maplit] +version = "1.0" [dependencies.yaml-rust] version = "0.4" diff --git a/src/ldap.rs b/src/ldap.rs index 698d598..790c420 100644 --- a/src/ldap.rs +++ b/src/ldap.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use std::error::Error; use ldap3::{LdapConn, Scope, SearchEntry}; +use yaml_rust::Yaml; // create an LDAP connection object pub fn connect(ldap_connection_info: HashMap<&str, &str>) -> LdapConn { @@ -43,3 +44,27 @@ pub fn do_search(ldap_conn: LdapConn, search_base: &str, search_filter: &str) -> Ok(()) } + +// perform an add user operation +pub fn do_add_user(ldap_conn: LdapConn, user_conf: Yaml, user_info: &HashMap<&str, &str>) -> Result<(), Box> { + let user_dn = format!("{}={},{}", user_conf["id_attr"].as_str().unwrap(), user_info.get("username").unwrap(), user_conf["base"].as_str().unwrap()); + let user_home = format!("/nfs/users/{}/home", user_info.get("username").unwrap()); + let user_display = format!("{} {}", user_info.get("first-name").unwrap(), user_info.get("last-name").unwrap()); + + let user_vec = vec![ + (user_conf["id_attr"].as_str().unwrap(), hashset!{user_info.get("username").unwrap().to_owned()}), + ("mail", hashset!{user_info.get("username").unwrap().to_owned()}), + ("displayName", hashset!{user_display.as_str()}), + ("givenName", hashset!{user_info.get("first-name").unwrap().to_owned()}), + ("sn", hashset!{user_info.get("last-name").unwrap().to_owned()}), + ("uidNumber", hashset!{user_info.get("id-number").unwrap().to_owned()}), + ("gidNumber", hashset!{user_info.get("id-number").unwrap().to_owned()}), + ("homeDirectory", hashset!{user_home.as_str()}), + ("objectClass", hashset!{user_conf["attrs"]["objectClass"].as_vec().unwrap()}) + ]; + + let res = ldap_conn.add(&user_dn, user_vec)?.success()?; + println!("{:?}", res); + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 182d655..d7791ab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,7 @@ extern crate clap; extern crate ldap3; +#[macro_use] +extern crate maplit; extern crate yaml_rust; mod ldap; @@ -71,6 +73,49 @@ fn main() { .default_value("(&(objectClass=*))") .help("LDAP search filter"))) + // LDAP add resource subcommand + .subcommand(SubCommand::with_name("add") + .about("Add an LDAP entry") + + // add user entry subcommand + .subcommand(SubCommand::with_name("user") + .about("Add an LDAP user entry") + // Username argument + .arg(Arg::with_name("username") + .short("u") + .long("username") + .takes_value(true) + .required(true) + .help("User's login username")) + // Email address argument + .arg(Arg::with_name("email") + .short("e") + .long("email") + .takes_value(true) + .required(true) + .help("User's email address")) + // First name argument + .arg(Arg::with_name("first-name") + .short("f") + .long("first-name") + .takes_value(true) + .required(true) + .help("User's first name")) + // Last name argument + .arg(Arg::with_name("last-name") + .short("l") + .long("last-name") + .takes_value(true) + .required(true) + .help("User's last name")) + // ID number argument + .arg(Arg::with_name("id-number") + .short("i") + .long("id-number") + .takes_value(true) + .required(true) + .help("User's ID number")))) + .get_matches(); // create a new hashmap for the connection info @@ -90,6 +135,31 @@ fn main() { let search_filter = matches.value_of("filter").unwrap(); // run the LDAP search - let _ = ldap::do_search(ldap_conn, search_base, search_filter); + match ldap::do_search(ldap_conn, search_base, search_filter) { + Ok(_) => {}, + Err(e) => println!("{:?}", e), + } + } else if let Some(matches) = matches.subcommand_matches("add") { + // perform an LDAP bind + let bind_dn = yaml["muldap"]["bind_dn"].as_str().unwrap(); + let bind_pw = yaml["muldap"]["bind_pw"].as_str().unwrap(); + ldap_conn.simple_bind(bind_dn, bind_pw); + + if let Some(matches) = matches.subcommand_matches("user") { + // create HashMap of user info + let mut ldap_user_info = HashMap::new(); + ldap_user_info.insert("username", matches.value_of("username").unwrap()); + ldap_user_info.insert("email", matches.value_of("email").unwrap()); + ldap_user_info.insert("first-name", matches.value_of("first-name").unwrap()); + ldap_user_info.insert("last-name", matches.value_of("last-name").unwrap()); + ldap_user_info.insert("id-number", matches.value_of("id-number").unwrap()); + + let user_conf = &yaml["muldap"]["user"]; + + match ldap::do_add_user(ldap_conn, user_conf.to_owned(), &ldap_user_info) { + Ok(_) => {}, + Err(e) => println!("{:?}", e), + } + } } }