Forum Discussion

R__Clark_149098's avatar
R__Clark_149098
Icon for Altocumulus rankAltocumulus
Jan 23, 2019

LDAP Query for Attribute

I apologize if this has been covered in a different article, but I have not been able to find anything that I've had success with.

In my environment, a user's DistinguishedName is totally unique, and they have no awareness as to what this attribute is. Users log in with their SamAccountName, which is different than anything in the DN string.

Example: Bob logs in with bob1234 but his DN is CN=Smith\, Bob1,DC=domain,DC=com

What I want to do is use an LDAP query (before authenticating), with what the user entered at login (SamAccountName), to probe the domain for a user matching that string, and assign the DistinguishedName from that user to session.logon.last.username via. variable assignment later.

In my LDAP query I only have the SearchFilter defined:

(SamAccountName=%{session.logon.last.username})

I assume the administrative user and Base Search DN are inherited from the LDAP Authentication Profile, so I have left the SearchDN empty. I thought I could query a user's attributes from the F5 without them even authenticating, but in practice it does not work. I am always presented with this log when I try:

/Common/S3-LDAP-POLICY_Test:Common:ba183ab6: LDAP Module: Failed to make ldap_search in 'DC=domain,DC=com' with filter '(SamAccountName=bob) ' and scope '2'. Bad search filter.

