I spoke abit to Therry about it and shared with him my far from
working code. If it is worth anything I will let you know what I
believe would be helpful. Ldap authentication itself is actually kind
of trivial. Like almost anything else there is a establish connection
portion, a query portion and a process response portion. The establish
a connection portion is a “bind” and this is often all that is needed
for authentication since ordinary users should be able to establish a
connection with their credentials.

The problem as I see it is NOT getting ldap to work but aggregating
the user databases/information into one place. There is one dictionary
for users in notebook and a seemingly independent one in twist.py. The
twist.py uses UserDatabase which is a container for the UserRecord
class. The notebook.py is based on the User class in user.py.
Notebook.py  simply maintains a dictionary of these. My plan was to
merge user.py/user_db.py into a single file. I will attach the code I
started below for reference called glasslab_user.py. Basically the the
idea is to merge the methods of the User class and the UserRecord
class.

Here is my use case. I have a small lab with mostly linux boxes, one
or two window boxes. We run a web server and svn repo for our students
and collaborators. We do image compression, analysis and recognition
research. The authentication we have goes through an LDAP. It is able
to do the authentication for both our web server and all the linux
boxes as well. On odd numbered Thursdays during a full moon we can get
the windows boxes to authenticate using pgina but thats another story.
I want to set up a group called sage_users and another group called
sage_admins on my ldap. On a login attempt I would like sage to see if
the user one of these groups and treat them accordingly. At this point
I have a small group and am not really concerned about speed so every
piece of information, user name, email address, password, may be
queried from the ldap each time. For a larger system it might make
sense to cache this information. I am guessing that sage should
probably keeps a couple of local “accounts” that do not depend on the
LDAP such as admin, guest, and pub. I do not want to allow my users to
create accounts... I have a separate mechanism for this via the ldap.

While this is not critically important, I have an apache web server
and I do a reverse proxy to an internal machine that runs sage.I would
eventually like the sage jobs to run on a couple of very fast multi-
core machines. We also have access to some Beowulf clusters so
distributed jobs would be very nice. All our users have disk space on
NFS shared accounts. It would also be good if the data related to that
user were somehow stored in their directory although thats is
definitely only a “nice to have”.

Here was the outline for my proposed approach:
Make the UserDatabase class subclass dict. I had some difficulty
overriding its constructor but it is reasonably easy to override the
getitem/setitem methods and key method. The key method makes a query
to the ldap to get all the users and takes a union of the ldap users
with the local users which is
made unique to allow for caching, and returns a list of usernames. On
a call to getitem, we can make a call to the superclass dict getitem
to see if we have the user locally. If not we catch the keyerror
exception, and check if the user is in the ldap. If so great, if not
we raise a keyerror exception and let the caller deal with it (not a
current user case). For local users
we can use the current md5 hashed password mechanism. For ldap users
the user object can either become a thin proxy, that is all calls to
get or set methods are passed to and from ldap, or on first call a
local object is created by coping all the fields from the lap EXCEPT
the password. The password should be maintained at the LDAP.

The User object contains a password object which has an overridden
__eq__ class as explained in an earlier post. This password object
also contains the username. Passwords are checked like this
Bob.password == input_password, where Bob is a user, Bob.password is a
password object and input_password is either a string or a password
object. The __eq__ makes the ldap query if the user is an ldap user or
the hash check if the user is local.

One way to stage this is to make the modifications of localizing the
User code first with the help of William and others familiar with the
structure of sage. The password class would be implemented just to
support the hash method... I think I basically have that. The reason
to do it this way is that William is probably more able to mess with
twist.py and notebook.py and run_notebook.py without running into all
the problems I did.

Once all the user stuff is in ONE PLACE ... it is fairly trivial to
drop in the ldap stuff on password as a “small patch”.

I am including all the files I was building.... the modifications
necessary to the rest of the code I am not really sure... there only
seem to be two places where there is a database of users but I am not
really certain how guard.py and avatars.py mix in.

A word of warning on the attached files.
(1) I scrubbed info from glasslab_conf.py obviously...I used some code
that makes a dict look like an object... not sure whether this is that
useful beyond cool.
(2) I am abroad and am including some script to set up an ssh tunnel.
Our ldap is only open in our local network so I wanted to be able to
debug from outside. This is the glasslab_tunnel.py ... it mostly works
although it depends on having ssh set up properly.
(3)     the glasslab_authentication.py code has all the functions that use
pyldap. As I said I was trying to set up tunnels possibly so this can
be simplified a bit. Also on our ldap the userid is not the primary
key for authentication. You need the common name or cn. So I do an
anonymous search for userid to common name first. The authentication
then tries to bind using the username/password for authentication.
Password fails or succeeds on that bind. Some folks will have the
searches also password protected. Since our network is internal we do
not care but more general support would require the initial search uid
to password to bind with a system user/password stored by sage and
with limited permissions (to search).  Thats about it. Hopefully this
is useful.

Will check back in an pitch in when I can. I love sage and greatly
appreciate the hard work of everyone who is contributing.

http://glasslab.engr.ccny.cuny.edu/glasslab/files/sage_ldap.tgz
--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---

Reply via email to