LDAP is the well known Lightweight Directory Access Protocol to implement directory services. It is easy to install LDAP on your own LAMP stack VPS in the cloud such as the one in Digital Ocean.
Having installed LDAP, how do we synchronize it to Moodle? remember, our LDAP is empty at the beginning. This will strange to many since the usual way to synchronize is from LDAP to Moodle not the other way around. But in our case we are using Moodle as the reference remember?
There are no readily available plugins to do this. I modified a Moodle plugin called Configurable Reports to do this.
Configurable reports is a remarkable though highly complicated plugin for Moodle. Basically it can generate a report based on custom SQL among many other types of reports. If you know a bit of SQL (and it is relatively easy to learn) you can generate highly customized reports this way. The plugin comes with 3 options for export: CSV, XLS, and ODF. The way I modified this plugin to achieve synchronization of my LDAP directory to Moodle was as follows:
- In the /export directory of the plugin I copied the directory called csv twice and renamed them as sync and sim respectively. So when a new SQL report is created you will be presented with 2 additional options for export: sync and sim.
- Inside of each of these directories there are 2 files: export.php and pix.gif. The gif file is a bit map icon that I modified to say LDAP (it said CSV originally).
- The export.php file is where all the action happens. The original csv export has been removed and some custom code has been added. This code does the following:
- It establishes connection to desired LDAP server using ldaps:// protocol. Make sure ports 389 and 636 are open in firewall on both sides on both servers. I may change the protocol from SSL to start TLS on standard port 389 later on. Also make sure that php-ldap module is installed and loaded. (apt-get install php7.0-ldap followed by sudo service apache restart)
- It binds using the admin account. This gives the code all the needed privileges to make modifications.
- It reads in the entries from the Moodle generated report as well as entries from the LDAP server (using the LDAP search filter that you can customize, set at the beginning of the code).
- It adds users into the appropriate organization units (ou’s) based on their ou status read from the report. In our case the mapping is set such that if the report ou contains “Teaching” that user gets added to the ou=employee in the LDAP tree. If the report ou contains “Student” that user gets added to the ou=student in the LDAP tree. These organizational units must be already present, this code does not create the ou’s in the tree, just adds users to the tree. (I needed just 2 ou’s to keep things simple. This is also easy to map to Google later on and adjust the app settings differently for employees vs students, to be explained in another post)
- It deletes those users from the LDAP directory who are not present in the report generated by the configurable_reports.
- It synchronizes all attributes from Moodle to LDAP for every user present in both directories.
The sim program only simulates the synchronization. The sync program performs the 1-way Moodle to LDAP synchronization. So we can test out what happens before actually performing the sync.
The program is fairly simple and documented to be self-explanatory and you can easily make changes to it. Make sure that your Moodle server has php_ldap installed for your version of php.
This code can be found on GitHub at https://github.com/spinozarabel/moodle-block_configurablereports/tree/master
Sample SQL code:
u.username AS 'uid' ,
CONCAT(u.FirstName,' ',u.MiddleName,' ',u.LastName) As 'cn' ,
CONCAT(u.FirstName,' ',u.MiddleName,' ',u.LastName) As 'displayName' ,
u.firstname AS 'givenName' ,
u.MiddleName AS 'initials' ,
u.lastname AS 'sn' ,
u.email AS 'mail' ,
u.institution AS 'o' ,
u.idnumber AS 'employeeNumber' ,
WHEN (u.suspended) <=> 0
WHEN (u.suspended) <=> 1
END) AS 'ou' ,
'InetOrgPerson' AS 'objectClass'
FROM prefix_cohort AS h
JOIN prefix_cohort_members AS hm ON h.id = hm.cohortid
JOIN prefix_user AS u ON hm.userid = u.id
1 = 1
# add your filtering here
ORDER BY u.username