Reorganized some command line options; added connection protocol argument; added YAML configuration file support for easy configuration loading

This commit is contained in:
Gregory Ballantine 2018-07-12 21:58:38 -04:00
parent 3f000036da
commit 64d0860eba
4 changed files with 99 additions and 23 deletions

16
Cargo.lock generated
View File

@ -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"

View File

@ -7,3 +7,5 @@ authors = ["Gregory Ballantine <gballantine555@gmail.com>"]
version = "2.32"
[dependencies.ldap3]
version = "0.6"
[dependencies.yaml-rust]
version = "0.4"

View File

@ -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<Error>> {
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<Error>> {
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(())

View File

@ -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 <gballantine555@gmail.com>")
.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);
}
}