/** * @return void */ function fetchGroupInfo($refreshCache = true) { global $wgAuth; global $wgOpenStackManagerLDAPServiceGroupBaseDN; global $wgMemc; # Load service group entry $dn = $wgOpenStackManagerLDAPServiceGroupBaseDN; $query = '(cn=' . $this->groupName . ')'; $key = wfMemcKey('openstackmanager', 'servicegroup', $this->groupName); if ($refreshCache) { $wgMemc->delete($key); $groupInfo = null; } else { $groupInfo = $wgMemc->get($key); } if (is_array($groupInfo)) { $this->groupInfo = $groupInfo; } else { $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $dn, $query); $this->groupInfo = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); $wgMemc->set($key, $this->groupInfo, 3600 * 24); } if ($this->groupInfo['count'] != "0") { $this->groupDN = $this->groupInfo[0]['dn']; } $this->usersDN = "ou=people" . "," . $wgOpenStackManagerLDAPServiceGroupBaseDN; }
/** * Fetch the host from LDAP and initialize the object * * @return void */ function fetchHostInfo() { global $wgAuth; global $wgOpenStackManagerLDAPInstanceBaseDN; $this->ip = $wgAuth->getLdapEscapedString($this->ip); $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $wgOpenStackManagerLDAPInstanceBaseDN, '(dc=' . $this->ip . ')'); $this->hostInfo = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); if ($this->hostInfo["count"] == "0") { $this->hostInfo = null; } else { $this->hostDN = $this->hostInfo[0]['dn']; } }
/** * @return void */ function fetchRoleInfo() { global $wgAuth; $dn = $this->project->projectDN; if (!$dn) { return; } $query = '(cn=' . $this->rolename . ')'; $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $dn, $query); $this->roleInfo = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); if ($this->roleInfo['count'] != "0") { $this->roleDN = $this->roleInfo[0]['dn']; } }
/** * Fetch the project group from LDAP and initialize the object * @return void */ function fetchProjectGroupInfo($refresh = true) { global $wgAuth; global $wgOpenStackManagerLDAPProjectGroupBaseDN; if ($this->loaded and !$refresh) { return; } $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $wgOpenStackManagerLDAPProjectGroupBaseDN, '(&(cn=' . $this->getProjectGroupName() . ')(objectclass=groupofnames))'); $this->projectGroupInfo = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); if (!isset($this->projectGroupInfo[0])) { $this->loaded = false; return; } $this->projectGroupDN = $this->projectGroupInfo[0]['dn']; $this->loaded = true; }
/** * Fetch the host from LDAP and initialize the object * * @return void */ function fetchHostInfo() { global $wgAuth; global $wgOpenStackManagerLDAPInstanceBaseDN; if ($this->getDomain()) { $fqdn = $this->instancename . '.' . $this->instanceproject . '.' . $this->getDomain()->getFullyQualifiedDomainName(); } else { # No domain means no instance! $this->hostInfo = null; return; } $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $wgOpenStackManagerLDAPInstanceBaseDN, '(dc=' . $fqdn . ')'); $this->hostInfo = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); if ($this->hostInfo["count"] == "0") { $this->hostInfo = null; } else { $this->hostDN = $this->hostInfo[0]['dn']; } }
/** * @return void */ function fetchRoleInfo() { global $wgAuth; global $wgOpenStackManagerLDAPGlobalRoles; $query = ''; if ($this->global) { if (isset($wgOpenStackManagerLDAPGlobalRoles["{$this->rolename}"])) { $dn = $wgOpenStackManagerLDAPGlobalRoles["{$this->rolename}"]; $query = '(objectclass=groupofnames)'; } else { # This condition would be a bug... $dn = ''; } } else { $dn = $this->project->projectDN; $query = '(cn=' . $this->rolename . ')'; } $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $dn, $query); $this->roleInfo = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); if ($this->roleInfo['count'] != "0") { $this->roleDN = $this->roleInfo[0]['dn']; } }
/** * Get all sudo policies * * @static * @return array of OpenStackNovaSudoer */ static function getAllSudoers() { global $wgAuth, $wgOpenStackManagerLDAPSudoerBaseDN; OpenStackNovaLdapConnection::connect(); $sudoers = array(); $result = LdapAuthenticationPlugin::ldap_search( $wgAuth->ldapconn, $wgOpenStackManagerLDAPSudoerBaseDN, '(&(cn=*)(objectclass=sudorole))' ); if ( $result ) { $entries = LdapAuthenticationPlugin::ldap_get_entries( $wgAuth->ldapconn, $result ); if ( $entries ) { # First entry is always a count array_shift( $entries ); foreach ( $entries as $entry ) { $sudoer = new OpenStackNovaSudoer( $entry['cn'][0] ); array_push( $sudoers, $sudoer ); } } } return $sudoers; }
/** * Get all sudo policies * * @param $projectName * @return array of OpenStackNovaSudoer */ static function getAllSudoersByProject($projectName) { global $wgAuth; OpenStackNovaLdapConnection::connect(); $sudoers = array(); $project = OpenStackNovaProject::getProjectByName($projectName); $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $project->getSudoersDN(), '(&(cn=*)(objectclass=sudorole))'); if ($result) { $entries = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); if ($entries) { # First entry is always a count array_shift($entries); foreach ($entries as $entry) { $sudoer = new OpenStackNovaSudoer($entry['cn'][0], $project); $sudoers[] = $sudoer; } } } return $sudoers; }
/** * Search groups for the supplied DN * * @param string $dn * @return array */ private function searchGroups($dn) { $this->printDebug("Entering searchGroups", NONSENSITIVE); $base = $this->getBaseDN(GROUPDN); $objectclass = $this->getConf('GroupObjectclass'); $attribute = $this->getConf('GroupAttribute'); $nameattribute = $this->getConf('GroupNameAttribute'); // We actually want to search for * not \2a, ensure we don't escape * $value = $dn; if ($value != "*") { $value = $this->getLdapEscapedString($value); } $proxyagent = $this->getConf('ProxyAgent'); if ($proxyagent) { // We'll try to bind as the proxyagent as the proxyagent should normally have more // rights than the user. If the proxyagent fails to bind, we will still be able // to search as the normal user (which is why we don't return on fail). $this->printDebug("Binding as the proxyagent", NONSENSITIVE); $this->bindAs($proxyagent, $this->getConf('ProxyAgentPassword')); } $groups = array("short" => array(), "dn" => array()); // AD does not include the primary group in the list of groups, we have to find it ourselves. // TODO: find a way to only do this search for AD domains. if ($dn != "*") { $PGfilter = "(&(distinguishedName={$value})(objectclass=user))"; $this->printDebug("User Filter: {$PGfilter}", SENSITIVE); $PGinfo = LdapAuthenticationPlugin::ldap_search($this->ldapconn, $base, $PGfilter); $PGentries = LdapAuthenticationPlugin::ldap_get_entries($this->ldapconn, $PGinfo); if ($PGentries) { $Usid = $PGentries[0]['objectsid'][0]; $PGrid = $PGentries[0]['primarygroupid'][0]; $PGsid = bin2hex($Usid); $PGSID = array(); for ($i = 0; $i < 56; $i += 2) { $PGSID[] = substr($PGsid, $i, 2); } $dPGrid = dechex($PGrid); $dPGrid = str_pad($dPGrid, 8, '0', STR_PAD_LEFT); $PGRID = array(); for ($i = 0; $i < 8; $i += 2) { array_push($PGRID, substr($dPGrid, $i, 2)); } for ($i = 24; $i < 28; $i++) { $PGSID[$i] = array_pop($PGRID); } $PGsid_string = ''; foreach ($PGSID as $PGsid_bit) { $PGsid_string .= "\\" . $PGsid_bit; } $PGfilter = "(&(objectSid={$PGsid_string})(objectclass={$objectclass}))"; $this->printDebug("Primary Group Filter: {$PGfilter}", SENSITIVE); $info = LdapAuthenticationPlugin::ldap_search($this->ldapconn, $base, $PGfilter); $PGentries = LdapAuthenticationPlugin::ldap_get_entries($this->ldapconn, $info); array_shift($PGentries); $dnMember = strtolower($PGentries[0]['dn']); $groups["dn"][] = $dnMember; // Get short name of group $memAttrs = explode(',', strtolower($dnMember)); if (isset($memAttrs[0])) { $memAttrs = explode('=', $memAttrs[0]); if (isset($memAttrs[0])) { $groups["short"][] = strtolower($memAttrs[1]); } } } } $filter = "(&({$attribute}={$value})(objectclass={$objectclass}))"; $this->printDebug("Search string: {$filter}", SENSITIVE); $info = LdapAuthenticationPlugin::ldap_search($this->ldapconn, $base, $filter); if (!$info) { $this->printDebug("No entries returned from search.", SENSITIVE); // Return an array so that other functions // don't error out. return array("short" => array(), "dn" => array()); } $entries = LdapAuthenticationPlugin::ldap_get_entries($this->ldapconn, $info); if ($entries) { // We need to shift because the first entry will be a count array_shift($entries); // Let's get a list of both full dn groups and shortname groups foreach ($entries as $entry) { $shortMember = strtolower($entry[$nameattribute][0]); $dnMember = strtolower($entry['dn']); $groups["short"][] = $shortMember; $groups["dn"][] = $dnMember; } } $this->printDebug("Returned groups:", SENSITIVE, $groups["dn"]); return $groups; }
/** * Hook to add objectclasses and attributes for users that already exist, but have * missing information. * * @static * @param $auth * @return bool */ static function LDAPSetNovaInfo( $auth ) { global $wgMemc; OpenStackNovaLdapConnection::connect(); $result = LdapAuthenticationPlugin::ldap_read( $auth->ldapconn, $auth->userInfo[0]['dn'], '(objectclass=*)', array( 'secretkey', 'accesskey', 'objectclass' ) ); $userInfo = LdapAuthenticationPlugin::ldap_get_entries( $auth->ldapconn, $result ); if ( !isset( $userInfo[0]['accesskey'] ) or !isset( $userInfo[0]['secretkey'] ) ) { $objectclasses = $userInfo[0]['objectclass']; # First entry is a count array_shift( $objectclasses ); if ( !in_array( 'novauser', $objectclasses ) ) { $values['objectclass'] = array(); # ldap_modify for objectclasses requires the array indexes be sequential. # It is stupid, yes. foreach ( $objectclasses as $objectclass ) { $values['objectclass'][] = $objectclass; } $values['objectclass'][] = 'novauser'; } $values['accesskey'] = OpenStackNovaUser::uuid4(); $values['secretkey'] = OpenStackNovaUser::uuid4(); $values['isnovaadmin'] = 'FALSE'; $success = LdapAuthenticationPlugin::ldap_modify( $auth->ldapconn, $auth->userdn, $values ); if ( $success ) { $key = wfMemcKey( 'ldapauthentication', 'userinfo', $auth->userdn ); $wgMemc->delete( $key ); $auth->printDebug( "Successfully modified the user's nova attributes", NONSENSITIVE ); return true; } else { $auth->printDebug( "Failed to modify the user's nova attributes.", NONSENSITIVE ); # Always return true, other hooks should still run, even if this fails return true; } } else { $auth->printDebug( "User has accesskey and secretkey set.", NONSENSITIVE ); return true; } }
static function AbortNewAccount($user, &$message) { global $wgRequest; global $wgAuth; global $wgUser; $shellaccountname = $wgRequest->getText('shellaccountname'); if (!preg_match("/^[a-z][a-z0-9\\-_]*\$/", $shellaccountname)) { $wgAuth->printDebug("Invalid shell name {$shellaccountname}", NONSENSITIVE); $message = wfMessage('openstackmanager-shellaccountvalidationfail')->parse(); return false; } $base = USERDN; $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $base, "(uid={$shellaccountname})"); if ($result) { $entries = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); if ((int) $entries['count'] > 0) { $wgAuth->printDebug("User {$shellaccountname} already exists.", NONSENSITIVE); $message = wfMessage('openstackmanager-shellaccountexists')->parse(); return false; } } if (class_exists('TitleBlacklist')) { return TitleBlacklistHooks::acceptNewUserName($shellaccountname, $wgUser, $message, $override = false, $log = true); } else { return true; } }
/** * Pulls all projects from LDAP and adds them as MediaWiki namespaces. Also adds * associated talk namespaces. This function must be called from LocalSettings. * * @static * @return void */ static function addNamespaces() { global $wgAuth; global $wgOpenStackManagerLDAPProjectBaseDN; global $wgExtraNamespaces; OpenStackNovaLdapConnection::connect(); $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $wgOpenStackManagerLDAPProjectBaseDN, 'owner=*'); $entries = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); if ($entries) { array_shift($entries); foreach ($entries as $entry) { $id = (int) $entry['gidnumber'][0]; $talkid = $id + 1; $name = ucwords($entry['cn'][0]); $wgAuth->printDebug("Adding namespace {$name}", NONSENSITIVE); $wgExtraNamespaces[$id] = $name; $wgExtraNamespaces[$talkid] = $name . '_talk'; } } else { $wgAuth->printDebug("Failed to find projects", NONSENSITIVE); } }
public function execute() { global $wgOpenStackManagerLDAPUsername; global $wgAuth; $user = new OpenStackNovaUser($wgOpenStackManagerLDAPUsername); $projects = OpenStackNovaProject::getAllProjects(); $failedSync = false; $attempt_count = 0; $synced_count = 0; $failed_count = 0; /** * @var $project OpenStackNovaProject */ foreach ($projects as $project) { // actually load the project info from ldap // (getAllProjects() doesn't do this) $project->fetchProjectInfo(); $projectName = $project->getProjectName(); $oldServiceGroupOUDN = 'ou=groups,' . $project->getProjectDN(); $oldServiceUserOUDN = 'ou=people,' . $project->getProjectDN(); $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $oldServiceGroupOUDN, '(objectclass=groupofnames)'); if ($result) { $this->serviceGroups = array(); $groupList = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); if (isset($groupList)) { array_shift($groupList); foreach ($groupList as $groupEntry) { $deleteme = "cn=" . $groupEntry['cn'][0] . "," . $oldServiceGroupOUDN; print "needs deleting: " . $deleteme . "..."; $attempt_count++; $success = LdapAuthenticationPlugin::ldap_delete($wgAuth->ldapconn, $deleteme); if ($success) { $synced_count++; print "done.\n"; } else { $failed_count++; print "FAILED\n"; } } } } $result = LdapAuthenticationPlugin::ldap_search($wgAuth->ldapconn, $oldServiceUserOUDN, '(objectclass=person)'); if ($result) { $this->serviceGroups = array(); $groupList = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); if (isset($groupList)) { array_shift($groupList); foreach ($groupList as $groupEntry) { $deleteme = "uid=" . $groupEntry['cn'][0] . "," . $oldServiceUserOUDN; print "user needs deleting: " . $deleteme . "..."; $attempt_count++; $success = LdapAuthenticationPlugin::ldap_delete($wgAuth->ldapconn, $deleteme); if ($success) { $synced_count++; print "done.\n"; } else { $failed_count++; print "FAILED\n"; } } } } $deleteme = $oldServiceGroupOUDN; print "ou needs deleting: " . $deleteme . "..."; $attempt_count++; $success = LdapAuthenticationPlugin::ldap_delete($wgAuth->ldapconn, $deleteme); if ($success) { $synced_count++; print "done.\n"; } else { $failed_count++; print "FAILED\n"; } $deleteme = $oldServiceUserOUDN; print "ou needs deleting: " . $deleteme . "..."; $attempt_count++; $success = LdapAuthenticationPlugin::ldap_delete($wgAuth->ldapconn, $deleteme); if ($success) { $synced_count++; print "done.\n"; } else { $failed_count++; print "FAILED\n"; } } $this->output("{$attempt_count} items needed cleanup. {$synced_count} removed, {$failed_count} failed.\n"); $this->output("Done.\n"); return $failed_count == 0; }
/** * Deletes a domain based on the domain's short name. Will fail to * delete the domain if any host entries still exist in the domain. * * @static * @param $domainname * @return bool */ static function deleteDomain( $domainname ) { global $wgAuth; OpenStackNovaLdapConnection::connect(); $domain = new OpenStackNovaDomain( $domainname ); if ( ! $domain ) { $wgAuth->printDebug( "Domain $domainname does not exist", NONSENSITIVE ); return false; } $dn = $domain->domainDN; # Domains can have records as sub entries. If sub-entries exist, fail. $result = LdapAuthenticationPlugin::ldap_list( $wgAuth->ldapconn, $dn, 'objectclass=*' ); $hosts = LdapAuthenticationPlugin::ldap_get_entries( $wgAuth->ldapconn, $result ); if ( $hosts['count'] != "0" ) { $wgAuth->printDebug( "Failed to delete domain $domainname, since it had sub entries", NONSENSITIVE ); return false; } $success = LdapAuthenticationPlugin::ldap_delete( $wgAuth->ldapconn, $dn ); if ( $success ) { $wgAuth->printDebug( "Successfully deleted domain $domainname", NONSENSITIVE ); return true; } else { $wgAuth->printDebug( "Failed to delete domain $domainname, since it had sub entries", NONSENSITIVE ); return false; } }
/** * Get all host entries in the specified domain. Returns an empty array * if no entries are found. * * @static * @param $domain OpenStackNovaDomain * @return array */ static function getAllHosts( $domain ) { global $wgAuth; OpenStackNovaLdapConnection::connect(); $hosts = array(); $result = LdapAuthenticationPlugin::ldap_search( $wgAuth->ldapconn, $domain->domainDN, '(dc=*)' ); if ( $result ) { $entries = LdapAuthenticationPlugin::ldap_get_entries( $wgAuth->ldapconn, $result ); if ( $entries ) { # First entry is always a count array_shift( $entries ); foreach ( $entries as $entry ) { $hosts[] = new OpenStackNovaHost( $entry['dc'][0], $domain ); } } } return $hosts; }
/** * Deletes a project based on project name. This function will also delete all roles * associated with the project. * * @param $projectname String * @return bool */ static function deleteProject($projectname) { global $wgAuth; OpenStackNovaLdapConnection::connect(); $project = new OpenStackNovaProject($projectname); if (!$project) { return false; } $dn = $project->projectDN; # Projects can have roles as sub-entries, we need to delete them first $result = LdapAuthenticationPlugin::ldap_list($wgAuth->ldapconn, $dn, 'objectclass=*'); $roles = LdapAuthenticationPlugin::ldap_get_entries($wgAuth->ldapconn, $result); array_shift($roles); foreach ($roles as $role) { $roledn = $role['dn']; $success = LdapAuthenticationPlugin::ldap_delete($wgAuth->ldapconn, $roledn); if ($success) { $wgAuth->printDebug("Successfully deleted role {$roledn}", NONSENSITIVE); } else { $wgAuth->printDebug("Failed to delete role {$roledn}", NONSENSITIVE); } } # Projects can have a separate group entry. If so, delete it now. if (OpenStackNovaProject::useProjectGroup()) { OpenStackNovaProjectGroup::deleteProjectGroup($projectname); } # Projects have a sudo OU and sudoers entries below that OU, we must delete them first $sudoers = OpenStackNovaSudoer::getAllSudoersByProject($project->getProjectName()); foreach ($sudoers as $sudoer) { $success = OpenStackNovaSudoer::deleteSudoer($sudoer->getSudoerName(), $project->getProjectName()); if ($success) { $wgAuth->printDebug("Successfully deleted sudoer " . $sudoer->getSudoerName(), NONSENSITIVE); } else { $wgAuth->printDebug("Failed to delete sudoer " . $sudoer->getSudoerName(), NONSENSITIVE); } } $success = LdapAuthenticationPlugin::ldap_delete($wgAuth->ldapconn, $project->getSudoersDN()); if ($success) { $wgAuth->printDebug("Successfully deleted sudoers OU " . $project->getSudoersDN(), NONSENSITIVE); } else { $wgAuth->printDebug("Failed to delete sudoers OU " . $project->getSudoersDN(), NONSENSITIVE); } # And, we need to clean up service groups. $servicegroups = $project->getServiceGroups(); foreach ($servicegroups as $group) { $groupName = $group->groupName; $success = OpenStackNovaServiceGroup::deleteServiceGroup($groupName, $project); if ($success) { $wgAuth->printDebug("Successfully deleted service group " . $groupName, NONSENSITIVE); } else { $wgAuth->printDebug("Failed to delete servie group " . $groupName, NONSENSITIVE); } } $success = LdapAuthenticationPlugin::ldap_delete($wgAuth->ldapconn, $dn); if ($success) { $wgAuth->printDebug("Successfully deleted project {$projectname}", NONSENSITIVE); return true; } else { $wgAuth->printDebug("Failed to delete project {$projectname}", NONSENSITIVE); return false; } }