ItopAD automatic import script webservicesAD_import_accounts.php parameter modification:
'simulation', 1,$sAuthUser = utils::ReadParam('auth_user', 'user_name', true);$sAuthPwd = utils::ReadParam('auth_pwd', 'user_pass', true);// Configuration of the Active Directory connection 'host' => '192.168.**.**', // IP or FQDN of your domain controller'port' => '389', // LDAP port, 398=LDAP, 636= LDAPS'dn' => 'OU=VB-User,DC=CORP,DC=logo',// Domain DN'username' => 'CN=LDAPSearch,OU=Special-User,OU=VB-User,DC=CORP,DC=logo', // username with read access'password' => 'logo@pass', // password for above
root@ITSM:/var/www/html/new_itop# vim webservices/AD_import_accounts.php
* @author Romain Quetiez
* @author Denis Flaven
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL */////////////////////////////////////////////////////////////////////////////////// Configuration parameters: adjust them to connect to your AD server// And configure the mapping between AD groups and iTop profiles$aConfig = array( // Configuration of the Active Directory connection 'host' => '192.168.**.**', // IP or FQDN of your domain controller 'port' => '389', // LDAP port, 398=LDAP, 636= LDAPS 'dn' => 'OU=VB-User,DC=CORP,DC=logo',// Domain DN 'username' => 'CN=LDAPSearch,OU=Special-User,OU=VB-User,DC=CORP,DC=logo', // username with read access 'password' => 'logo@pass', // password for above // Query to retrieve and filter the users from AD // Example: retrieve all users from the AD Group "iTop Users" //'ldap_query' => '(&(objectCategory=user)(memberOf=CN=iTop Users,CN=Users,DC=combodo,DC=net))', // Example 2: retrieves ALL the users from AD 'ldap_query' => '(&(objectCategory=user))', // Retrieve all users // Which field to use as the iTop login samaccountname or userprincipalname ? 'login' => 'samaccountname', //'login' => 'userprincipalname', // Mapping between the AD groups and the iTop profiles 'profiles_mapping' => array( //AD Group Name => iTop Profile Name //'Administrators' => 'Administrator', 'ITSM_Administrator' => 'Administrator', 'ITSM_ChangeApprover' => 'Change Approver', 'ITSM_ChangeImplementor' => 'Change Implementor', 'ITSM_ChangeSupervisor' => 'Change Supervisor', 'ITSM_ConfigurationManager' => 'Configuration Manager', 'ITSM_DocumentAuthor' => 'Document author', 'ITSM_PortalPowerUser' => 'Portal power user', 'ITSM_PortalUser' => 'Portal user', 'ITSM_ProblemManager' => 'Problem Manager', 'ITSM_ServiceDeskAgent' => 'Service Desk Agent', 'ITSM_ServiceManager' => 'Service Manager', 'ITSM_SupportAgent' => 'Support Agent', ), // Since each iTop user must have at least one profile, assign the profile // Below to users for which there was no match in the above mapping 'default_profile' => 'Portal user', 'default_language' => 'ZH CN', // Default language for creating new users 'default_organization' => 2, // ID of the default organization for creating new contacts );// End of configuration////////////////////////////////////////////////////////////////////////////////if (file_exists('../approot.inc.php')){ // iTop 1.0.2 include('../approot.inc.php');}else // iTop 1.0 & 1.0.1{ define('APPROOT', '../');}require_once(APPROOT.'application/application.inc.php');require_once(APPROOT.'application/webpage.class.inc.php');require_once(APPROOT.'application/csvpage.class.inc.php');require_once(APPROOT.'application/clipage.class.inc.php');require_once(APPROOT.'application/startup.inc.php');// List of attributes to retrieve$aAttribs = array( 'samaccountname', 'sn', 'givenname', 'userprincipalname', 'cn', 'memberof', 'mail',);$g_aUsersCache = null; // Cache of all the iTop users to speed up searches$g_aProfilesCache = null; // Cache of all iTop profiles/** * Helper function to read attributes from LDAP data * @param hash The LDAP data for one item as returned by ldap_search * @param string The name of the attribute to retrieve * @return mixed null if no such attribute, a scalar or a array depending on the * number of values for the attribute. */ function ReadLdapValue($aEntry, $sValueName){ if (array_key_exists($sValueName, $aEntry)) { $iCount = $aEntry[$sValueName]['count']; switch($iCount) { case 0: // No value, return null return null; case 1: // Just one value, return it return $aEntry[$sValueName][0]; default: // Many values, return all of them as an array // except the 'count' entry $aValues = $aEntry[$sValueName]; unset($aValues['count']); return $aValues; } } return null;}/** * Helper function that processes 1 user at a time * @param $aData hash The input data from Active Directory * @param $index integer The index of the current user in the AD query (for reporting) * @param $aConfig hash The configuration parameter * @param $oChange CMDBChange Change to record all the changes or null if simulation mode * @return string The action undertaken 'created', 'synchronized', 'error' */ function ProcessUser($aData, $index, $aConfig, $oChange = null){ $sAction = 'error'; $sUserLogin = $aData['samaccountname']; if (!is_array($aData['memberof'])) { $aADGroups = array($aData['memberof']); } else { $aADGroups = $aData['memberof']; } $aITopProfiles = array(); foreach($aADGroups as $sGroupString) { $aMatches = array(); $sShortGroupString = ''; if (preg_match('/^CN=([^,]+)/', $sGroupString, $aMatches)) { $sShortGroupString = $aMatches[1]; } //echo "
GroupString: $sGroupString => $sShortGroupString
"; if (isset($aConfig['profiles_mapping'][$sShortGroupString])) { $aITopProfiles[] = $aConfig['profiles_mapping'][$sShortGroupString]; } } if (count($aITopProfiles) == 0) { // Each user must have at least one profile // Assign the 'default_profile' to this user $aITopProfiles[] = $aConfig['default_profile']; } echo "User#{$index}: {$aData['cn']}\n"; echo "
"; foreach($aData as $sAttrib => $value) { echo "
$sAttrib | "; echo "
"; if (is_array($value)) { echo implode(' ', $value); } else { echo htmlentities($value); } echo " |
\n"; } echo "
iTop Profiles | "; echo "
"; echo implode(' ', $aITopProfiles); echo " |
\n"; echo "
"; $sLogin = $aData[$aConfig['login']]; $oITopUser = GetUserByLogin($sLogin); if ($oITopUser == null) { // Check if a contact needs to be created or not $oPerson = GetPersonByEmail($aData['mail']); if (is_object($oPerson)) { echo "
A person with the email='{$aData['mail']}' was found ".$oPerson->GetHyperlink().". This person will be used when creating the account.
"; } else if ($oPerson == null) { echo "
A new person will be created.
"; $oPerson = new Person(); $oPerson->Set('first_name', $aData['givenname']); $oPerson->Set('name', $aData['sn']); $oPerson->Set('email', $aData['mail']); $oPerson->Set('org_id', $aConfig['default_organization']); if ($oChange != null) { $oPerson->DBInsertTracked($oChange); } } else { // Error ! Several matches found ?? throw new Exception($oPerson); } $sAction = 'created'; echo "User $sLogin will be
created in iTop"; $oITopUser = new UserLDAP; $oITopUser->Set('login', $sLogin); $oITopUser->Set('contactid', $oPerson->GetKey()); $oITopUser->Set('language', $aConfig['default_language']); // Update the profiles $oLinkSet = DBObjectSet::FromScratch('URP_UserProfile'); foreach($aITopProfiles as $sProfile) { $oLink = new URP_UserProfile; $iProfileId = GetProfileByName($sProfile); if ($iProfileId != null) { $oLink->Set('profileid', $iProfileId); $oLinkSet->AddObject($oLink); } else { echo "
Error: the profile '$sProfile' does not exist in iTop, verify the profiles_mapping configuration!
"; } } $oITopUser->Set('profile_list', $oLinkSet); if ($oChange != null) { $oITopUser->DBInsertTracked($oChange); } } else if(is_object($oITopUser)) { $sAction = 'synchronized'; echo "User $sLogin (UserLDAP::".$oITopUser->GetKey().") will be
synchronized in iTop"; // Update the profiles $oLinkSet = DBObjectSet::FromScratch('URP_UserProfile'); $oITopUser->Set('login', $sLogin); foreach($aITopProfiles as $sProfile) { $oLink = new URP_UserProfile; $iProfileId = GetProfileByName($sProfile); if ($iProfileId != null) { $oLink->Set('profileid', $iProfileId); $oLinkSet->AddObject($oLink); } else { echo "
Error: the profile '$sProfile' does not exist in iTop, verify the profiles_mapping configuration!
"; } } $oITopUser->Set('profile_list', $oLinkSet); if ($oChange != null) { $oITopUser->DBUpdateTracked($oChange); } } else { // Error, another kind of user already exists with the same login ? echo "Error: $oITopUser"; } return $sAction;}/** * Search the given user (identified by its login) in the iTop database * @param $sLogin string The login of the user * @return mixed null => nothing found, object => the user to synchronize, string => error message */function GetUserByLogin($sLogin){ global $g_aUsersCache; $result = null; if ($g_aUsersCache == null) InitUsersCache(); if (isset($g_aUsersCache[$sLogin])) { $oUser = $g_aUsersCache[$sLogin]; if (get_class($oUser) != 'UserLDAP') { $result = "A user with the same login ($sLogin), but not managed by LDAP already exists in iTop, the AD record will be ignored."; } else { $result = $oUser; } } return $result;}/** * Initializes the cache for quickly searching iTop users * @param none * @return integer Number of users fetched from iTop */function InitUsersCache(){ global $g_aUsersCache; $sOQL = "SELECT User"; $oSearch = DBObjectSearch::FromOQL($sOQL); $oSet = new CMDBObjectSet($oSearch); $iRet = $oSet->Count(); while($oUser = $oSet->Fetch()) { $g_aUsersCache[$oUser->Get('login')] = $oUser; } return $iRet;}/** * Retrieves the ID of a profile (in iTop) base on its name * @param $sProfile string Name of the profile * @return integer ID of the profile, or null is not found */function GetProfileByName($sProfileName){ global $g_aProfilesCache; $iRet = null; if ($g_aProfilesCache == null) InitProfilesCache(); if (isset($g_aProfilesCache[$sProfileName])) { $iRet = $g_aProfilesCache[$sProfileName]; } return $iRet;}/** * Initializes the cache of the iTop profiles * @param none * @return void */function InitProfilesCache(){ global $g_aProfilesCache; $sOQL = "SELECT URP_Profiles"; $oSearch = DBObjectSearch::FromOQL($sOQL); $oSet = new CMDBObjectSet($oSearch); while($oProfile = $oSet->Fetch()) { $g_aProfilesCache[$oProfile->GetName()] = $oProfile->GetKey(); }}/** * Search for a Person by email address * @param $sEmail string * @return mixed Person (if found) or null (not found) or string (error) */function GetPersonByEmail($sEmail){ static $oSearch = null; // OQL Query cache $person = null; if ($oSearch == null) { $sOQL = 'SELECT Person WHERE email = :email'; $oSearch = DBObjectSearch::FromOQL($sOQL); } $oSet = new CMDBObjectSet($oSearch, array(), array('email' => $sEmail)); switch($oSet->Count()) { case 0: $person = null; break; case 1: $person = $oSet->Fetch(); break; default: $person = ' several matches found: '.$oSet->Count()." persons have the email address '$sEmail'"; } return $person; } /****************************************************************************** * * Main program * ******************************************************************************/if (utils::IsModeCLI()){ $sAuthUser = utils::ReadParam('auth_user', 'user_name', true); $sAuthPwd = utils::ReadParam('auth_pwd', 'user_pass', true); if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd)) { UserRights::Login($sAuthUser); // Login & set the user's language } else { echo "Access restricted or wrong credentials ('$sAuthUser')"; exit; }}else{ $_SESSION['login_mode'] = 'basic'; require_once('../application/loginwebpage.class.inc.php'); LoginWebPage::DoLogin(); // Check user rights and prompt if needed $sCSVData = utils::ReadPostedParam('csvdata');}if (!UserRights::IsAdministrator()){ echo '
Access is restricted to administrators
'; exit;}// By default, run in simulation mode (i.e do nothing)#'simulation', 1, test#'simulation', 0, exec$bSimulationMode = utils::ReadParam('simulation', 1, true);$oMyChange = null;if (!$bSimulationMode){ $oMyChange = MetaModel::NewObject("CMDBChange"); $oMyChange->Set("date", time()); if (UserRights::IsImpersonated()) { $sUserString = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUser(), UserRights::GetUser()); } else { $sUserString = UserRights::GetUser(); } $oMyChange->Set("userinfo", $sUserString); $oMyChange->DBInsert();}else{ echo "Simulation mode -- no action will be performed"; echo "
Set the parameter simulation=0 to trigger the actual execution.
";} $ad = ldap_connect($aConfig['host'], $aConfig['port']) or die( "Could not connect to {$aConfig['host']} on port {$aConfig['port']}!" );echo "
Connected to {$aConfig['host']} on port {$aConfig['port']}
\n";// Set version numberldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3) or die ("Could not set ldap protocol");ldap_set_option($ad, LDAP_OPT_REFERRALS,0) or die ("could no se the ldap referrals");// Binding to ldap server$bd = ldap_bind($ad, $aConfig['username'], $aConfig['password']) or die ("Could not bind");echo "
Identified as {$aConfig['username']}
\n";$sLdapSearch = $aConfig['ldap_query'];echo "
LDAP Query: '$sLdapSearch'
";$search = ldap_search($ad, $aConfig['dn'], $sLdapSearch /*, $aAttribs*/) or die ("ldap search failed");$entries = ldap_get_entries($ad, $search);$index = 1;$aStatistics = array( 'created' => 0, 'synchronized' => 0, 'error' => 0,);$iCreated = 0;$iSynchronized = 0;$iErrors = 0; if ($entries["count"] > 0){ $iITopUsers = InitUsersCache(); echo "{$entries["count"]} user(s) found in Active Directory, $iITopUsers (including non-LDAP users) found in iTop.\n"; foreach($entries as $key => $aEntry) { //echo "
$key\n"; //print_r($aEntry); //echo "
\n"; if (strcmp($key,'count') != 0) { $aData = array(); foreach($aAttribs as $sName) { $aData[$sName] = ReadLdapValue($aEntry, $sName); } if (empty($aData['mail'])) { $aData['mail'] = $aData['userprincipalname']; } try { $sAction = ProcessUser($aData, $index, $aConfig, $oMyChange); } catch(Exception $e) { echo "
An error occured while processing $index: ".$e->getMessage()."
"; $sAction = 'error'; } echo "
\n"; $aStatistics[$sAction]++; $index++; } }}else{ echo "
Nothing found !
\n"; echo "
LDAP query was: $sLdapSearch
\n";}ldap_unbind($ad);if ($bSimulationMode){ echo "Simulation mode -- no action was performed";}echo "Statistics:";echo "
";foreach($aStatistics as $sKey => $iValue){ echo "
$sKey | \n"; echo "
$iValue |
\n";}echo "
";?>root@ITSM:/var/www/html/new_itop#
After completing the parameters, run the following command in the command line:
root@ITSM:/var/www/html/new_itop# cd webservices/root@ITSM:/var/www/html/new_itop/webservices# php AD_import_accounts.php
Execute in the scheduled task;
root@itsm-demo:~# cat /etc/crontab # /etc/crontab: system-wide crontab# Unlike any other crontab you don't have to run the `crontab'# command to install the new version when you edit this file# and files in /etc/cron.d. These files also have username fields,# that none of the other crontabs do.SHELL=/bin/shPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin# m h dom mon dow user command17 * * * * root cd / && run-parts --report /etc/cron.hourly25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )#1 */24 * * * root cd /var/www/html/itop.new/webservices/;php AD_import_accounts.php > /dev/null 2>&1