Re: slow AD ldap query or bad filter/algorithm?
Clément OUDOT <[email protected]> Fri, 11 Dec 2015 12:15:55 +0100
| Newsgroups | gmane.comp.lang.perl.modules.ldap |
|---|---|
| Message-ID | <CAK_oV49jYmVabejkw+NNYyYy+cm8nSpmDY20XNGUC-rp3VCZ8w@mail.gmail.com> |
--001a11443984796adf05269d720e Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable 2015-12-11 12:12 GMT+01:00 Natxo Asenjo <[email protected]>: > hi, > > I need to get mail enabled groups info from Active Directory. > > AD mail enabled groups (be it distribution or security groups) keeps the > member attributes as distinguishednames > > Example: > > CN=3Dmailgroup,OU=3DGroep,DC=3Ddomain,DC=3Dtld > objectClass: top > objectClass: group > cn: mailgroup > member: CN=3Duser a,OU=3Dstaff,dc=3Ddomain,dc=3Dtld > member: CN=3Duser b,OU=3Dstaff,dc=3Ddomain,dc=3Dtld > member: CN=3Duser c,OU=3Dstaff,dc=3Ddomain,dc=3Dtld > member: CN=3Duser d,OU=3Dstaff,dc=3Ddomain,dc=3Dtld > > etc > > So in order to get the mail addresses of those users, I need to launch > another query. > > So I first query the mail enabled groups, fast query: > > my $mail_enabled_grps_AD =3D "(&(objectCategory=3Dgroup)(mail=3D*))"; > > # first find enabled accounts to fill @ad_enabled > while (1) { > my $search_ad =3D $ad_ldap->search( > base =3D> "dc=3Ddomain,dc=3Dtld", > scope =3D> "sub", > filter =3D> $mail_enabled_grps_AD, > attr =3D> > [ 'cn', 'member', 'mail', 'proxyaddresess', 'distinguishedname'= , > ], > control =3D> [$page_ad], > ); > > $search_ad->code && die "error on search ad: $@: " . $search_ad->erro= r; > while ( my $entry =3D $search_ad->pop_entry() ) { > my $displayname =3D $entry->get_value('cn'); > my $dn =3D $entry->get_value('distinguishedname'); > my $mail =3D $entry->get_value('mail'); > my @members =3D $entry->get_value('member'); > my @email_addrs =3D $entry->get_value('proxyaddresses'); > > # fill @ad_enabled > push @ad_mail_enbld_groups, lc $mail; > > my @ad_mails =3D _from_dn_to_mail(@members); > > # generate hash for hoh_AD > my $rec =3D { > MAIL =3D> $mail, > MEMBERS =3D> [@members], > MEMBERS_ADDRS =3D> [@ad_mails], > PROXYADDRS =3D> [@email_addrs], > }; > > # assing $rec to %hoh_AD > $hoh_AD{$mail} =3D $rec; > > } > > my ($resp) =3D $search_ad->control(LDAP_CONTROL_PAGED) or last; > $cookie_ad =3D $resp->cookie or last; > $page_ad->cookie($cookie_ad); > } > > If I do not use my @ad_mails =3D _from_dn_to_mail(@members); then this > snippet runs under 2 seconds. > > If I use it, it takes 2m30secs. > > This is the code in the sub(s): > > sub _get_ad_user_mail { > my ($ad_user) =3D @_; > my $search_ad =3D $ad_ldap->search( > base =3D> "dc=3Ddomain,dc=3Dtld", > scope =3D> "sub", > filter =3D> > "(&(objectclass=3Duser)(objectcategory=3Dperson)(distinguishedname=3D$ad_= user))", > attr =3D> ['mail'], > ); > > $search_ad->code && die "error on search ad: $@: " . $search_ad->erro= r; > for my $entry ( $search_ad->entries ) { > my $ad_user_mail =3D $entry->get_value('mail'); > return $ad_user_mail; > } > } > > sub _from_dn_to_mail { > my (@members) =3D @_; > my @ad_mail; > for my $member (@members) { > push @ad_mail, _get_ad_user_mail($member); > } > return @ad_mail; > > } > > > I mean, it works, but is it normal that it's so slow or am I missing > something very obvious? > > Thanks for you input. > You should do a search directly on the member DN (with scope base) instead of requestind the suffix in sub _get_ad_user_mail : sub _get_ad_user_mail { my ($ad_user) =3D @_; my $search_ad =3D $ad_ldap->search( base =3D> $ad_user, scope =3D> "base", filter =3D> "(objectclass=3D*)", attr =3D> ['mail'], ); $search_ad->code && die "error on search ad: $@: " . $search_ad->error; for my $entry ( $search_ad->entries ) { my $ad_user_mail =3D $entry->get_value('mail'); return $ad_user_mail; } } Cl=C3=A9ment. --001a11443984796adf05269d720e Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo= te">2015-12-11 12:12 GMT+01:00 Natxo Asenjo <span dir=3D"ltr"><<a href= =3D"mailto:[email protected]" target=3D"_blank">[email protected]= </a>></span>:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0= px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div = dir=3D"ltr"><div>hi,<br><br></div><div>I need to get mail enabled groups in= fo from Active Directory.<br><br></div>AD mail enabled groups (be it distri= bution or security groups) keeps the member attributes as distinguishedname= s<br clear=3D"all"><div><div><div><div><div><br>Example:<br><br>CN=3Dmailgr= oup,OU=3DGroep,DC=3Ddomain,DC=3Dtld<br>objectClass: top<br>objectClass: gro= up<br>cn: mailgroup<br>member: CN=3Duser a,OU=3Dstaff,dc=3Ddomain,dc=3Dtld<= br>member: CN=3Duser b,OU=3Dstaff,dc=3Ddomain,dc=3Dtld<br>member: CN=3Duser= c,OU=3Dstaff,dc=3Ddomain,dc=3Dtld<br>member: CN=3Duser d,OU=3Dstaff,dc=3Dd= omain,dc=3Dtld<br><br></div><div>etc<br><br></div><div>So in order to get t= he mail addresses of those users, I need to launch another query.<br><br></= div><div>So I first query the mail enabled groups, fast query:<br><br>my $m= ail_enabled_grps_AD =3D "(&(objectCategory=3Dgroup)(mail=3D*))&quo= t;;<br><br># first find enabled accounts to fill @ad_enabled<br>while (1) {= <br>=C2=A0=C2=A0=C2=A0 my $search_ad =3D $ad_ldap->search(<br>=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 base=C2=A0=C2=A0 =3D> "dc=3Ddomai= n,dc=3Dtld",<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 scope=C2=A0= =3D> "sub",<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fil= ter =3D> $mail_enabled_grps_AD,<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0 attr =3D><br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 [ 'cn', 'member', 'mail', 'proxyaddresess&#= 39;, 'distinguishedname', ],<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 control =3D> [$page_ad],<br>=C2=A0=C2=A0=C2=A0 );<br><br>=C2= =A0=C2=A0=C2=A0 $search_ad->code && die "error on search ad= : $@: " . $search_ad->error;<br>=C2=A0=C2=A0=C2=A0 while ( my $entr= y =3D $search_ad->pop_entry() ) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 my $displayname =3D $entry->get_value('cn');<br>=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 my $dn=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 =3D $entry->get_value('distinguishedname= 9;);<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 my $mail=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0 =3D $entry->get_value('mail');<br>= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 my @members=C2=A0=C2=A0=C2=A0=C2= =A0 =3D $entry->get_value('member');<br>=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0 my @email_addrs =3D $entry->get_value('proxyaddre= sses');<br><br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 # fill @ad_en= abled<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 push @ad_mail_enbld_gro= ups, lc $mail;<br><br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 my @ad_mai= ls =3D _from_dn_to_mail(@members);<br><br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 # generate hash for hoh_AD<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 my $rec =3D {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0 MAIL=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 =3D> $mail,<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 MEMBERS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =3D> [@membe= rs],<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 = MEMBERS_ADDRS =3D> [@ad_mails],<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 PROXYADDRS=C2=A0=C2=A0=C2=A0 =3D> [@email= _addrs],<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 };<br><br>=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 # assing $rec to %hoh_AD<br>=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 $hoh_AD{$mail} =3D $rec;<br><br>=C2=A0=C2=A0= =C2=A0 }<br><br>=C2=A0=C2=A0=C2=A0 my ($resp) =3D $search_ad->control(LD= AP_CONTROL_PAGED) or last;<br>=C2=A0=C2=A0=C2=A0 $cookie_ad =3D $resp->c= ookie or last;<br>=C2=A0=C2=A0=C2=A0 $page_ad->cookie($cookie_ad);<br>}<= br><br></div><div>If I do not use =C2=A0 my @ad_mails =3D _from_dn_to_mail(= @members); then this snippet runs under 2 seconds.<br><br></div><div>If I u= se it, it takes 2m30secs.<br><br></div><div>This is the code in the sub(s):= <br><br>sub _get_ad_user_mail {<br>=C2=A0=C2=A0=C2=A0 my ($ad_user) =3D @_;= <br>=C2=A0=C2=A0=C2=A0 my $search_ad =3D $ad_ldap->search(<br>=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 base=C2=A0 =3D> "dc=3Ddomain,dc= =3Dtld",<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 scope =3D> &= quot;sub",<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 filter =3D>= ;<br>"(&(objectclass=3Duser)(objectcategory=3Dperson)(distinguishe= dname=3D$ad_user))",<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 att= r =3D> ['mail'],<br>=C2=A0=C2=A0=C2=A0 );<br><br>=C2=A0=C2=A0=C2= =A0 $search_ad->code && die "error on search ad: $@: "= . $search_ad->error;<br>=C2=A0=C2=A0=C2=A0 for my $entry ( $search_ad-&= gt;entries ) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 my $ad_user_ma= il =3D $entry->get_value('mail');<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 return $ad_user_mail;<br>=C2=A0=C2=A0=C2=A0 }<br>}<br><br>s= ub _from_dn_to_mail {<br>=C2=A0=C2=A0=C2=A0 my (@members) =3D @_;<br>=C2=A0= =C2=A0=C2=A0 my @ad_mail;<br>=C2=A0=C2=A0=C2=A0 for my $member (@members) {= <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 push @ad_mail, _get_ad_user_= mail($member);<br>=C2=A0=C2=A0=C2=A0 }<br>=C2=A0=C2=A0=C2=A0 return @ad_mai= l;<br><br>}<br></div><div><br></div><div><br></div><div>I mean, it works, b= ut is it normal that it's so slow or am I missing something very obviou= s?<br><br></div><div>Thanks for you input.<span class=3D""><font color=3D"#= 888888"><br></font></span></div></div></div></div></div></div></blockquote>= <div><br><br><br></div><div>You should do a search directly on the member D= N (with scope base) instead of requestind the suffix in sub _get_ad_user_m= ail :<br><br><br><br>sub _get_ad_user_mail {<br>=C2=A0=C2=A0=C2=A0 my ($ad_= user) =3D @_;<br>=C2=A0=C2=A0=C2=A0 my $search_ad =3D $ad_ldap->search(<= br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 base=C2=A0 =3D> $ad_user,<= br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 scope =3D> "base"= ;,<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 filter =3D> "(obje= ctclass=3D*)",<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 attr =3D&= gt; ['mail'],<br>=C2=A0=C2=A0=C2=A0 );<br><br>=C2=A0=C2=A0=C2=A0 $s= earch_ad->code && die "error on search ad: $@: " . $se= arch_ad->error;<br>=C2=A0=C2=A0=C2=A0 for my $entry ( $search_ad->ent= ries ) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 my $ad_user_mail =3D= $entry->get_value('mail');<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 return $ad_user_mail;<br>=C2=A0=C2=A0=C2=A0 }<br>}<br></div><div>= =C2=A0<br><br><br></div><div>Cl=C3=A9ment.<br></div></div></div></div> --001a11443984796adf05269d720e--