From 64d0860eba4913852cca01d2eb636a242c829889 Mon Sep 17 00:00:00 2001 From: Gregory Ballantine Date: Thu, 12 Jul 2018 21:58:38 -0400 Subject: [PATCH] Reorganized some command line options; added connection protocol argument; added YAML configuration file support for easy configuration loading --- Cargo.lock | 16 ++++++++++++ Cargo.toml | 2 ++ src/ldap.rs | 31 ++++++++++++++++++----- src/main.rs | 73 +++++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 99 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d36f9af..c25b395 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)", + "yaml-rust 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -240,6 +241,11 @@ name = "libc" version = "0.2.42" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "linked-hash-map" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "log" version = "0.3.9" @@ -787,6 +793,14 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "yaml-rust" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" @@ -817,6 +831,7 @@ dependencies = [ "checksum lber 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa172a35dd26774593b503d085735a189e322d16a2049b2739eb7f914b141b36" "checksum ldap3 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48c15866ba175af81acc75dfc5d4f18aaf8a87f37d2f92252659950196d14221" "checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" +"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 matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" @@ -879,3 +894,4 @@ dependencies = [ "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum yaml-rust 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57ab38ee1a4a266ed033496cf9af1828d8d6e6c1cfa5f643a2809effcae4d628" diff --git a/Cargo.toml b/Cargo.toml index dee1ea7..a490f24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,5 @@ authors = ["Gregory Ballantine "] version = "2.32" [dependencies.ldap3] version = "0.6" +[dependencies.yaml-rust] +version = "0.4" diff --git a/src/ldap.rs b/src/ldap.rs index 3df5b6f..ada7617 100644 --- a/src/ldap.rs +++ b/src/ldap.rs @@ -1,20 +1,37 @@ +use std::collections::HashMap; use std::error::Error; use ldap3::{LdapConn, Scope, SearchEntry}; -pub fn do_search(host: &str, port: u16, base: &str) -> Result<(), Box> { - let conn_string = format!("ldap://{}:{}", host, port); +// create an LDAP connection object +pub fn connect(ldap_connection_info: HashMap<&str, &str>) -> LdapConn { + let conn_string = format!("{}://{}:{}", + ldap_connection_info.get("protocol").unwrap(), + ldap_connection_info.get("server").unwrap(), + ldap_connection_info.get("port").unwrap()); + let ldap_conn = LdapConn::new(&conn_string); - let ldap = LdapConn::new(&conn_string)?; - let (rs, _res) = ldap.search( - base, + if ldap_conn.is_ok() { + return ldap_conn.ok().unwrap(); + } else { + panic!("{:?}", ldap_conn.err().unwrap()); + } +} + +// perform an LDAP search +pub fn do_search(ldap_conn: LdapConn, search_base: &str) -> Result<(), Box> { + let (rs, _res) = ldap_conn.search( + search_base, Scope::Subtree, "(&(objectClass=*))", - vec!["l"] + vec!["*"] )?.success()?; for entry in rs { - println!("{:?}", SearchEntry::construct(entry)); + let search_entry = SearchEntry::construct(entry); + if search_entry.attrs.get("uid").is_some() { + println!("{:?}", search_entry.attrs.get("uid").unwrap()[0]); + } } Ok(()) diff --git a/src/main.rs b/src/main.rs index b65cfe6..3822ea7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,44 +1,85 @@ -#[macro_use] extern crate clap; extern crate ldap3; +extern crate yaml_rust; mod ldap; +use std::collections::HashMap; +use std::fs::File; +use std::io::prelude::*; + use clap::{App, Arg, SubCommand}; +use yaml_rust::YamlLoader; fn main() { + // read user configuration file + let yaml_file = File::open("/home/gballan/.muldap.yaml"); + let mut yaml_raw = String::new(); + yaml_file.unwrap().read_to_string(&mut yaml_raw); + // parse user configuration + let yaml_multi = YamlLoader::load_from_str(&yaml_raw).unwrap(); + let yaml = &yaml_multi[0]; + // parse options let matches = App::new("Metaunix.net LDAP tool") .version("0.1.0") .author("Gregory W. Ballantine ") .about("Tool to manage LDAP resources for Metaunix.net") + // connection protocol argument + .arg(Arg::with_name("protocol") + .short("P") + .long("protocol") + .takes_value(true) + .required(true) + .default_value(yaml["muldap"]["protocl"].as_str().unwrap_or("ldap")) + .help("LDAP connection protocol to use (typically ldap or ldaps)")) + // server argument + .arg(Arg::with_name("server") + .short("s") + .long("server") + .takes_value(true) + .required(true) + .default_value(yaml["muldap"]["server"].as_str().unwrap()) + .help("LDAP server to search")) + // server port argument + .arg(Arg::with_name("port") + .short("p") + .long("port") + .takes_value(true) + .required(true) + .default_value(yaml["muldap"]["port"].as_str().unwrap_or("389")) + .help("Port on which the LDAP server is listening on")) + // LDAP search subcommand .subcommand(SubCommand::with_name("search") .about("Search an LDAP directory") - .arg(Arg::with_name("server") - .short("s") - .long("server") - .takes_value(true) - .help("LDAP server to search")) - .arg(Arg::with_name("port") - .short("p") - .long("port") - .takes_value(true) - .help("Port on which the LDAP server is listening on")) .arg(Arg::with_name("base") .short("b") .long("base") .takes_value(true) + .required(true) + .default_value(yaml["muldap"]["search_base"].as_str().unwrap()) .help("Base DN to search with"))) .get_matches(); - // check for subcommand + // create a new hashmap for the connection info + let mut ldap_connection_info = HashMap::new(); + // add connection info to hashmap + ldap_connection_info.insert("protocol", matches.value_of("protocol").unwrap()); + ldap_connection_info.insert("server", matches.value_of("server").unwrap()); + ldap_connection_info.insert("port", matches.value_of("port").unwrap()); + + // create LDAP connection + let ldap_conn = ldap::connect(ldap_connection_info); + + // search subcommand if let Some(matches) = matches.subcommand_matches("search") { - let server = matches.value_of("server").unwrap(); - let port = value_t!(matches, "port", u16).unwrap_or(389); - let base = matches.value_of("base").unwrap(); - let _ = ldap::do_search(server, port, base); + // get search options + let search_base = matches.value_of("base").unwrap(); + + // run the LDAP search + let _ = ldap::do_search(ldap_conn, search_base); } }