fix: now checks to see what is needed to be added or removed.
This is more complex than the ``replace`` option but it should give more reliable results
This commit is contained in:
parent
cd710e5df7
commit
1dae2ecb26
1 changed files with 90 additions and 19 deletions
109
src/lib.rs
109
src/lib.rs
|
@ -8,6 +8,7 @@ use sqlx::{
|
|||
sqlite::{SqliteConnectOptions, SqlitePoolOptions},
|
||||
Error, Pool, Sqlite,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
use std::{
|
||||
env,
|
||||
str::FromStr,
|
||||
|
@ -215,28 +216,23 @@ pub async fn update_group(config: &Config, group: &str, users: &[String], replac
|
|||
// use the admin account
|
||||
ldap.simple_bind(&config.ldap_admin, &config.ldap_admin_pw)?.success()?;
|
||||
|
||||
let dn = format!("cn={},ou=groups,dc=skynet,dc=ie", group);
|
||||
let members = users.iter().map(|uid| uid_to_dn(uid)).collect();
|
||||
let mods = if replace {
|
||||
vec![Mod::Replace("member".to_string(), members)]
|
||||
} else {
|
||||
vec![Mod::Add("member".to_string(), members)]
|
||||
};
|
||||
// we have two groups in teh LDAP that folks must be a member of
|
||||
// ``groupname`` is the main group that we use to grant folks access to services
|
||||
// ``groupname-linux`` is specifically so that we can store some of the key linux data in the ldap, such as uid's
|
||||
|
||||
if let Err(x) = ldap.modify(&dn, mods) {
|
||||
println!("{:?}", x);
|
||||
{
|
||||
let dn = format!("cn={},ou=groups,dc=skynet,dc=ie", group);
|
||||
let in_wolves = users.iter().map(|uid| uid_to_dn(uid)).collect::<HashSet<String>>();
|
||||
let attribute = "member";
|
||||
update_group_sub(&mut ldap, &dn, attribute, &in_wolves, replace);
|
||||
}
|
||||
|
||||
let dn_linux = format!("cn={}-linux,ou=groups,dc=skynet,dc=ie", group);
|
||||
let members_linux = users.iter().map(|uid| uid.to_string()).collect();
|
||||
let mods = if replace {
|
||||
vec![Mod::Replace("memberUid".to_string(), members_linux)]
|
||||
} else {
|
||||
vec![Mod::Add("memberUid".to_string(), members_linux)]
|
||||
};
|
||||
if let Err(x) = ldap.modify(&dn_linux, mods) {
|
||||
println!("{:?}", x);
|
||||
};
|
||||
{
|
||||
let dn = format!("cn={}-linux,ou=groups,dc=skynet,dc=ie", group);
|
||||
let in_wolves = users.iter().map(|uid| uid.to_string()).collect::<HashSet<String>>();
|
||||
let attribute = "memberUid";
|
||||
update_group_sub(&mut ldap, &dn, attribute, &in_wolves, replace);
|
||||
}
|
||||
|
||||
// tidy up
|
||||
ldap.unbind()?;
|
||||
|
@ -244,6 +240,81 @@ pub async fn update_group(config: &Config, group: &str, users: &[String], replac
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn update_group_sub(ldap: &mut LdapConn, dn: &str, attribute: &str, in_wolves: &HashSet<String>, replace: bool) {
|
||||
if replace {
|
||||
let in_ldap = get_ldap_group(ldap, dn, attribute);
|
||||
let modifications = members_to_modifications(in_wolves, &in_ldap, attribute);
|
||||
|
||||
// uid=gamesdev,ou=users,dc=skynet,dc=ie
|
||||
// uid=gamesdev,ou=users,dc=skynet,dc=ie
|
||||
// dbg!(&dn, &modifications);
|
||||
if !modifications.is_empty() {
|
||||
if let Err(x) = ldap.modify(dn, modifications) {
|
||||
println!("{:?}", x);
|
||||
}
|
||||
}
|
||||
} else if let Err(x) = ldap.modify(dn, vec![Mod::Add(attribute.to_string(), in_wolves.to_owned())]) {
|
||||
println!("{:?}", x);
|
||||
};
|
||||
}
|
||||
|
||||
fn get_ldap_group(ldap: &mut LdapConn, dn: &str, attribute: &str) -> HashSet<String> {
|
||||
match ldap.search(dn, Scope::Base, "(objectClass=*)", vec!["cn", attribute]) {
|
||||
Ok(x) => {
|
||||
if let Ok((rs, _res)) = x.success() {
|
||||
for entry in rs {
|
||||
let tmp = SearchEntry::construct(entry);
|
||||
if tmp.attrs.contains_key(attribute) && !tmp.attrs[attribute].is_empty() {
|
||||
return HashSet::from_iter(tmp.attrs[attribute].iter().cloned());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
dbg!(e);
|
||||
}
|
||||
};
|
||||
HashSet::new()
|
||||
}
|
||||
fn members_to_modifications(in_wolves: &HashSet<String>, in_ldap: &HashSet<String>, attribute: &str) -> Vec<Mod<String>> {
|
||||
let mut add = HashSet::new();
|
||||
let mut remove = HashSet::new();
|
||||
|
||||
// now we need a vec
|
||||
let mut joined = HashSet::new();
|
||||
for member in in_ldap {
|
||||
joined.insert(member.to_owned());
|
||||
}
|
||||
for member in in_wolves {
|
||||
joined.insert(member.to_owned());
|
||||
}
|
||||
|
||||
for member in &joined {
|
||||
// if its already in both then we dont need to do anything, nothign changes
|
||||
if in_ldap.contains(member) && in_wolves.contains(member) {
|
||||
continue;
|
||||
}
|
||||
// if its in the ldap but not the database (from wolves) then we will need to remove from teh LDAP
|
||||
if in_ldap.contains(member) && !in_wolves.contains(member) {
|
||||
remove.insert(member.to_owned());
|
||||
}
|
||||
// if the person is member on wolves but not ldap then we need to add it to the LDAP
|
||||
if !in_ldap.contains(member) && in_wolves.contains(member) {
|
||||
add.insert(member.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
let mut modifications = vec![];
|
||||
if !add.is_empty() {
|
||||
modifications.push(Mod::Add(attribute.to_string(), add));
|
||||
}
|
||||
if !remove.is_empty() {
|
||||
modifications.push(Mod::Delete(attribute.to_string(), remove));
|
||||
}
|
||||
|
||||
modifications
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct LdapAuth {
|
||||
user: String,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue