Re: Filter for LDAP login

68 views
Skip to first unread message

Dima Pasechnik

unread,
Jul 29, 2015, 10:02:08 PM7/29/15
to sage-support, drgn...@gmail.com, sage-n...@googlegroups.com
it's probably better to ask on sage-notebook. I cc there.

On Wednesday, 29 July 2015 18:37:28 UTC+1, Jeff Taylor wrote:
We have Sage 6.7 installed and are successfully using LDAP authentication for logins, however we would like to restrict access to a specific department.  In our case the filter would be 'department=Math', so the login query would need to be something like (&(uid=username)(department=Math))

I've been poking around in local/lib/python2.7/site-packages/sagenb-0.11.4-py2.7.egg/sagenb/notebook/auth.py and added the following under _ldap_search:
query = "(&(" + query + ")(department=Math))"

I generated a new auth.pyc, but this doesn't seem to change which accounts can log in.  I'm not sure if I'm just in the wrong bit of code, or I'm doing something else wrong (I'm not familiar with python).  Could someone possibly point me to the correct file and perhaps provide an example of including a filter to limit the allowed users?

Dima Pasechnik

unread,
Jul 29, 2015, 10:16:26 PM7/29/15
to sage-support, drgn...@gmail.com, sage-n...@googlegroups.com, dim...@gmail.com


On Thursday, 30 July 2015 03:02:07 UTC+1, Dima Pasechnik wrote:
it's probably better to ask on sage-notebook. I cc there.

On Wednesday, 29 July 2015 18:37:28 UTC+1, Jeff Taylor wrote:
We have Sage 6.7 installed and are successfully using LDAP authentication for logins, however we would like to restrict access to a specific department.  In our case the filter would be 'department=Math', so the login query would need to be something like (&(uid=username)(department=Math))

I've been poking around in local/lib/python2.7/site-packages/sagenb-0.11.4-py2.7.egg/sagenb/notebook/auth.py and added the following under _ldap_search:
query = "(&(" + query + ")(department=Math))"

this looks fishy.  You should modify the call to this
function in _get_ldapuser, not the function itself.
Check out the documentation on Python ldap module on how to create a proper query in this case.

Or do not modify this call, but just parse what you get, and filter out users which are not in Math.

HTH,
Dima

Jeff Taylor

unread,
Jul 31, 2015, 11:05:49 AM7/31/15
to sage-notebook, sage-s...@googlegroups.com, drgn...@gmail.com, dim...@gmail.com
Thanks for forwarding my message to the proper group, I'll continue from here.

Regarding your reply, this doesn't really answer the question of where I should be looking in the code to make the change correctly. And if this is in fact the right bit of code where users are looked up in LDAP, why did none of my changes have any affect on the outcome? Surely modifying the query to force an invalid user, such as "department=INVALID", should have prevented me from being able to log in with my user account?

And finally, I don't understand your suggestion to modify the call to _get_ldapuser -- That function only accepts a username and attrlist for inputs, there is nothing in the function that allows setting a filter for the lookup. According to the notes for LdapAuth, _ldap_search seems to be called first to confirm the user exists, and only after that is successful does the function proceed to call _get_ldapuser to get the details. And since _ldap_search actually has a query passed to it, wouldn't this be the ideal place to add a filter to the criteria?

Dima Pasechnik

unread,
Jul 31, 2015, 11:39:25 AM7/31/15
to Jeff Taylor, sage-notebook, sage-s...@googlegroups.com
On Fri, Jul 31, 2015 at 07:54:54AM -0700, Jeff Taylor wrote:
> Thanks for forwarding my message to the proper group, I'll continue from
> here.
>
> Regarding your reply, this doesn't really answer the question of where I
> should be looking in the code to make the change correctly. And if this
> is in fact the right bit of code where users are looked up in LDAP, why
> did none of my changes have any affect on the outcome? Surely modifying
> the query to force an invalid user, such as "department=INVALID", should
> have prevented me from being able to log in with my user account?

I can only imagine that some stale config was left somewhere...
To update .pyc file corresponding to the .py file you edit, you'd need to
delete the .pyc file and restart the server.


>
> And finally, I don't understand your suggestion to modify the call to
> _get_ldapuser

no, I said you'd have to modify the call to _ldap_search made in
_get_ldapuser; you can change the query formed on lines 94-95 of
https://github.com/sagemath/sagenb/blob/master/sagenb/notebook/auth.py
to contain department.
Then _ldap_search will get the appropriately modified query.
Print query to see what actually gets passed, in what format etc...

> -- That function only accepts a username and attrlist for
> inputs, there is nothing in the function that allows setting a filter for
> the lookup. According to the notes for LdapAuth, _ldap_search seems to be
> called first to confirm the user exists, and only after that is successful
> does the function proceed to call _get_ldapuser to get the details. And
> since _ldap_search actually has a query passed to it, wouldn't this be the
> ideal place to add a filter to the criteria?

What I suggest seems easier, as you'd only construct the query once,
rather than modify it.

What you might also do is to output the result of the call to
_ldap_search() on line 97 of auth.py to a file (or just print it)
to see what it actually returns, for debugging purposes.

HTH,
Dima

Jeff Taylor

unread,
Jul 31, 2015, 12:13:06 PM7/31/15
to sage-notebook, drgn...@gmail.com, sage-s...@googlegroups.com, dim...@gmail.com
I have to restart the webserver to test each change?  That's rather awkward since I don't have direct control of apache on this system.  I've been using "python -m py_compile auth.py" to generate the new .pyc file, isn't there some way to force the system to read the new file without a full restart?

Regarding the changes to _ldap_search / _get_ldapuser ... ah ok that makes more sense now.  So I should be able to use the same string modification to query, or directly modify the statement that creates the query, I just need to get the system to read my changes so I can test them.

Jeff Taylor

unread,
Jul 31, 2015, 1:45:27 PM7/31/15
to sage-notebook, drgn...@gmail.com, sage-s...@googlegroups.com, dim...@gmail.com
Ah ok, I see I only have to restart sage itself for the changes to take place...  So I've been testing various options, and so far everything seems to prevent a valid login.  Perhaps you can help with this?

Initially in auth.py, I was trying to modify lines 94-95 like this:
        query = filter_format(
            '(&(objectClass=*)(%s=%s))', (self._conf['ldap_username_attrib'], username))

If I can't match this, then nothing else is going to work, right?  Except this doesn't work either.  The only error I get is that my password is wrong, which doesn't tell me anything useful.  I tried adding the following line immediately after setting query:
        print 'LDAP Query: %s' % query
however nothing prints to the screen, nor do I see anything appear in sage.log.  So if I try using a print statement for debugging, where should I see the output?

Failing thus far, I thought I would just manually set the query string so I know exactly what is in it.  First I tried this:
        query = '(uid=myUser)'
and this worked exactly as expected, allowing me to log in.  Next I set it as follows:
        query = '(&(objectClass=*)(uid=myUser))'
however this again fails to log in.  WHY does this fail?  This is a valid LDAP search string, and it should always match on "objectClass=*" so why can't I log in with this query?

Thanks for your help so far, at least I'm starting to make some progress now.

Dima Pasechnik

unread,
Jul 31, 2015, 1:52:28 PM7/31/15
to Jeff Taylor, sage-notebook, sage-support
All I can recall now is that you might need to authenticate to your
LDAP server to get a response.
Perhaps the errors you see are of this kind, it just refuses to talk to you.

When we ran such a setup back in 2011 we had to get a special account
to do this authentication, to have an unattended service. Probably one
can even dig up a patch that took care of this...

I suggest that you try to play with your Python LDAP interface in an
interactive Python session...

Dima

Dima Pasechnik

unread,
Jul 31, 2015, 1:56:22 PM7/31/15
to sage-notebook, drgn...@gmail.com, sage-s...@googlegroups.com, dim...@gmail.com
oops, sorry, scratch this. Indeed, you wrote that you are able to use it for login.
That is, your change is wrong...

Jeff Taylor

unread,
Jul 31, 2015, 4:57:57 PM7/31/15
to sage-notebook, sage-s...@googlegroups.com, drgn...@gmail.com, dim...@gmail.com
After much debugging, it turns out the LDAP bind account I was given didn't have the ability to read fields other than the uid.  I was provided with another account and the full query filter is now working as intended.  Now I'm just down to fine-tuning my filter for the appropriate departments and confirming it work.

Thanks so much for all the help!

Jori Mäntysalo

unread,
Aug 10, 2015, 6:25:58 AM8/10/15
to sage-notebook
On Fri, 31 Jul 2015, Jeff Taylor wrote:

> Now I'm just down to fine-tuning my filter for the appropriate
> departments and confirming it work.

Can you write some manual after having this done? I guess that it would be
useful for many administrator.

--
Jori Mäntysalo

kcrisman

unread,
Aug 14, 2015, 8:51:23 AM8/14/15
to sage-notebook

> Now I'm just down to fine-tuning my filter for the appropriate
> departments and confirming it work.

Can you write some manual after having this done? I guess that it would be
useful for many administrator.


Yes, PLEASE, info about exactly how to use this functionality would be very valuable to add to the documentation to sagenb. 

Jeff Taylor

unread,
Aug 14, 2015, 11:45:19 AM8/14/15
to sage-n...@googlegroups.com
Not exactly a manual, but I can certainly share how I made my changes...

Specifically, you want the file in
<sage>/local/lib/python2.7/site-packages/sagenb-0.11.4-py2.7.egg/sagenb/notebook/auth.py
(this is for sage 6.7, it may change for other versions).

Around line 94 of this file, you will find lines that look like this:
query = filter_format(
'(%s=%s)', (self._conf['ldap_username_attrib'], username))

The first part of the second line is your LDAP query, and you can add to
that to validate against multiple parameters. In my case, I needed to
AND against a couple other fields, so I changed it to read:
'(&(%s=%s)(objectClass=person)(memberOf=mathematics))'

If you wanted to get more complicated, you can also perform OR
functions, such as if you wanted to give access to two different
departments:
'(&(%s=%s) (objectClass=person)
(|(memberOf=mathematics)(memberOf=engineering)) )'


