Commit 69f9f1e1 authored by Aaron Wells's avatar Aaron Wells Committed by Gerrit Code Review
Browse files

Bug1180622: Refactoring the local/mahara_ldap_sync scripts into the auth/ldap plugin



Change-Id: I860d8c1bd693e5983b04d0cd75021f4cd564a871
Signed-off-by: Aaron Wells's avatarAaron Wells <aaronw@catalyst.net.nz>
parent fb95353b
<?php
/**
* Mahara: Electronic portfolio, weblog, resume builder and social networking
* Copyright (C) 2006-2009 Catalyst IT Ltd (http://www.catalyst.net.nz)
* Copyright (C) 2006-2013 Catalyst IT Ltd (http://www.catalyst.net.nz)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -17,10 +17,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package mahara
* @subpackage mahara-sync-ldap
* @subpackage auth-ldap
* @author Patrick Pollet <pp@patrickpollet.net>
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 2006-2011 Catalyst IT Ltd http://catalyst.net.nz
* @copyright (C) 2013 Catalyst IT Ltd http://catalyst.net.nz
* @copyright (C) 2011 INSA de Lyon France
*
* This file incorporates work covered by the following copyright and
......@@ -45,6 +46,11 @@
*/
/**
* This is an OPTIONAL command-line script, to be used if you want more detailed control over the
* ldap sync process than what you get from the standard ldap sync cron task. If you use this script,
* you will probably also want to disable the standard ldap sync cron task by deleting its entry from
* the auth_cron table in the database.
*
* The purpose of this CLI script is to be run as a cron job to synchronize Mahara's groups
* with groups defined on a LDAP server
*
......@@ -84,24 +90,17 @@ define('CLI', 1);
require(dirname(dirname(dirname(dirname(__FILE__)))) . '/init.php');
require(get_config('libroot') . 'cli.php');
require(get_config('docroot') . 'auth/ldap/lib.php');
// must be done before any output
$USER->reanimate(1, 1);
require(get_config('libroot') . 'institution.php');
require(get_config('libroot') . 'group.php');
require(get_config('libroot') . 'searchlib.php');
require_once(get_config('docroot') . 'auth/ldap/lib.php');
require_once(dirname(dirname(__FILE__))) . '/lib.php';
$CFG->debug_ldap_groupes = true;
//testing flag force a LDAP search for mahara username even if the user's DN
//is in the form xx=maharausername,ou=xxxx,dc=yyyyy ....
//$CFG->no_speedup_ldap = true;
$cli = get_cli();
$options = array();
......@@ -109,68 +108,119 @@ $options = array();
$options['institution'] = new stdClass();
$options['institution']->examplevalue = '\'my institution\'';
$options['institution']->shortoptions = array('i');
$options['institution']->description = get_string('institutionname', 'local.ldap');
$options['institution']->description = get_string('institutionname', 'auth.ldap');
$options['institution']->required = true;
$options['exclude'] = new stdClass();
$options['exclude']->examplevalue = '\'repository*;cipc-*[;another reg. exp.]\'';
$options['exclude']->shortoptions = array('x');
$options['exclude']->description = get_string('excludelist', 'local.ldap');
$options['exclude']->description = get_string('excludelist', 'auth.ldap');
$options['exclude']->required = false;
$options['exclude']->defaultvalue = -1;
$options['include'] = new stdClass();
$options['include']->examplevalue = '\'repository*;cipc-*[;another reg. exp.]\'';
$options['include']->shortoptions = array('o');
$options['include']->description = get_string('includelist', 'local.ldap');
$options['include']->description = get_string('includelist', 'auth.ldap');
$options['include']->required = false;
$options['include']->defaultvalue = -1;
$options['contexts'] = new stdClass();
$options['contexts']->examplevalue = '\'ou=groups,ou=pc,dc=insa-lyon,dc=fr[;anothercontext]\'';
$options['contexts']->shortoptions = array('c');
$options['contexts']->description = get_string('searchcontexts', 'local.ldap');
$options['contexts']->description = get_string('searchcontexts', 'auth.ldap');
$options['contexts']->required = false;
$options['contexts']->defaultvalue = -1;
$options['searchsub'] = new stdClass();
$options['searchsub']->examplevalue = '0';
$options['searchsub']->shortoptions = array('s');
$options['searchsub']->description = get_string('searchsubcontexts', 'local.ldap');
$options['searchsub']->description = get_string('searchsubcontextscliparam', 'auth.ldap');
$options['searchsub']->required = false;
$options['searchsub']->defaultvalue = -1;
$options['grouptype'] = new stdClass();
$options['grouptype']->examplevalue = 'course|standard';
$options['grouptype']->shortoptions = array('t');
$options['grouptype']->description = get_string('grouptype', 'local.ldap');
$options['grouptype']->description = get_string('grouptype', 'auth.ldap');
$options['grouptype']->required = false;
$options['grouptype']->defaultvalue = -1;
$options['nocreate'] = new stdClass();
$options['nocreate']->shortoptions = array('n');
$options['nocreate']->description = get_string('nocreatemissinggroups', 'local.ldap');
$options['nocreate']->description = get_string('nocreatemissinggroups', 'auth.ldap');
$options['nocreate']->required = false;
$options['nocreate']->defaultvalue = -1;
$options['nestedgroups'] = new stdClass();
$options['nestedgroups']->shortoptions = array('e');
$options['nestedgroups']->description = get_string('syncgroupsnestedgroups', 'auth.ldap');
$options['nestedgroups']->required = false;
$options['nestedgroups']->defaultvalue = -1;
$options['groupclass'] = new stdClass();
$options['groupclass']->shortoptions = array('l');
$options['groupclass']->description = get_string('syncgroupsgroupclass', 'auth.ldap');
$options['groupclass']->required = false;
$options['groupclass']->defaultvalue = -1;
$options['groupattribute'] = new stdClass();
$options['groupattribute']->shortoptions = array('a');
$options['groupattribute']->description = get_string('syncgroupsgroupattribute', 'auth.ldap');
$options['groupattribute']->required = false;
$options['groupattribute']->defaultvalue = -1;
$options['dryrun'] = new stdClass();
$options['dryrun']->description = get_string('dryrun', 'local.ldap');
$options['dryrun']->description = get_string('dryrun', 'auth.ldap');
$options['dryrun']->required = false;
$options['dryrun']->defaultvalue = false;
$settings = new stdClass();
$settings->options = $options;
$settings->info = get_string('cli_mahara_sync_groups', 'local.ldap');
$settings->info = get_string('cli_info_sync_groups', 'auth.ldap');
$cli->setup($settings);
// Check initial password and e-mail address before we install
try {
$institutionname = $cli->get_cli_param('institution');
$institution = new Institution ($institutionname);
$excludelist = explode(';', $cli->get_cli_param('exclude'));
$includelist = explode(';', $cli->get_cli_param('include'));
$CFG->debug_ldap_groupes = $cli->get_cli_param('verbose');
$excludelist = $cli->get_cli_param('exclude');
$includelist = $cli->get_cli_param('include');
// Overriding the value from config-defaults for this script
$CFG->auth_ldap_debug_sync_cron = $cli->get_cli_param('verbose');
$onlycontexts = $cli->get_cli_param('contexts');
$searchsub = $cli->get_cli_param('searchsub');
$grouptype = $cli->get_cli_param('grouptype') == 'course' ? 'course' : 'standard';
$grouptype = $cli->get_cli_param('grouptype');
// If they supplied a grouptype, only allow it to be 'course' or 'standard'
if ($grouptype != -1) {
if ($grouptype !== 'course') {
$grouptype = 'standard';
}
}
$nocreate = $cli->get_cli_param('nocreate');
$nestedgroups = $cli->get_cli_param('nestedgroups');
$groupclass = $cli->get_cli_param('groupclass');
$groupattribute = $cli->get_cli_param('groupattribute');
$dryrun = $cli->get_cli_param('dryrun');
auth_ldap_sync_groups(
$institutionname,
true,
($excludelist == -1 ? null : $excludelist),
($includelist == -1 ? null : $includelist),
($onlycontexts == -1 ? null : $onlycontexts),
($searchsub == -1 ? null : $searchsub),
($grouptype == -1 ? null : $grouptype),
($nocreate == -1 ? null : !$nocreate),
($nestedgroups == -1 ? null : $nestedgroups),
($groupclass == -1 ? null : $groupclass),
($groupattribute == -1 ? null : $groupattribute),
false,
null,
null,
$dryrun
);
}
// we catch missing parameter and unknown institution
catch (Exception $e) {
......@@ -178,159 +228,5 @@ catch (Exception $e) {
cli::cli_exit($e->getMessage(), true);
}
$cli->cli_print('---------- started at ' . date('r', time()) . ' ----------');
if ($CFG->debug_ldap_groupes) {
moodle_print_object("institution : ", $institution);
moodle_print_object("exclusion list : ", $excludelist);
moodle_print_object("inclusion list : ", $includelist);
}
$auths = auth_instance_get_matching_instances($institutionname);
if ($CFG->debug_ldap_groupes) {
moodle_print_object("auths candidates : ", $auths);
}
if (count($auths) == 0) {
cli::cli_exit(get_string('cli_mahara_nomatchingauths', 'local.ldap'));
}
//fetch current members of that institution
$params = new StdClass;
$params->institution = $institutionname;
$params->member = 1;
$params->query = '';
$params->lastinstitution = null;
$params->requested = null;
$params->invitedby = null;
$limit = 0;
//note that the studentid returned here is always null since it is retrieved
// from the table usr_institution and not from the table user ...
// we don't need it here
$data = get_institutional_admin_search_results($params, $limit);
// map user's id to username for easy retrieving
$currentmembers = array();
foreach ($data['data'] as $datum) {
$currentmembers [$datum['username']] = $datum['id'];
}
unset ($data); // save memory
if ($CFG->debug_ldap_groupes) {
moodle_print_object("current members : ".count($currentmembers).' ', $currentmembers);
}
// it is unlikely that there is mre than one LDAP per institution
foreach ($auths as $auth) {
$instance = new GAAuthLdap($auth->id);
// override defaut contexts values for the auth plugin
if ($onlycontexts) {
$instance->set_config('contexts', $onlycontexts);
}
// OVERRRIDING searchsub contexts for this auth plugin
if ($searchsub !== false) {
$instance->set_config('search_sub', $searchsub ? 'yes' : 'no');
}
//testing code process nested groups
// to enable it set CFG->ldap_process_nested_groups to 1 in config.php
//$instance->set_config('process_nested_groups',true);
if ($CFG->debug_ldap_groupes) {
moodle_print_object("config. LDAP : ", $instance->get_config());
}
$groups = $instance->ldap_get_grouplist();
if ($CFG->debug_ldap_groupes) {
moodle_print_object("Found LDAP groups : ", $groups);
}
$nbadded = 0;
foreach ($groups as $group) {
if (!ldap_sync_filter_name($group, $includelist, $excludelist)) {
continue;
}
if ($CFG->debug_ldap_groupes) {
moodle_print_object("processing group : ", $group);
}
// test whether this group exists within the institution
if (!$dbgroup = get_record('group', 'shortname', $group, 'institution', $institutionname)) {
if ($nocreate) {
$cli->cli_print('autocreation is off so skipping Mahara not existing group ' . $group);
continue;
}
$ldapusers = $instance->ldap_get_group_members($group);
if (count($ldapusers)==0) {
$cli->cli_print('will not autocreate an empty Mahara group ' . $group);
continue;
}
try {
$cli->cli_print('creating group ' . $group);
$dbgroup = array();
$dbgroup['name'] = $institutionname . ' : ' . $group;
$dbgroup['institution'] = $institutionname;
$dbgroup['shortname'] = $group;
$dbgroup['grouptype'] = $grouptype; // default standard (change to course)
$dbgroup['controlled'] = 1; //definitively
$nbadded++;
if (!$dryrun) {
$groupid = group_create($dbgroup);
}
}
catch (Exception $ex) {
$cli->cli_print($ex->getMessage());
continue;
}
} else {
$groupid = $dbgroup->id;
$cli->cli_print('group exists ' . $group);
$ldapusers = $instance->ldap_get_group_members($group);
}
// now it does exist see what members should be added/removed
if ($CFG->debug_ldap_groupes) {
moodle_print_object($group . ' : ', $ldapusers);
}
$members = array('1' => 'admin'); //must be set otherwise fatal error group_update_members: no group admins listed for group
foreach ($ldapusers as $username) {
if (isset($currentmembers[$username])) {
$id = $currentmembers[$username];
$members[$id] = 'member';
}
}
if ($CFG->debug_ldap_groupes) {
moodle_print_object('new members list : '.count($members).' ', $members);
}
unset($ldapusers); //try to save memory before memory consuming call to API
$result = $dryrun ? false : group_update_members($groupid, $members);
if ($result) {
$cli->cli_print(" -> added : {$result['added']} removed : {$result['removed']} updated : {$result['updated']}");
} else {
$cli->cli_print('-> no change for ' . $group);
}
unset ($members);
//break;
}
}
$USER->logout(); // important
cli::cli_exit('---------- ended at ' . date('r', time()) . ' ----------', true);
<?php
/**
* Mahara: Electronic portfolio, weblog, resume builder and social networking
* Copyright (C) 2006-2009 Catalyst IT Ltd (http://www.catalyst.net.nz)
* Copyright (C) 2006-2013 Catalyst IT Ltd (http://www.catalyst.net.nz)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -17,10 +17,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package mahara
* @subpackage mahara-sync-ldap
* @subpackage auth-ldap
* @author Patrick Pollet <pp@patrickpollet.net>
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 2006-2011 Catalyst IT Ltd http://catalyst.net.nz
* @copyright (C) 2013 Catalyst IT Ltd http://catalyst.net.nz
* @copyright (C) 2011 INSA de Lyon France
*
* This file incorporates work covered by the following copyright and
......@@ -45,6 +46,11 @@
*/
/**
* This is an OPTIONAL command-line script, to be used if you want more detailed control over the
* ldap sync process than what you get from the standard ldap sync cron task. If you use this script,
* you will probably also want to disable the standard ldap sync cron task by deleting its entry from
* the auth_cron table in the database.
*
* The purpose of this CLI script is to be run as a cron job to synchronize Mahara's groups
* with users having some attribute set on a LDAP server
*
......@@ -67,14 +73,10 @@
* Notes:
* - run this script on command line without any paramters to get help on all options
* - it is required to use root or the the web server accounts when executing PHP CLI scripts
* - you need to change the "www-data" to match the apache user account
* - use "su" if "sudo" not available
* - If you have a large number of groups/users, you may want to raise the memory limits
* by passing -d memory_limit=256M
* - For debugging & better logging, you are encouraged to use in the command line:
* -d log_errors=1 -d error_reporting=E_ALL -d display_errors=0 -d html_errors=0
*
*
*/
define('INTERNAL', 1);
......@@ -84,19 +86,16 @@ define('CLI', 1);
require(dirname(dirname(dirname(dirname(__FILE__)))) . '/init.php');
require(get_config('libroot') . 'cli.php');
require(get_config('docroot') . 'auth/ldap/lib.php');
// must be done before any output
$USER->reanimate(1, 1);
require(get_config('libroot') . 'institution.php');
require(get_config('libroot') . 'group.php');
require(get_config('libroot') . 'searchlib.php');
require_once(get_config('docroot') . 'auth/ldap/lib.php');
require_once(dirname(dirname(__FILE__))) . '/lib.php';
$cli = get_cli();
$options = array();
......@@ -104,77 +103,107 @@ $options = array();
$options['institution'] = new stdClass();
$options['institution']->examplevalue = '\'my institution\'';
$options['institution']->shortoptions = array('i');
$options['institution']->description = get_string('institutionname', 'local.ldap');
$options['institution']->description = get_string('institutionname', 'auth.ldap');
$options['institution']->required = true;
$options['attribute'] = new stdClass();
$options['attribute']->examplevalue = '\'eduPersonAffiliation\'';
$options['attribute']->shortoptions = array('a');
$options['attribute']->description = get_string('attributename', 'local.ldap');
$options['attribute']->required = true;
$options['attribute']->description = get_string('attributename', 'auth.ldap');
$options['attribute']->required = false;
$options['attribute']->defaultvalue = -1;
$options['exclude'] = new stdClass();
$options['exclude']->examplevalue = '\'repository*;cipc-*[;another reg. exp.]\'';
$options['exclude']->shortoptions = array('x');
$options['exclude']->description = get_string('excludelist', 'local.ldap');
$options['exclude']->description = get_string('excludelist', 'auth.ldap');
$options['exclude']->required = false;
$options['exclude']->defaultvalue = -1;
$options['include'] = new stdClass();
$options['include']->examplevalue = '\'repository*;cipc-*[;another reg. exp.]\'';
$options['include']->shortoptions = array('o');
$options['include']->description = get_string('includelist', 'local.ldap');
$options['include']->description = get_string('includelist', 'auth.ldap');
$options['include']->required = false;
$options['include']->defaultvalue = -1;
$options['contexts'] = new stdClass();
$options['contexts']->examplevalue = '\'ou=students,ou=pc,dc=insa-lyon,dc=fr[;anothercontext]\'';
$options['contexts']->shortoptions = array('c');
$options['contexts']->description = get_string('searchcontexts', 'local.ldap');
$options['contexts']->description = get_string('searchcontexts', 'auth.ldap');
$options['contexts']->required = false;
$options['contexts']->defaultvalue = -1;
$options['searchsub'] = new stdClass();
$options['searchsub']->examplevalue = '0';
$options['searchsub']->shortoptions = array('s');
$options['searchsub']->description = get_string('searchsubcontexts', 'local.ldap');
$options['searchsub']->description = get_string('searchsubcontextscliparam', 'auth.ldap');
$options['searchsub']->required = false;
$options['searchsub']->defaultvalue = -1;
$options['grouptype'] = new stdClass();
$options['grouptype']->examplevalue = 'course|standard';
$options['grouptype']->shortoptions = array('t');
$options['grouptype']->description = get_string('grouptype', 'local.ldap');
$options['grouptype']->description = get_string('grouptype', 'auth.ldap');
$options['grouptype']->required = false;
$options['grouptype']->defaultvalue = -1;
$options['nocreate'] = new stdClass();
$options['nocreate']->shortoptions = array('n');
$options['nocreate']->description = get_string('nocreatemissinggroups', 'local.ldap');
$options['nocreate']->description = get_string('nocreatemissinggroups', 'auth.ldap');
$options['nocreate']->required = false;
$options['nocreate']->defaultvalue = -1;
$options['dryrun'] = new stdClass();
$options['dryrun']->description = get_string('dryrun', 'local.ldap');
$options['dryrun']->description = get_string('dryrun', 'auth.ldap');
$options['dryrun']->required = false;
$settings = new stdClass();
$settings->options = $options;
$settings->info = get_string('cli_mahara_sync_groups_attribute', 'local.ldap');
$settings->info = get_string('cli_info_sync_groups_attribute', 'auth.ldap');
$cli->setup($settings);
try {
//REQUIRED
//REQUIRED
$institutionname = $cli->get_cli_param('institution');
$institution = new Institution ($institutionname);
$attributename = $cli->get_cli_param('attribute');
//OPTIONALS
$excludelist = explode(';', $cli->get_cli_param('exclude'));
$includelist = explode(';', $cli->get_cli_param('include'));
$CFG->debug_ldap_groupes = $cli->get_cli_param('verbose');
$excludelist = $cli->get_cli_param('exclude');
$includelist = $cli->get_cli_param('include');
// Overriding the value from config-defaults for this script run
$CFG->auth_ldap_debug_sync_cron = $cli->get_cli_param('verbose');
$onlycontexts = $cli->get_cli_param('contexts');
$searchsub = $cli->get_cli_param('searchsub');
$grouptype = $cli->get_cli_param('grouptype') == 'course' ? 'course' : 'standard';
$grouptype = $cli->get_cli_param('grouptype');
// If they supplied a grouptype, only allow it to be 'course' or 'standard'
if ($grouptype != -1) {
if ($grouptype !== 'course') {
$grouptype = 'standard';
}
}
$nocreate = $cli->get_cli_param('nocreate');
$dryrun = $cli->get_cli_param('dryrun');
auth_ldap_sync_groups(
$institutionname,
false,
($excludelist == -1 ? null : $excludelist),
($includelist == -1 ? null : $includelist),
($onlycontexts == -1 ? null : $onlycontexts),
($searchsub == -1 ? null : $searchsub),
($grouptype == -1 ? null : $grouptype),
($nocreate == -1 ? null : !$nocreate),
null,
null,
null,
true,
($attributename == -1 ? null : $attributename),
null,
$dryrun
);
}
// we catch missing parameter and unknown institution
catch (Exception $e) {
......@@ -182,153 +211,5 @@ catch (Exception $e) {
cli::cli_exit($e->getMessage(), true);
}
$cli->cli_print('---------- started at ' . date('r', time()) . ' ----------');
if ($CFG->debug_ldap_groupes) {
moodle_print_object("institution : ", $institution);
moodle_print_object("exclusion list : ", $excludelist);
moodle_print_object("inclusion list : ", $includelist);
}
$auths = auth_instance_get_matching_instances($institutionname);
if ($CFG->debug_ldap_groupes) {
moodle_print_object("auths candidates : ", $auths);
}
if (count($auths) == 0) {
cli::cli_exit(get_string('cli_mahara_nomatchingauths', 'local.ldap'));
}
//fetch current members of that institution
$params = new StdClass;
$params->institution = $institutionname;
$params->member = 1;
$params->query = '';
$params->lastinstitution = null;
$params->requested = null;
$params->invitedby = null;
$limit = 0;