General plugins (Local): LDAP syncing scripts

local_ldap
Maintained by Picture of Charles Fulton Charles Fulton
This plugin synchronizes Moodle cohorts against an LDAP directory using either group memberships or attribute values.
222 sites
200 downloads
7 fans

This plugin synchronizes Moodle cohorts against an LDAP directory using either group memberships or attribute values. This is a continuation of Patrick Pollet's local_ldap plugin, which in turn was inspired by MDL-25011 and MDL-25054.

This plugin requires that you have either CAS or LDAP enabled as an authentication method. It officially supports OpenLDAP and Active Directory, although only the former has unit test coverage. I do not have access to an AD environment and cannot guarantee that it will continue to work.

The synchronization tasks are managed as scheduled tasks and are disabled by default.

Screenshots

Screenshot #0

Contributors

Picture of Charles Fulton
Charles Fulton (Lead maintainer)
Please login to view contributors details and/or to contact them

Comments RSS

Show comments
  • Picture of in mmi
    Fri, 30 Jun 2017, 10:22 PM
    Hi,
    Thanks for porting Patrick Pollet's local_ldap plugin to Moodle 3.3.x !
    I'm trying to use you plugin over here in order to synchronizes Moodle (version 3.3.0) cohorts against an openLDAP directory using attribute values.
    But whenever i try to run the "Synchronize cohorts from LDAP attributes" scheduled tasks with the "Run now" link, i get this weird message:
    --
    Synchronize cohorts from LDAP attributes
    Component is not enabled (local_ldap).
    --
    And i just don't know what else i need to enable in order to activate the plugin ?


    And why i try to run the scheduled task from the command line, i see that the script get the right cohort and students (SELECT statement below) from the openldap server but don't update the moodle database with those information mixed
    Again, i must be missing something but i just don't know what ? root@localhost:/var/www/moodle/admin/tool/task/cli# php schedule_task.php --showdebugging --showsql --execute=\\local_ldap\\task\\attribute_sync_task
    --------------------------------
    SELECT * FROM dml_task_scheduled WHERE classname = $1
    [array (
    0 => '\\local_ldap\\task\\attribute_sync_task',
    )]
    --------------------------------
    Query took: 0.0014050006866455 seconds.
    --------------------------------
    --------------------------------
    SELECT * FROM dml_user WHERE id = $1 AND deleted = $2
    [array (
    0 => '2',
    1 => 0,
    )]
    --------------------------------
    Query took: 0.0024418830871582 seconds.
    --------------------------------
    --------------------------------
    SELECT * FROM dml_context WHERE contextlevel = $1 AND instanceid = $2
    [array (
    0 => 50,
    1 => '1',
    )]
    --------------------------------
    Query took: 0.00089883804321289 seconds.
    --------------------------------
    Execute scheduled task: Synchronize cohorts from LDAP attributes (local_ldap\task\attribute_sync_task)
    --------------------------------
    SELECT a.attnum, a.attname AS field, t.typname AS type, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, d.adsrc
    FROM pg_catalog.pg_class c
    JOIN pg_catalog.pg_namespace as ns ON ns.oid = c.relnamespace
    JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
    JOIN pg_catalog.pg_type t ON t.oid = a.atttypid
    LEFT JOIN pg_catalog.pg_attrdef d ON (d.adrelid = c.oid AND d.adnum = a.attnum)
    WHERE relkind = 'r' AND c.relname = 'dml_lock_db' AND c.reltype > 0 AND a.attnum > 0
    AND (ns.nspname = current_schema() OR ns.oid = pg_my_temp_schema())
    ORDER BY a.attnum
    --------------------------------
    Query took: 0.0040478706359863 seconds.
    --------------------------------
    --------------------------------
    SELECT * FROM dml_lock_db WHERE resourcekey = $1
    [array (
    0 => 'core_cron',
    )]
    --------------------------------
    Query took: 0.0010879039764404 seconds.
    --------------------------------
    --------------------------------
    SELECT pg_try_advisory_lock($1, $2) AS locked
    [array (
    0 => 1043963308,
    1 => '1',
    )]
    --------------------------------
    Query took: 0.0007178783416748 seconds.
    --------------------------------
    --------------------------------
    SELECT * FROM dml_lock_db WHERE resourcekey = $1
    [array (
    0 => '\\local_ldap\\task\\attribute_sync_task',
    )]
    --------------------------------
    Query took: 0.00076699256896973 seconds.
    --------------------------------
    --------------------------------
    SELECT pg_try_advisory_lock($1, $2) AS locked
    [array (
    0 => 1043963308,
    1 => '2',
    )]
    --------------------------------
    Query took: 0.00069594383239746 seconds.
    --------------------------------
    --------------------------------
    SELECT pg_advisory_unlock($1, $2) AS unlocked
    [array (
    0 => 1043963308,
    1 => '1',
    )]
    --------------------------------
    Query took: 0.00069999694824219 seconds.
    --------------------------------
    --------------------------------
    SELECT * FROM dml_cohort WHERE idnumber = $1
    [array (
    0 => 'MYCOHORT-NAME',
    )]
    --------------------------------
    Query took: 0.0011801719665527 seconds.
    --------------------------------
    --------------------------------
    SELECT id,username FROM dml_user WHERE username = $1
    [array (
    0 => '21402292',
    )]
    --------------------------------
    Query took: 0.00087714195251465 seconds.
    --------------------------------
    #(...)
    #(...)
    --------------------------------
    SELECT id,username FROM dml_user WHERE username = $1
    [array (
    0 => '21608614',
    )]
    --------------------------------
    Query took: 0.00082302093505859 seconds.
    --------------------------------
    --------------------------------
    SELECT u.id,u.username
    FROM dml_user u
    JOIN dml_cohort_members cm ON (cm.userid = u.id AND cm.cohortid = $1)
    WHERE u.deleted=0
    [array (
    0 => '1',
    )]
    --------------------------------
    Query took: 0.0015769004821777 seconds.
    --------------------------------
    ... used 90 dbqueries
    ... used 0.21602487564087 seconds
    Scheduled task complete: Synchronize cohorts from LDAP attributes (local_ldap\task\attribute_sync_task)
    --------------------------------
    SELECT * FROM dml_task_scheduled WHERE classname = $1
    [array (
    0 => '\\local_ldap\\task\\attribute_sync_task',
    )]
    --------------------------------
    Query took: 0.00087404251098633 seconds.
    --------------------------------
    --------------------------------
    UPDATE dml_task_scheduled SET component = $1,classname = $2,lastruntime = $3,nextruntime = $4,blocking = $5,minute = $6,hour = $7,day = $8,month = $9,dayofweek = $10,faildelay = $11,customised = $12,disabled = $13 WHERE id=$14
    [array (
    'component' => 'local_ldap',
    'classname' => '\\local_ldap\\task\\attribute_sync_task',
    'lastruntime' => 1498831891,
    'nextruntime' => 1499274000,
    'blocking' => '0',
    'minute' => '0',
    'hour' => '19',
    'day' => '*',
    'month' => '*',
    'dayofweek' => '3',
    'faildelay' => 0,
    'customised' => '1',
    'disabled' => '0',
    0 => '61',
    )]
    --------------------------------
    Query took: 0.0017478466033936 seconds.
    --------------------------------
    --------------------------------
    SELECT pg_advisory_unlock($1, $2) AS unlocked
    [array (
    0 => 1043963308,
    1 => '2',
    )]
    --------------------------------
    Query took: 0.0006718635559082 seconds.
    --------------------------------

    I'd really appreciate any help with this smile
    Thanks !
  • Picture of Charles Fulton
    Fri, 30 Jun 2017, 10:57 PM
    The "component is not enabled" message is a core bug which is fixed in 3.3.1: https://tracker.moodle.org/browse/MDL-59096.
  • Picture of in mmi
    Tue, 4 Jul 2017, 6:34 PM
    Hi Charles,
    You were right ! Thanks a lot as i wouldn't have guessed myself.

    As for the fact that from the command line, the script was retrieving the right users from the ldap but not updating the moodle database, this is expected behaviour since the source code clearly state that the "LDAP users unknown to Moodle" are filtered out before synchronizing the moodle DB. And as i've just configured Jasing CAS as the main authentication method, my moodle user database is still empty right now because a moodle account is created for each CAS user only *after* the first successful CAS authentication and no user has been authenticated so far on my instance

    Again, thanks for your help and your contribution to this plugin
  • Picture of Andrew O'Brien
    Thu, 13 Jul 2017, 4:49 PM
    I've just updated to 3.3.1 and the LDAP Sync scripts will now run. All our cohorts are created, but they don't populate with any users.

    Our environment is Windows with AD from Server 2008 R2. Moodle is 3.3.1 hosted on Linux. Classes are defined in AD under OU=Classes, OU=Groups, DC=domain,DC=co,DC=uk.

    Any help with getting our cohorts populated will be very much appreciated!
  • Picture of Andrew O'Brien
    Thu, 13 Jul 2017, 5:15 PM
    I've just got this working by removing the sAMAccountName entry in the LDAP Groups Sync setup.
  • Picture of Charles Fulton
    Thu, 13 Jul 2017, 5:45 PM
    Hi Andrew, glad to hear that it's working for you now.
  • Picture of santosh dharamsale
    Wed, 27 Sep 2017, 2:17 AM
    i am not able to sync cohorts

    C:\Bitnami\moodle\php>php C:\Bitnami\moodle\apps\moodle\htdocs\admin\tool\task\c
    li\schedule_task.php --execute=\local_ldap\task\group_sync_task
    Execute scheduled task: Synchronize cohorts from LDAP groups (local_ldap\task\gr
    oup_sync_task)
    ... used 1063 dbqueries
    ... used 27.389446020126 seconds
    Scheduled task complete: Synchronize cohorts from LDAP groups (local_ldap\task\g
    roup_sync_task)
  • Picture of Emma Richardson
    Sat, 30 Sep 2017, 7:14 AM
    I just got this working with AD today. The settings that worked for me were cn and group. I had tried sAMAccountname but that did not work. Once I removed that, cohorts were created and users added.
  • Picture of Emma Richardson
    Wed, 4 Oct 2017, 10:11 PM
    Does this work with multiple ldap servers? I have added a second server and am wondering if it will sync groups from it automatically or if I need to reinstall to have it pick up the second server or it will work at all?
  • Picture of Emma Richardson
    Tue, 10 Oct 2017, 12:04 AM
    Answered my own question - looking at code, it looks like it will only query ldap plugin and not look for any clones. Will attempt to clone it for my second ldap server.
  • Picture of C Nienaber
    Tue, 12 Dec 2017, 12:46 AM
    Latest version on Moodle 3.4 fails to properly process nested AD/LDAP groups when the 'experimental setting' of providing a search base DN via the config.php setting "$CFG->cohort_synching_ldap_groups_contexts=" is used. It works fine on resolving nested groups to individual users in a cohort when this setting is not specified. If group objects within the search base contain users directly, then cohorts reflecting those groups are created and populated with those users. If group objects within the search base contain a mixture of users and nested groups then the created cohorts will contain those directly contained users, but none of the users which nested groups contain. Definitely some sort of bug which I have as yet not been able to isolate in tracing execution of the code in Patrick Pollet's locallib.php (the version which the 'LDAP Scripts' plugin pulls in seems to pull in is marked 'revision March 2013' on line 47).

    I expect that there are other people experiencing this issue who may not have spoken up, if so - please confirm that you are observing this behavior. Group synching from a base container instead of the entire directory is a must for corporate deployments where harvesting the entirety of the groups in AD to an external database is highly problematic from a security point of view (exposes group objects with sensitive uses to anyone having sufficient permissions to browse group objects in Moodle), causes unnecessary complexity and confusion for Moodle admins with unnecessary group objects being created. Working with the ill conceived group syncing modes provided by the base LDAP modules, or attribute based grouping in a situation where you're dealing with a moderately complex AD is a non-starter. IMHO, Group synching from a constrained subtree of AD should be considered a MUST / core functionality.

    Traversing the entire AD tree to discover users - the way the base LDAP modules normally do - is fine for facilitating user population and SSO, but if we were to evade this problem by not specifying a search base, then we wind up with 600 cohort objects many of which are sensitive... not a serviceable approach.
  • Picture of C Nienaber
    Tue, 12 Dec 2017, 9:54 AM
    Figured out where the problem described in my previous post arises: the function 'is_ldap_group' evaluates whether or not a group exists simply by checking for it's presence in the '$groupdnscache' array rather than actually interrogating the LDAP directory. So, in a situation where you stipulate a 'cohort_synching_ldap_groups_contexts', the cache only gets populated with groups *within* that AD subtree and any nested subgroups contained in objects in that subtree which reside in another part of the directory will not be found and resolved to usernames. I worked around this by creating a separate '$ cache object called '$all_groups_dn_cache' 'which is based on the overall BaseDN rather than pruned subtree which we are targeting for group sync. I instantiate / populate this cache object at the top of the routine which normally populates '$groupdnscache' - ldap_get_grouplist, use the new all groups cache object for lookups within 'is_ldap_group', and have 'ldap_get_group_members_ad' always search the baseDN rather than the pruned subtree.
  • Picture of Charles Fulton
    Tue, 12 Dec 2017, 10:11 PM
    Thanks for digging in to that issue. I'll try to add some tests which account for nested groups. There's an ongoing discussion at https://github.com/LafColITS/moodle-local_ldap/issues/6 about formal support for targeting specific OUs for group sync.
  • Picture of Bryan South
    Thu, 11 Jan 2018, 3:36 AM
    I have had ldap sync working for quite a while, but when I run the task for this sync, I get the following error.

    Scheduled task failed: Synchronize cohorts from LDAP groups (local_ldap\task\group_sync_task),LDAP-module cannot connect to any servers: No LDAP Host URL, Version or User Type specified in your LDAP settings
  • Picture of Bryan South
    Sat, 13 Jan 2018, 5:31 AM
    OK so I had to disable CAS, and then it used the LDAP settings instead. I still cant get anything to sync however.

    ... started 13:28:06. Current memory use 6.8MB.
    ... used 0 dbqueries
    ... used 0.042673110961914 seconds
    Scheduled task complete: Synchronize cohorts from LDAP groups (local_ldap\task\group_sync_task)

    I have tried various settings, but no luck. I do have a context set in the ldap settings, and I'm not sure if that would impact the group sync, as the groups are in a different OU in AD than the users and what OU the contact is limited to.
1 2
Please login to post comments