I am using CAS authentication and trying to get the cas_ldap_sync_users.php script working. I am able to authenticate and all user fields are being mapped so I know that a connection to the LDAP server is being established.
When I try the sync script it connects, creates the temp table, sits there for 30 minutes and then returns "Did not get any users from LDAP error? exiting" I have a feeling that it is related to the number of users in our LDAP dir, just over 645,000.
I am able to browse the directory through an LDAP browser just fine and like I said before if I login it maps fields perfectly for each individual user.
Is there a timeout setting in the authentication scripts somewhere that I can play with to see if it is timeing out before getting all users or some way that I can limit the number of users I get from LDAP?
Scott Karren
If I'm not mistaken, there is a limit by default, the number of records return on an ldap query.
It is a Sun Directory Server, Here is my ldap config.
Version - 3
LDAP encoding - utf-8
UserType - PosixAccount(Rfc2307)
Contexts ou=utah.edu
Search Subcontexts - Yes
Deference Alias - No
User attribute - unid
member attribute - blank
member attribute uses DN - blank
Object Class - *
Scott Karren
I have narrowed the problem down to the fact that the LDAP server is timing out trying to get 645,000 users. No amount of tweaking on the Moodle side has helped and the group that manages the LDAP is unable to reset the timeout or max query size. Because the LDAP is part of UEN (Utah Education Network) it includes all prospective university students (all senior and graduated high school students). I don't needs these people. Is there someplace in the auth.php file that I can hardcode the search query for the attributes that I want to get?
Any help is appreciated.
Scott Karren
If you are using a recent 1.8 or 1.9 version (later than 2008.08.24), you can set the objecClass setting to any valid LDAP filter to select the users subset you are interested in.
For example you can set it to:
(&(objectClass=user)(postalCode=20500))
and you'll only get those users whose postal code is 20500.
Saludos. Iñaki.
Let me make sure I understand correctly. Would this filter go in the objectclass setting in the LDAP settings screen? If so would that filter only allow users with the postal code of 20500 to login to the system?
I am using CAS authentication but I need to sync users from the LDAP that I am connecting to. I am mainly concerned with being able to sync employees, but I need to leave the system accessible to students as well.
In looking at the auth.php in the CAS directory I noticed these lines of code
////
//// get user's list from ldap to sql in a scalable fashion
////
// prepare some data we'll need
$filter = "(&(".$this->config->user_attribute."=*)(".$this->config->objectclass."))";
Can I rewrite this line to look only for uuemployee=uuCurrentEmployee for the sync only?
Scott
Would this filter go in the objectclass setting in the LDAP settings screen?
Yes, the filter would go in the objectclass setting in the LDAP settings screen. But this is only available in the LDAP plugin, not the CAS plugin (even if you use LDAP as the CAS backend; both plugins are completely independent from 1.8 on).
If so would that filter only allow users with the postal code of 20500 to login to the system?
No, login doesn't have into account the objectclass value, but the user attribute setting only. So any user inside the configured contexts should be able to log in.
Can I rewrite this line to look only for uuemployee=uuCurrentEmployee for the sync only?
Sure you can Just make sure you rewrite it again every time you upgrade your moodle install!
Saludos. Iñaki.
$filter = "(&(".$this->config->user_attribute."=*)(".$this->config->objectclass."))";
I have tried $filter = '(&('.$this->config->user_attribute.'=*)'.$this->config->objectclass.'=uuCurrentEmployee)';
But this just results in an argument error on a different line. Can you help me here?
Scott
Assuming that 'uuemployee' is the attribute you want to check for, and that 'uuCurrentEmployee' is the value that attribute should have, something like the following should do the trick:
$filter = "(&(".$this->config->user_attribute."=*)(".$this->config->objectclass.")(uuemployee=uuCurrentEmployee))";
Saludos. Iñaki.
Thank you!! That filter worked very well for me. My LDAP result set is down from 645,000 to just under 30,000.
The script connects and runs and starts to either insert or update users, but is stopping after 30 minutes with the error "LDAP Module cannot connect to any servers" It does not seem to matter what I do to tweak config settings it still stops at 30 minutes (+/- a couple of minutes). Any ideas what might be happening here?
Scott Karren
http://moodle.org/mod/forum/discuss.php?d=115460
which may be the same issue. It seems that the connections do not close.
In my case I am calling sync_users(1000) but I tried sync_users(1) without any benefit. Also, I tweaked LDAP's MAXPAGESIZE without any noticeable effect.
Alan
This is very interesting, are you seeing these connections on your webserver or on the LDAP server? In looking at my webserver with the sync script running I have almost 500000 active tcp connections, when the script closes that number drops just a little bit.
Are you able to sync any users or does the script just sit there? I have tried variations on both the sync_users and bulk_insert with the same results.
Scott Karren
The wait state is a normal state. After TCP closes a connection, the standard mandates that the socket associated with that connection must remain in a waiting state for some time (up to four minutes!) before we can reuse it, to make really sure both ends have closed it properly.
The problem you are seeing is a mix of the way Moodle queries the LDAP server (it opens a new connection to get the user details, once it has determined the user has to be added/updated) and your LDAP server not expiring closed connections fast enough (and probably imposing a hard limit on the number of 'active/waiting' connections).
You should probably file a bug in the tracker, pointing it to this thread, and post the bug number here, so we can track it
Saludos. Iñaki.
What command line are you using to run the script? It might happen that PHP is terminating the script because it has reached the max_execution_time value (beware that PHP doesn't count system calls as execution time, so time spent inside ldap connections, etc won't count towards that time limit). Also the script might be reaching the memory_limit value.
For a user set that big, setting generous limits for both max_execution_time and memory_limit is usually a good idea, in addition to enabling debugging and logging options, as recommended at the top of the auth_ldap_sync_users.php script.
Saludos. Iñaki.
Right now max_execution_time=30, max_input_time=60, and memory limit=128M are what are set in the php.ini file.
What would you suggest for the max_execution_time and memory_limit?
Scott Karren
Humm, you are using CAS. I don't know why but I thought you were using LDAP. Will have to recheck some things, as the CAS plugin and the LDAP plugin are no longer using the same code, so things could work a little bit different.
The memory_limit value is probably ok. I'd set the max_execution_time to 900 or even '0' (to disable it completely). Hmmmm, acording to http://www.php.net/manual/en/info.configuration.php#ini.max-execution-time max_execution_time is set to 0 when running php on the command line, so doesn't look like this could be the problem.
Anyway, adding the debugging and logging options could shed some light, so I'd run it like this:
C:\php\edutest\php-win.exe -d memory_limit=512M -d log_errors=1 -d error_reporting=E_ALL -d display_errors=0 -d html_errors=0 -d error_log=C:\weblogs\test\cron\syncfile-errors.log-f C:\inetroot\edutest\educationroot\auth\cas\cas_ldap_sync_users.php > C:\weblogs\test\cron\syncfile.log
And then, in addition to having a look at syncfile.log, you should have a look at the syncfile-errors.log (that will hold the PHP errors, if any).
Saludos. Iñaki.
Iñaki
I ran the command line that you suggested and am attaching the resulting files. Even increasing the memory and execution time did not help. Any thoughts.
Scott Karren
It seems the LDAP server is refusing connections after some time. You could probably be suffering the same problem as Alan Zaitchnik, but after a longer period of time.
I'll see if I can come up with a patch to reuse connections, instead of opening a new one for each user we are updating or creating anew, and see if that makes a difference.
Saludos. Iñaki.
That would be great!! Please let me know what I can do to assist.
Scott Karren
Scott,
here's a patch you can try. I've tested it locally with 700 users and it keeps only one connection open for the whole sync run.
In addition to that, it lowers the total run time from 18 seconds to 9 seconds (which I suspect is due to LDAP connections setup and tear down time).
Can you try it in a test box and see if it makes a difference for you? Put the file at the top or your moodle installation directory and then follow the steps outlined in http://docs.moodle.org/en/Development:How_to_apply_a_patch
Saludos. Iñaki.
Thank you very much for this, I have one question. The diff file patches the auth.php file in the auth/ldap dir, since I use CAS authentication and I know the auth.php in the auth/cas dir is different will this patch still work?
I am working on bringing the auth.php in the cas dir more up to date, but I am not as proficient as I would like to be.
Scott Karren
I keep on forgetting that you are using CAS instead of LDAP . Anyway, here's the same patch for the CAS auth plugin. Note that I haven't tested it, as I don't have a CAS server to test it, but it's almost a clone of the LDAP patch (I've just added a couple of missing calls to ldap_close(), but they shouldn't be called from sync_users(), so that shouldn't really make a difference).
Saludos. Iñaki.
Ok, so I have tested your patch numerous times this morning. It picked up the correct number of users, inserted/updated them accordingly and did it in half the time it used to take. 29711 users doing a full insert takes 21 minutes (emptying the user table and repopulating it), doing an update takes 16 minutes. And it did all of this using just one connection. I still need to test it and see how it does against suspending internal accounts, but as of right now it is working very well. I would definitely reccomend throwing both of these patches into core. Thank you!!!
Scott Karren
I have just committed both patches in 1.9 and HEAD (the future 2.0).
Saludos. Iñaki.