slow AD ldap query or bad filter/algorithm?

[email protected] (Natxo Asenjo) Fri, 11 Dec 2015 12:12:04 +0100
Newsgroups perl.ldap
Message-ID <CAHBEJzVhLJeLUvEJNon=YvrNAkLYwJXifF9BR18qEn20tyPv6Q@mail.gmail.com>
--047d7b111907a937f705269d6400
Content-Type: text/plain; charset=UTF-8

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=mailgroup,OU=Groep,DC=domain,DC=tld
objectClass: top
objectClass: group
cn: mailgroup
member: CN=user a,OU=staff,dc=domain,dc=tld
member: CN=user b,OU=staff,dc=domain,dc=tld
member: CN=user c,OU=staff,dc=domain,dc=tld
member: CN=user d,OU=staff,dc=domain,dc=tld

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 = "(&(objectCategory=group)(mail=*))";

# first find enabled accounts to fill @ad_enabled
while (1) {
    my $search_ad = $ad_ldap->search(
        base   => "dc=domain,dc=tld",
        scope  => "sub",
        filter => $mail_enabled_grps_AD,
        attr =>
          [ 'cn', 'member', 'mail', 'proxyaddresess', 'distinguishedname',
],
        control => [$page_ad],
    );

    $search_ad->code && die "error on search ad: $@: " . $search_ad->error;
    while ( my $entry = $search_ad->pop_entry() ) {
        my $displayname = $entry->get_value('cn');
        my $dn          = $entry->get_value('distinguishedname');
        my $mail        = $entry->get_value('mail');
        my @members     = $entry->get_value('member');
        my @email_addrs = $entry->get_value('proxyaddresses');

        # fill @ad_enabled
        push @ad_mail_enbld_groups, lc $mail;

        my @ad_mails = _from_dn_to_mail(@members);

        # generate hash for hoh_AD
        my $rec = {
            MAIL          => $mail,
            MEMBERS       => [@members],
            MEMBERS_ADDRS => [@ad_mails],
            PROXYADDRS    => [@email_addrs],
        };

        # assing $rec to %hoh_AD
        $hoh_AD{$mail} = $rec;

    }

    my ($resp) = $search_ad->control(LDAP_CONTROL_PAGED) or last;
    $cookie_ad = $resp->cookie or last;
    $page_ad->cookie($cookie_ad);
}

If I do not use   my @ad_mails = _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) = @_;
    my $search_ad = $ad_ldap->search(
        base  => "dc=domain,dc=tld",
        scope => "sub",
        filter =>
"(&(objectclass=user)(objectcategory=person)(distinguishedname=$ad_user))",
        attr => ['mail'],
    );

    $search_ad->code && die "error on search ad: $@: " . $search_ad->error;
    for my $entry ( $search_ad->entries ) {
        my $ad_user_mail = $entry->get_value('mail');
        return $ad_user_mail;
    }
}

sub _from_dn_to_mail {
    my (@members) = @_;
    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.
-- 
--
Groeten,
natxo

--047d7b111907a937f705269d6400
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>hi,<br><br></div><div>I need to get mail enabled grou=
ps info from Active Directory.<br><br></div>AD mail enabled groups (be it d=
istribution or security groups) keeps the member attributes as distinguishe=
dnames<br clear=3D"all"><div><div><div><div><div><br>Example:<br><br>CN=3Dm=
ailgroup,OU=3DGroep,DC=3Ddomain,DC=3Dtld<br>objectClass: top<br>objectClass=
: group<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=3Ddomain,dc=3Dtld<br><br></div><div>etc<br><br></div><div>So in order t=
o get the 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><b=
r>my $mail_enabled_grps_AD =3D &quot;(&amp;(objectCategory=3Dgroup)(mail=3D=
*))&quot;;<br><br># first find enabled accounts to fill @ad_enabled<br>whil=
e (1) {<br>=C2=A0=C2=A0=C2=A0 my $search_ad =3D $ad_ldap-&gt;search(<br>=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 base=C2=A0=C2=A0 =3D&gt; &quot;dc=
=3Ddomain,dc=3Dtld&quot;,<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 sco=
pe=C2=A0 =3D&gt; &quot;sub&quot;,<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 filter =3D&gt; $mail_enabled_grps_AD,<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 attr =3D&gt;<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0 [ &#39;cn&#39;, &#39;member&#39;, &#39;mail&#39;, &#39;proxyad=
dresess&#39;, &#39;distinguishedname&#39;, ],<br>=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 control =3D&gt; [$page_ad],<br>=C2=A0=C2=A0=C2=A0 );<br>=
<br>=C2=A0=C2=A0=C2=A0 $search_ad-&gt;code &amp;&amp; die &quot;error on se=
arch ad: $@: &quot; . $search_ad-&gt;error;<br>=C2=A0=C2=A0=C2=A0 while ( m=
y $entry =3D $search_ad-&gt;pop_entry() ) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 my $displayname =3D $entry-&gt;get_value(&#39;cn&#39;);<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-&gt;get_value(&#39;distinguishedn=
ame&#39;);<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-&gt;get_value(&#39;mail&#39;);=
<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-&gt;get_value(&#39;member&#39;);<br>=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 my @email_addrs =3D $entry-&gt;get_value(&#39;prox=
yaddresses&#39;);<br><br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 # fill =
@ad_enabled<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 push @ad_mail_enb=
ld_groups, lc $mail;<br><br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 my @=
ad_mails =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&gt; $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&gt; [=
@members],<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&gt; [@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&gt; [=
@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-&gt;cont=
rol(LDAP_CONTROL_PAGED) or last;<br>=C2=A0=C2=A0=C2=A0 $cookie_ad =3D $resp=
-&gt;cookie or last;<br>=C2=A0=C2=A0=C2=A0 $page_ad-&gt;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 use it, it takes 2m30secs.<br><br></div><div>This is the code in the s=
ub(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-&gt;search(<br>=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 base=C2=A0 =3D&gt; &quot;dc=3Ddomai=
n,dc=3Dtld&quot;,<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 scope =3D&g=
t; &quot;sub&quot;,<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 filter =
=3D&gt;<br>&quot;(&amp;(objectclass=3Duser)(objectcategory=3Dperson)(distin=
guishedname=3D$ad_user))&quot;,<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 attr =3D&gt; [&#39;mail&#39;],<br>=C2=A0=C2=A0=C2=A0 );<br><br>=C2=A0=
=C2=A0=C2=A0 $search_ad-&gt;code &amp;&amp; die &quot;error on search ad: $=
@: &quot; . $search_ad-&gt;error;<br>=C2=A0=C2=A0=C2=A0 for my $entry ( $se=
arch_ad-&gt;entries ) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 my $a=
d_user_mail =3D $entry-&gt;get_value(&#39;mail&#39;);<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>sub _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 (@m=
embers) {<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 retur=
n @ad_mail;<br><br>}<br></div><div><br></div><div><br></div><div>I mean, it=
 works, but is it normal that it&#39;s so slow or am I missing something ve=
ry obvious?<br><br></div><div>Thanks for you input.<br></div><div>-- <br><d=
iv class=3D"gmail_signature">--<br>Groeten,<br>natxo</div>
</div></div></div></div></div></div>

--047d7b111907a937f705269d6400--