/** * Create a new project group based on project name. * * @static * @param $projectname * @return bool */ static function createProjectGroup($projectname) { global $wgAuth; global $wgOpenStackManagerLDAPProjectGroupBaseDN; OpenStackNovaLdapConnection::connect(); $projectGroupName = self::$prefix . $projectname; $projectGroup = array(); $projectGroup['objectclass'][] = 'posixgroup'; $projectGroup['objectclass'][] = 'groupofnames'; $projectGroup['cn'] = $projectGroupName; $projectGroup['gidnumber'] = OpenStackNovaUser::getNextIdNumber($wgAuth, 'gidnumber'); $projectGroupDN = 'cn=' . $projectGroupName . ',' . $wgOpenStackManagerLDAPProjectGroupBaseDN; # TODO: If project group creation fails we need to be able to fail gracefully $success = LdapAuthenticationPlugin::ldap_add($wgAuth->ldapconn, $projectGroupDN, $projectGroup); if ($success) { $wgAuth->printDebug("Successfully added project group {$projectGroupName}", NONSENSITIVE); } else { $wgAuth->printDebug("Failed to add project group {$projectGroupName}: " . ldap_error($wgAuth->ldapconn), NONSENSITIVE); } return $success; }
/** * Hook to add objectclasses and attributes for users being created. * * @static * @param $auth * @param $username * @param $values * @param $writeloc * @param $userdn * @param $result * @return bool */ static function LDAPSetCreationValues( $auth, $username, &$values, $writeloc, &$userdn, &$result ) { global $wgOpenStackManagerLDAPDefaultGid; global $wgOpenStackManagerLDAPDefaultShell; global $wgOpenStackManagerLDAPUseUidAsNamingAttribute; global $wgRequest; $values['objectclass'][] = 'person'; $values['objectclass'][] = 'novauser'; $values['objectclass'][] = 'ldappublickey'; $values['objectclass'][] = 'posixaccount'; $values['objectclass'][] = 'shadowaccount'; $values['accesskey'] = OpenStackNovaUser::uuid4(); $values['secretkey'] = OpenStackNovaUser::uuid4(); $values['isnovaadmin'] = 'FALSE'; $uidnumber = OpenStackNovaUser::getNextIdNumber( $auth, 'uidnumber' ); if ( ! $uidnumber ) { $result = false; return false; } $values['cn'] = $username; if ( '' != $auth->realname ) { $values['displayname'] = $auth->realname; } $username = $wgRequest->getText( 'shellaccountname' ); if ( ! preg_match( "/^[a-z][a-z0-9\-_]*$/", $username ) ) { $result = false; return false; } $values['uid'] = $username; $base = $auth->getBaseDN( USERDN ); # Though the LDAP plugin checks to see if the user account exists, # it does not check to see if the uid attribute is already used. $result = LdapAuthenticationPlugin::ldap_search( $auth->ldapconn, $base, "(uid=$username)" ); if ( $result ) { $entries = LdapAuthenticationPlugin::ldap_get_entries( $auth->ldapconn, $result ); if ( (int)$entries['count'] > 0 ) { $auth->printDebug( "User $username already exists.", NONSENSITIVE ); # uid attribute is already in use, fail. $result = false; return false; } } $values['uidnumber'] = $uidnumber; $values['gidnumber'] = $wgOpenStackManagerLDAPDefaultGid; $values['homedirectory'] = '/home/' . $username; $values['loginshell'] = $wgOpenStackManagerLDAPDefaultShell; if ( $wgOpenStackManagerLDAPUseUidAsNamingAttribute ) { if ( $writeloc == '' ) { $auth->printDebug( "Trying to set the userdn, but write location isn't set.", NONSENSITIVE ); return false; } else { $userdn = 'uid=' . $username . ',' . $writeloc; $auth->printDebug( "Using uid as the naming attribute, dn is: $userdn", NONSENSITIVE ); } } $auth->printDebug( "User account's objectclasses: ", NONSENSITIVE, $values['objectclass'] ); $auth->printDebug( "User account's attributes: ", HIGHLYSENSITIVE, $values ); return true; }
/** * Hook to retry setting the creation values. Specifically, this will try to set a new * uid in case there's a race condition. * * @static * @param $auth * @param $username * @param $values * @param $writeloc * @param $userdn * @param $result * @return bool */ static function LDAPRetrySetCreationValues($auth, $username, &$values, $writeloc, &$userdn, &$result) { $uidnumber = OpenStackNovaUser::getNextIdNumber($auth, 'uidnumber'); if (!$uidnumber) { $result = false; return false; } $values['uidnumber'] = $uidnumber; $result = true; return true; }
/** * Create a new project based on project name. This function will also create * all roles needed by the project. * * @static * @param $projectname * @return bool */ static function createProject($projectname) { global $wgAuth; global $wgOpenStackManagerLDAPUser; global $wgOpenStackManagerLDAPProjectBaseDN; OpenStackNovaLdapConnection::connect(); $project = array(); $project['objectclass'][] = 'groupofnames'; $project['objectclass'][] = 'posixgroup'; $project['cn'] = $projectname; $project['owner'] = $wgOpenStackManagerLDAPUser; $project['gidnumber'] = OpenStackNovaUser::getNextIdNumber($wgAuth, 'gidnumber'); $projectdn = 'cn=' . $projectname . ',' . $wgOpenStackManagerLDAPProjectBaseDN; $success = LdapAuthenticationPlugin::ldap_add($wgAuth->ldapconn, $projectdn, $project); $project = new OpenStackNovaProject($projectname); if ($success) { foreach (self::$rolenames as $rolename) { $role = OpenStackNovaRole::createRole($rolename, $project); # TODO: If role addition fails, find a way to fail gracefully # Though, if the project was added successfully, it is unlikely # that role addition will fail. } $wgAuth->printDebug("Successfully added project {$projectname}", NONSENSITIVE); return true; } else { $wgAuth->printDebug("Failed to add project {$projectname}", NONSENSITIVE); return false; } }
/** * @static * @param $groupName * @param $project OpenStackNovaProject * @param $initialUser * @return null|OpenStackNovaServiceGroup */ static function createServiceGroup($inGroupName, $project, $initialUser) { global $wgAuth; global $wgOpenStackManagerLDAPUser; global $wgOpenStackManagerLDAPDefaultShell; global $wgOpenStackManagerLDAPServiceGroupBaseDN; global $wgMemc; OpenStackNovaLdapConnection::connect(); $projectPrefix = $project->getProjectName() . '.'; # We don't want naming collisions between service groups and actual groups # or users. So, prepend $projectPrefix to the requested group name. if (strpos($inGroupName, $projectPrefix, 0) === 0) { # The user was clever and already added the prefix. $groupName = $inGroupName; $simpleGroupName = substr($inGroupName, strlen($projectPrefix)); } else { $groupName = $projectPrefix . $inGroupName; $simpleGroupName = $inGroupName; } if ($initialUser) { $user = new OpenStackNovaUser($initialUser); if (!$user->userDN) { $wgAuth->printDebug("Unable to find initial user {$initialUser} for new group {$groupName}", NONSENSITIVE); return null; } $initialUserDN = $user->userDN; } $key = wfMemcKey('openstackmanager', 'servicegroup', $groupName); $wgMemc->delete($key); $group = array(); $group['objectclass'][] = 'posixgroup'; $group['objectclass'][] = 'groupofnames'; $group['cn'] = $groupName; $groupdn = 'cn=' . $groupName . ',' . $wgOpenStackManagerLDAPServiceGroupBaseDN; $group['gidnumber'] = OpenStackNovaUser::getNextIdNumber($wgAuth, 'gidnumber'); $group['member'] = array(); if ($initialUser) { $group['member'][] = $initialUserDN; } $success = LdapAuthenticationPlugin::ldap_add($wgAuth->ldapconn, $groupdn, $group); if ($success) { $wgAuth->printDebug("Successfully added service group {$groupdn}", NONSENSITIVE); } else { $wgAuth->printDebug("Failed to add service group {$groupdn}", NONSENSITIVE); return null; } # stamp out regular expressions! $homeDir = $project->getServiceGroupHomedirPattern(); $homeDir = str_ireplace('%u', $simpleGroupName, $homeDir); $homeDir = str_ireplace('%p', $projectPrefix, $homeDir); # Now create the special SG member $newGroup = self::getServiceGroupByName($groupName, $project); $userdn = $newGroup->getSpecialUserDN(); $user = array(); $user['objectclass'][] = 'shadowaccount'; $user['objectclass'][] = 'posixaccount'; $user['objectclass'][] = 'person'; $user['objectclass'][] = 'top'; $user['loginshell'] = $wgOpenStackManagerLDAPDefaultShell; $user['homedirectory'] = $homeDir; $user['uidnumber'] = $group['gidnumber']; $user['gidnumber'] = $group['gidnumber']; $user['uid'] = $groupName; $user['sn'] = $groupName; $user['cn'] = $groupName; $success = LdapAuthenticationPlugin::ldap_add($wgAuth->ldapconn, $userdn, $user); if ($success) { $wgAuth->printDebug("Successfully created service user {$userdn}", NONSENSITIVE); } else { $wgAuth->printDebug("Failed to create service user {$userdn}", NONSENSITIVE); return null; } # Create Sudo policy so that the service user can chown files in its homedir if (OpenStackNovaSudoer::createSudoer($groupName . '-chmod', $project->getProjectName(), array($groupName), array(), array('/bin/chown -R ' . $groupName . '\\:' . $groupName . ' ' . $homeDir), array('!authenticate'))) { $wgAuth->printDebug("Successfully created chmod sudo policy for {$groupName}", NONSENSITIVE); } else { $wgAuth->printDebug("Failed to creat chmod sudo policy for {$groupName}", NONSENSITIVE); } # Create Sudo policy so that members of the group can sudo as the service user if (OpenStackNovaSudoer::createSudoer('runas-' . $groupName, $project->getProjectName(), array("%" . $groupName), array($groupName), array('ALL'), array('!authenticate'))) { $wgAuth->printDebug("Successfully created run-as sudo policy for {$groupName}", NONSENSITIVE); } else { $wgAuth->printDebug("Failed to creat run-as sudo policy for {$groupName}", NONSENSITIVE); } return $newGroup; }
/** * Create a new project based on project name. This function will also create * all roles needed by the project. * * @static * @param $projectname * @return bool */ static function createProject($projectname) { global $wgAuth; global $wgOpenStackManagerLDAPUser; global $wgOpenStackManagerLDAPProjectBaseDN; OpenStackNovaLdapConnection::connect(); $project = array(); $project['objectclass'][] = 'extensibleobject'; $project['objectclass'][] = 'groupofnames'; $project['cn'] = $projectname; $project['member'] = $wgOpenStackManagerLDAPUser; $projectdn = 'cn=' . $projectname . ',' . $wgOpenStackManagerLDAPProjectBaseDN; // if we're not going to use project groups, // then create this project as a posixgroup if (!OpenStackNovaProject::useProjectGroup()) { $project['gidnumber'] = OpenStackNovaUser::getNextIdNumber($wgAuth, 'gidnumber'); $project['objectclass'][] = 'posixgroup'; } $success = LdapAuthenticationPlugin::ldap_add($wgAuth->ldapconn, $projectdn, $project); $project = new OpenStackNovaProject($projectname); if ($success) { foreach (self::$rolenames as $rolename) { OpenStackNovaRole::createRole($rolename, $project); # TODO: If role addition fails, find a way to fail gracefully # Though, if the project was added successfully, it is unlikely # that role addition will fail. } $sudoerOU = array(); $sudoerOU['objectclass'][] = 'organizationalunit'; $sudoerOU['ou'] = 'sudooers'; $sudoerOUdn = 'ou=sudoers,' . $projectdn; LdapAuthenticationPlugin::ldap_add($wgAuth->ldapconn, $sudoerOUdn, $sudoerOU); # TODO: If sudoerOU creation fails we need to be able to fail gracefully $wgAuth->printDebug("Successfully added project {$projectname}", NONSENSITIVE); // Now that we've created the Project, if we // are supposed to use a corresponding Project Group // to manage posix group permissions, do so now. if (OpenStackNovaProject::useProjectGroup()) { OpenStackNovaProjectGroup::createProjectGroup($projectname); # TODO: If project group creation fails we need to be able to fail gracefully } // Create two default, permissive sudo policies. First, // allow sudo (as root) for all members... $projectGroup = "%" . $project->getProjectGroup()->getProjectGroupName(); if (OpenStackNovaSudoer::createSudoer('default-sudo', $projectname, array($projectGroup), array(), array('ALL'), array('!authenticate'))) { $wgAuth->printDebug("Successfully created default sudo policy for {$projectname}", NONSENSITIVE); } // Now, allow all project members to sudo to all other users. $projectGroup = "%" . $project->getProjectGroup()->getProjectGroupName(); if (OpenStackNovaSudoer::createSudoer('default-sudo-as', $projectname, array($projectGroup), array("{$projectGroup}"), array('ALL'), array('!authenticate'))) { $wgAuth->printDebug("Successfully created default sudo-as policy for {$projectname}", NONSENSITIVE); } } else { $wgAuth->printDebug("Failed to add project {$projectname}", NONSENSITIVE); return false; } OpenStackNovaProject::createServiceGroupOUs($projectname); return true; }