To validate against these extra parameters, you also need to include
them in the attribute list being pulled from LDAP. So the final block
of code looks like this:
query = filter_format(
'(&(%s=%s)(objectClass=person)(memberOf=mathematics))',
(self._conf['ldap_username_attrib'], username))
attrlist = ["objectClass", "memberOf"]

Once you have it changed for your needs, generate the new .pyc file:
# python -m py_compile auth.py

Restart Sage and your new filter should be working. Hope that helps.

kcrisman

unread,
Aug 14, 2015, 2:59:46 PM8/14/15
to sage-notebook

Not exactly a manual, but I can certainly share how I made my changes...

Aha!  What I meant was whether you could contribute a short-but-complete description that would expand upon https://github.com/sagemath/sagenb#ldap-authentication - unless that really is all there is to it?

Jeff Taylor

unread,
Aug 14, 2015, 3:55:34 PM8/14/15
to sage-n...@googlegroups.com
After I finished with troubleshooting and getting an LDAP account that could properly read the required fields, yes, what I wrote above is all that I needed to change to add the login filtering.  As with most things, the change itself was fairly minor, but finding out WHAT to change was the real challenge.


On 08/14/2015 12:59 PM, kcrisman wrote:

Not exactly a manual, but I can certainly share how I made my changes...

