inejge / ldap3

A pure-Rust LDAP library using the Tokio stack
Apache License 2.0
226 stars 39 forks source link

There was a problem creating ou using recursion #130

Closed cn-hew closed 3 months ago

cn-hew commented 3 months ago

ldap_comm.rs

use std::collections::HashSet;
use std::error::Error;
use std::pin::Pin;
use ldap3::result::Result;
use ldap3::{Ldap, LdapConn, LdapConnAsync, LdapConnSettings, SearchEntry, LdapResult, LdapError};
use ldap3::Scope::Subtree;

pub struct LdapClient {
    ldap: LdapConn,
}

impl LdapClient {
    pub fn connect() -> Result<Self> {
        let ( mut ldap) = LdapConn::with_settings(
            LdapConnSettings::new()
                .set_no_tls_verify(true)
                .set_starttls(true),
            "ldaps://prod-ad-dc01-hq.testddd.com:636",
        )?;
        // ldap3::drive!(conn);
        let res = ldap
            .simple_bind("CN=Moka Program,OU=Service Account,DC=testddd,DC=com", "pdx18edezk")?
            .success()?;
        Ok(Self { ldap })
    }

    pub async fn create_user(&mut self,ou: (String, String)) ->Result<()> {
    Ok(())
    }

    pub fn move_user_dn() {}
    pub fn modify_user_password() {}
    pub fn modify_user_attr() {}
    pub fn add_user_attr() {}
    pub fn move_ou() {}
    pub fn delete_ou() {}
    pub  fn create_ou_demo(&mut self, ou: (String, String)) -> Result<LdapResult> {
        let (children_ou, parent_ou) = ou;
        let dn = format!("{},{}", children_ou, parent_ou);
        let attr_ou: Vec<_> = children_ou.split('=').collect();
        let attr = attr_ou[1].to_string();
        println!("dn {:?}, att {:?} \n",dn,attr.clone());

        let result: LdapResult = self.ldap.add(dn.as_str(), vec![
            ("objectClass", HashSet::from(["organizationalUnit", "posixGroup", "top"])),
            ("ou", HashSet::from([attr.as_str().clone()])),
        ])?;
        println!("one {:#?},{},{} \n",result,dn,attr.as_str().clone());
        if result.rc == 68 {
            println!("{:#?}",result);
            return Ok(result); // Object already exists
        } else if result.rc == 32 {
            // No such object, so create parent OUs
            let mut new_parents_list: Vec<&str> = parent_ou.split(',').collect();
            let mut new_parents_ou = String::new();
            let mut new_children_ou = String::new();

            if let Some(first_element) = new_parents_list.first_mut() {
                if let Some((_, children_ou)) = first_element.split_once('=') {
                    new_parents_list.remove(0);
                    new_parents_ou = new_parents_list.join(",");
                    new_children_ou = children_ou.to_string();
                }
            }

            if !new_parents_ou.is_empty() && !new_children_ou.is_empty() {
                let child = format!("OU={}",new_children_ou.clone());
                let new_ou = (child, new_parents_ou.clone());
                println!("new ou {:?}\n",new_ou.clone());
                // let future = Box::pin(self.create_ou_demo(new_ou));
                let result = self.create_ou_demo(new_ou);
                println!("two {:#?} \n",result);

                // Retry adding the original DN
                let result: LdapResult = self.ldap.add(dn.as_str(), vec![
                    ("objectClass", HashSet::from(["organizationalUnit", "posixGroup", "top"])),
                    ("ou", HashSet::from([children_ou.as_str()])),
                ])?;
                println!("three {:#?},{},{} \n",result,dn.clone(),children_ou.as_str().clone());
                return Ok(result);
            }
        }
        println!("four {:#?} \n",result);
        Ok(result)
    }
}

a utils rs code

pub fn convert_ldap_path(input: &str) -> (String,String) {
    let root_ou=",OU=TestCompany,OU=Test Users,DC=test,DC=com";
    let path = input.chars().skip(5).collect::<String>();
    let parts: Vec<&str> = path.split('/').collect();
    let reversed_parts: Vec<&str> = parts.iter().rev().cloned().collect();
    let mut ou_parts: Vec<String> = reversed_parts.iter().map(|part| format!("OU={}", part)).collect();
    let child_ou= ou_parts.remove(0);
    (child_ou, ou_parts.join(",")+root_ou)

}

Caller code

 fn main()  {
    let ou_path = "one/1one/2two/3tree/4tree/5tree/6tree";
    let mut ldap_client = ldap_comm::LdapClient::connect().unwrap();
    let ou = utils::convert_ldap_path(ou_path);
    println!("main ou {:?}",ou);
    let create_ou_future = ldap_client.create_ou_demo(ou);
    let dd = create_ou_future.unwrap();
    println!("hello {:#?}",dd);
}

When recursively calling the second level, the error message is as follows. I don't understand why. Thank you very much for any recovery.

three LdapResult {
    rc: 34,
    matched: "",
    text: "00002081: NameErr: DSID-03050F42, problem 2003 (BAD_ATT_SYNTAX), data 0, best match of:\n\t'OU=three tree,OU=wo tree,OU=TestCompany,OU=LSYM Users,DC=lsym,DC=cn'\n\0",
    refs: [],
    ctrls: [],
},OU=three tree,OU=wo tree,OU=TestCompany,OU=LSYM Users,DC=lsym,DC=cn,OU=three tree 

two Ok(
    LdapResult {
        rc: 34,
        matched: "",
        text: "00002081: NameErr: DSID-03050F42, problem 2003 (BAD_ATT_SYNTAX), data 0, best match of:\n\t'OU=three tree,OU=wo tree,OU=TestCompany,OU=LSYM Users,DC=lsym,DC=cn'\n\0",
        refs: [],
        ctrls: [],
    },
) 
cn-hew commented 3 months ago

The problem has been identified. The parameters were not passed correctly during the second call

inejge commented 3 months ago

Heads up: there is a realistic-looking bind password in your opening comment, rotate it in your setup if it's a real one.