Is this something I can even potentially do with APM?

  • I ultimately got this working by creating an LDAP Query action, I used the following as a SearchFilter:

    (SamAccountName=%{session.logon.last.username})
    

    I set DistinguishedName as a required attribute so that I was able to use it later. These are case sensitive when you try to use them in Variable Assigns, so make sure to check the session variables after a login attempt if things aren't working.

    The format of my LDAP users DN is CN=Bob\, Smith... or CN=Bob... so I had to cover both cases. The F5 adds an extra slash to the session variable to make it a literal slash in TCL (my guess). I had to create a variable assign to remove that extra slash so when it's sent to the LDAP server it understands it.

    This was the expression field of my variable assign:

    set dn "[mcget {session.ldap.last.attr.dn}]"
    if {[string first "\\" $dn] != -1} {
        return [string map {\\\\ \\} $dn]
    } else {
        return $dn
    }
    

    Finally I created an LDAP auth action with the following in the UserDN. SearchDN and SearchFilter are empty.

    I had to open a case with F5 to figure out how to not send hex to my LDAP server. They key is the :noconv function.

    %{dn:noconv}

    After this authentication worked!!

  • I've used searchfilters like this:

    (|(sAMAccountName=%{session.logon.last.username})(userPrincipalName=%{session.logon.last.username}))

    Try ldapsearch from the command line to first check if the query is working:

    ldapsearch -x -LLL -h 10.10.10.10 -D 'Administrator@example.com' -w S3cr3tP@ss -b 'dc=example,dc=com' -s sub "(|(sAMAccountName=bob@example.com)(userPrincipalName=bob.smith@example.com))" sAMAccountName
    

    And try using the SearchDN:

    dc=example,dc=com

  • Hi R. Clark,

    did you notice the traling white-space character in your LDAP filter?

    /Common/S3-LDAP-POLICY_Test:Common:ba183ab6: LDAP Module: Failed to make ldap_search in 'DC=domain,DC=com' with filter

    '(SamAccountName=bob) '
    and scope '2'. Bad search filter.

    Cheers, Kai

  • Well, I got further. I ran a capture and saw that somehow the ldapsearch interrogates the searchDN correctly and is able to pull user searchDN. I ran a capture with this:

    ldapsearch -LLL "(samaccountname=*bob1234*)" -h 10.10.10.10 -D 'domain\bindacct' -W -b 'DC=domain,DC=com' dn

    Gave me this, which is what I ultimately wanted:

    distinguishedName: CN=bsmith,DC=domain,DC=com

    I copied the searchDN from that into my LDAP query and I am able to pull the user's DN now.

    Only problem is I can't figure out the syntax to use the attribute I assigned in the query correctly. I'm using the syntax from this article but nothing I try seems to work in the authentication step.

    I have tried:

    • session.ldap.last.attr.DistinguishedName
    • (session.ldap.last.attr.DistinguishedName)
    • %{session.ldap.last.attr.DistinguishedName}
    • (%{session.ldap.last.attr.$DistinguishedName})
    • (%{session.ldap.last.attr.DistinguishedName})

    The last version returns:

    LDAP-POLICY_Test:Common:7cc4f5b1: LDAP Module: Failed to bind with '()'. Invalid credentials, 80090308: LdapErr: DSID-0C090400, comment: AcceptSecurityContext error, data 52e, v1db1

    Which to me seems like the syntax is close, but it's not pulling the attribute correctly. I'm going to keep plugging away unless someone has a quick tip for me.

  • Well, now I learned that the attributes are case-sensitive, so:

    %{session.ldap.last.attr.distinguishedName}

    works. However, what is returned has the = , and \ characters converted to hex.

    LDAP-POLICY_Test:Common:7900bf66: LDAP Module: Failed to bind with '(CN\3dBob\5c\5c\2c Smith\2cDC\3ddomain\2cDC\3dcom)'. Invalid credentials, 80090308: LdapErr: DSID-0C090400, comment: AcceptSecurityContext error, data 52e, v1db1

    I probably could convert them with tcl in a variable assign, but seems like there is an easier way or I'm missing something?

  • Hi R. Clark,

    the iRule-specifc syntax below will at first

    [string]
    replace the value to a URI encoded format followed by
    [URI::decode]
    command to unescape the URI encoded characters.

    set var {CN\3dBob\5c\5c\2c Smith\2cDC\3ddomain\2cDC\3dcom}
    log local0.debug "Decoded: [URI::decode [string map { "\\5c\\5c" "%5c" "\\" "%" } $var]]"
    

    Keep in mind that the

    [URI::decode]
    command wont be available within APMs variable assign actions. For that usecase you would need to
    [string]
    replace the value to a HEX encoded format followed by a
    [subst]
    command to unescape the HEX encoded characters.

    set var {CN\3dBob\5c\5c\2c Smith\2cDC\3ddomain\2cDC\3dcom}
    log local0.debug "Decoded: [subst -nocommands -novariables [string map { "\\5c\\5c" "\\x5c" "\\" "\\x" } $var]]"
    

    Note: I'm working very frequently with LDAP and AD based APM scenarios, but i simply don't get the point what the heck you are trying to accomblish and also why?

    Cheers, Kai

  • Thanks Kai,

    I actually got it working by pulling the firstname and lastname in a variable assign from the dn attribute and inserting them in the last LDAP authentication step to avoid the hex all together. I'll try to implement your solution as well.

    CN=%{lastname}\, %{firstname},DC=domain,DC=com

    To answer your question--it's just the nature of how our domain is configured unfortunately (I'm not sure why either). If I could authenticate with samAccountName and not DN, I wouldn't need to query anything. Since users are used to typing in their samaccountName, that's the way I have to make it work.

  • Just out of curiosity why is hex sent to the LDAP server when the session variable does not contain hex? It's confusing when you have to fight with this when it appears as though the session variable is correct.

     

    I wouldn't need a variable assign at all if the F5 sent the authentication string how the distinguishedName session variable appears in the UI.

     

  • I ultimately got this working by creating an LDAP Query action, I used the following as a SearchFilter:

    (SamAccountName=%{session.logon.last.username})
    

    I set DistinguishedName as a required attribute so that I was able to use it later. These are case sensitive when you try to use them in Variable Assigns, so make sure to check the session variables after a login attempt if things aren't working.

    The format of my LDAP users DN is CN=Bob\, Smith... or CN=Bob... so I had to cover both cases. The F5 adds an extra slash to the session variable to make it a literal slash in TCL (my guess). I had to create a variable assign to remove that extra slash so when it's sent to the LDAP server it understands it.

    This was the expression field of my variable assign:

    set dn "[mcget {session.ldap.last.attr.dn}]"
    if {[string first "\\" $dn] != -1} {
        return [string map {\\\\ \\} $dn]
    } else {
        return $dn
    }
    

    Finally I created an LDAP auth action with the following in the UserDN. SearchDN and SearchFilter are empty.

    I had to open a case with F5 to figure out how to not send hex to my LDAP server. They key is the :noconv function.

    %{dn:noconv}

    After this authentication worked!!