Aha!  What I meant was whether you could contribute a short-but-complete description that would expand upon https://github.com/sagemath/sagenb#ldap-authentication - unless that really is all there is to it?
--
You received this message because you are subscribed to the Google Groups "sage-notebook" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-noteboo...@googlegroups.com.
Visit this group at http://groups.google.com/group/sage-notebook.
For more options, visit https://groups.google.com/d/optout.

Robin Martinjak

unread,
Aug 17, 2015, 2:22:05 AM8/17/15
to sage-n...@googlegroups.com

If you think this would be useful for other users, it should be fairly trivial to add a config option to extend the LDAP query in server_conf.py, and then use e.g.

 query = filter_format(

    '(&(%s=%s)(%s))', (self._conf['ldap_username_attrib'], username,

                                 self._conf['ldap_custom_filter']))

Which is surely preferable over adding "modify some code here and here" to the documentation.

Jeff Taylor

unread,
Aug 17, 2015, 11:08:25 AM8/17/15
to sage-n...@googlegroups.com
Personally, yes, I would vote to have this option added. The most
important aspect is that we wouldn't have to continually modify the code
as we performed software updates.

kcrisman

unread,
Aug 18, 2015, 8:30:26 PM8/18/15
to sage-notebook
Jeff, if you are able to give a review of code for this purpose I'd merge in code for this - Robin has already contributed to sagenb and knows the drill :)  I should have time to look at sagenb stuff in a couple weeks, once our semester is underway. 

Jeff Taylor

unread,
Aug 19, 2015, 10:59:23 AM8/19/15
to sage-n...@googlegroups.com
I'm probably not the best person to be giving a code review here.  I don't actually know much about Sage and have never worked with python before.  Someone else in our IT department set Sage up on the server, and I only got involved because of my experience with LDAP.
--
You received this message because you are subscribed to a topic in the Google Groups "sage-notebook" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sage-notebook/NcJD3PFYOYY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sage-noteboo...@googlegroups.com.

kcrisman

unread,
Sep 1, 2015, 3:50:05 PM9/1/15
to sage-notebook

I'm probably not the best person to be giving a code review here.  I don't actually know much about Sage and have never worked with python before.  Someone else in our IT department set Sage up on the server, and I only got involved because of my experience with LDAP.


But at the very least you know whether something is working properly when it comes to LDAP... 

Robin Martinjak

unread,
Sep 8, 2015, 6:22:55 PM9/8/15
to sage-notebook
Can someone with a working LDAP setup (this excludes me) try https://github.com/sagemath/sagenb(memberOf=mathematics/pull/347?
Note that the custom query should not be encompassed in parentheses, e.g. "&(objectClass=person)(memberOf=mathematics)" should be correct in Jeff's case.

On Tue, 1 Sep 2015 at 21:50 kcrisman <kcri...@gmail.com> wrote:

I'm probably not the best person to be giving a code review here.  I don't actually know much about Sage and have never worked with python before.  Someone else in our IT department set Sage up on the server, and I only got involved because of my experience with LDAP.


But at the very least you know whether something is working properly when it comes to LDAP... 

--
You received this message because you are subscribed to the Google Groups "sage-notebook" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-noteboo...@googlegroups.com.

kcrisman

unread,
Sep 8, 2015, 11:56:18 PM9/8/15
to sage-support, sage-n...@googlegroups.com


After much debugging, it turns out the LDAP bind account I was given didn't have the ability to read fields other than the uid.  I was provided with another account and the full query filter is now working as intended.  Now I'm just down to fine-tuning my filter for the appropriate departments and confirming it work.


Reply all
Reply to author
Forward
0 new messages