I apologize in advance for the length of this. I hate long email but I
value the advice of this list when approaching something as complex as
I’m describing below … and if I can’t adequately explain it here, I
feel like I shouldn’t do it at all. So you get to read a long email.
I want to implement the mapping of LDAP attr -> RT field mentioned in
Philip Cole’s code comments at
http://wiki.bestpractical.com/index.cgi?AutoCreateAndCanonicalizeUserInfo and, in order to avoid synchronization issues, I want information which is gotten from LDAP to be immutable in all RT interfaces (web and CLI). I have the additional challenge of five valid FQDNs by which you can reach folks here using some various combos of unix login, first-initial-last-name, and first.last left of the @ … but there’s no one LHS which is universal to all five RHS.
I should mention that I have no control of, and little influence in, how
this all works, so cleaning it up isn’t an option for me. I’m also in a
hurry (I need to finish this by Friday), so waiting for the coming
cleanup isn’t an option, either.
I’m considering doing this like so:
Add %RT::LdapAttrMap as Philip Cole suggests, with some way of
indicating user-based custom fields as well. Perhaps:
%RT::LdapAttrMap = ( Name=> ‘uid’,
Add $RT::LdapUserInfoEnable and $RT::LdapUserInfoTTL (in minutes)
to control whether user info is acquired from LDAP and, if so, how
long it’s considered valid before rechecking LDAP.
Add user-based CFs for:
- preferred email (Freeform single, set when receiving user email)
- valid email addrs (Freeform multiple, cached from LDAP)
- ExternalObjectId (Freeform single, cached from LDAP)
- last LDAP update (Freeform single, set while getting LDAP info);
alternately, this could just use the existing “LastUpdate"
RT::User attr … though I was thinking that forcing a cache
refresh could be as easy as blanking this CF and clicking
Refactor Philip Cole’s RT::User::LookupExternalUserInfo() to accept
ExternalObjectId or ExternalUserName (for use with the LDAP auth
params), as well as the current key/value scheme.
Add a method, RT::User->RefreshFromExternalUserInfo(), which calls
LookupExternalUserInfo() then uses the mapping defined in
%RT::LdapAttrMap to set the current objects attrs appropriately.
Any time user info is loaded RT::User->Load(), check that the cached
data hasn’t outlived its expiration and, if it has, call
RefreshFromExternalInfo(). Failure of this refresh generates a
warning (info? crit?) but is not fatal.
So where are the holes I’ve missed?
Thanks for reading this far!
p.s. if ever you want to be sure to understand what you intend, compose
your plans in an email to people smarter than yourself and in front of
whom you’d like not to make a fool of yourself. It’s worked for me. =]
p.p.s. A minor digression: if I were implementing directly in RT rather
than as a contrib, I’d extend the Users table with ExternalObjectId and
LastExternalUpdate columns, both of which would only be seen on the
/Admin/Users/Modify page. I’d also add an EmailAddresses table with id,
ObjectId (users or groups, right?), EmailAddress, and Preferred
I’d also work to better integrate the external autho/info methods
(RT::ExternalInfo.pm? $RT::ExternalAuthMethod? Dunno =). It might be fun
to leverage this to groups, too (manage RT group membership in LDAP;
give groups a distinct email address and leave off emailing individuals;
If someone cares to comment on this approach, I’d enjoy the benefit of
Jim Meyer, Geek at Large firstname.lastname@example.org