fix: now checks to see what is needed to be added or removed.
All checks were successful
Build / build (push) Successful in 2m54s
Build / deploy (push) Successful in 24s

This is more complex than the ``replace`` option but it should give more reliable results
This commit is contained in:
silver 2025-06-29 22:59:12 +01:00
parent cd710e5df7
commit 1dae2ecb26
Signed by: silver
GPG key ID: 36F93D61BAD3FD7D

View file

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