Can returned attributes be forced into lowercase

Question:

Changes on our LDAP Server have changed the case of the attributes returned from search. For example, "mailroutingaddress" is now "mailRoutingAddress". The searches themselves are case insensitive, but the python code processing the returned ldap object is attempting to reference attributes in all lower case and failing.

Is there a simple way to specify that the LDAP module should lowercase all returned attributes? Or, is there a straightforward way to change them to lowercase as soon as the results are returned?

We’re trying to avoid extensive rewrites to handle this change in our LDAP software.

This code returns an error "Key not found"

timestamp_filter = ldap.filter.filter_format("a filter that works as intended")
timestamp_result = search_ldap(timestamp_filter, ['modifytimestamp'])
if not timestamp_result:
    log_it('WARN', 'No timestamp returned for group "%s"' % group_cn)
    return False
else:
    mod = timestamp_result[0][1]['modifytimestamp'][0].decode('utf-8').split('Z')[0]

When the last line was change to this, it worked:

    mod = timestamp_result[0][1]['modifyTimestamp'][0].decode('utf-8').split('Z')[0]

I was hoping there was something I could do when the ldap object was first bound:

def bind_to_ldap(dn=auth_dn,pwd=auth_pwd):
  # create connection to ldap and pass bind object back to caller
  try:
    ldc = ldap.initialize(uri, bytes_mode=False)
    bind = ldc.simple_bind_s(dn, pwd)
  except ldap.LDAPError as lerr:
    log_it('EXCEPTION',"Exception raised when attempting to bind to LDAP server %s with dn %s" % (uri, dn))
    graceful_exit("%s" % lerr)

  return ldc

Or, I could iterate over all of the attributes passed back by the search function.

s_filter = ldap.filter.filter_format("a filter that works as intended")
s_results = search_ldap(s_filter)

groups = {}
# okay, lots of processing do here....

for group in s_results:
    # etc. etc. etc.
Asked By: Stephen Jarjoura

||

Answers:

You can change a dict’s keys to lowercase pretty easily with a dict comprehension:

>>> timestamp_result = {'modifyTimestamp': 'foo'}
>>> timestamp_result = {k.lower(): v for k, v in timestamp_result.items()}
>>> timestamp_result
{'modifytimestamp': 'foo'}

A more robust solution would be to have the search_ldap function normalize the server output — that would minimize the amount of code that you’d need to update when the server response changes.

Answered By: Samwise

This is an old school solution from someone who started as a B-developer (and Originally trained on A as in APL-360)

    static void ChangeNodeNamesToLower(XmlDocument dom)
    {
        if (dom == null) return;
        char[] sampleXML = dom.DocumentElement.OuterXml.ToCharArray();
        bool inquote=false;
        for(var i=0; i<sampleXML.Length; i++)
        {
            if (sampleXML[i]=='"') inquote= !inquote;
            if(!inquote) {
                sampleXML[i] =Char.ToLower( sampleXML[i]);
            }
        }
        dom.LoadXml(new string(sampleXML));           
    }
Answered By: Ken Lassesen