From 3872dee261779a3263155935a578173205aae533 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 30 Apr 2016 20:38:16 -0400 Subject: Added support for LDAP Posix Groups (OpenLDAP with memberUid) --- app/Core/Ldap/Group.php | 7 ++- app/Core/Ldap/Query.php | 4 ++ app/Core/Ldap/User.php | 117 ++++++++++++++++++++++++++++++++++-------- app/User/LdapUserProvider.php | 4 +- app/constants.php | 1 + 5 files changed, 107 insertions(+), 26 deletions(-) (limited to 'app') diff --git a/app/Core/Ldap/Group.php b/app/Core/Ldap/Group.php index 634d47ee..e1f60ab5 100644 --- a/app/Core/Ldap/Group.php +++ b/app/Core/Ldap/Group.php @@ -39,12 +39,11 @@ class Group * @access public * @param Client $client * @param string $query - * @return array + * @return LdapGroupProvider[] */ public static function getGroups(Client $client, $query) { - $className = get_called_class(); - $self = new $className(new Query($client)); + $self = new static(new Query($client)); return $self->find($query); } @@ -111,7 +110,7 @@ class Group throw new LogicException('LDAP full name attribute empty, check the parameter LDAP_GROUP_ATTRIBUTE_NAME'); } - return LDAP_GROUP_ATTRIBUTE_NAME; + return strtolower(LDAP_GROUP_ATTRIBUTE_NAME); } /** diff --git a/app/Core/Ldap/Query.php b/app/Core/Ldap/Query.php index 7c1524ca..0f9abb5c 100644 --- a/app/Core/Ldap/Query.php +++ b/app/Core/Ldap/Query.php @@ -66,6 +66,10 @@ class Query $this->entries = $entries; + if (DEBUG && $this->client->hasLogger()) { + $this->client->getLogger()->debug('NbEntries='.$entries['count']); + } + return $this; } diff --git a/app/Core/Ldap/User.php b/app/Core/Ldap/User.php index d23ec07e..d5e1eb8a 100644 --- a/app/Core/Ldap/User.php +++ b/app/Core/Ldap/User.php @@ -22,15 +22,25 @@ class User */ protected $query; + /** + * LDAP Group object + * + * @access protected + * @var Group + */ + protected $group; + /** * Constructor * * @access public - * @param Query $query + * @param Query $query + * @param Group $group */ - public function __construct(Query $query) + public function __construct(Query $query, Group $group = null) { $this->query = $query; + $this->group = $group; } /** @@ -44,7 +54,7 @@ class User */ public static function getUser(Client $client, $username) { - $self = new static(new Query($client)); + $self = new static(new Query($client), new Group(new Query($client))); return $self->find($self->getLdapUserPattern($username)); } @@ -53,7 +63,7 @@ class User * * @access public * @param string $query - * @return null|LdapUserProvider + * @return LdapUserProvider */ public function find($query) { @@ -67,6 +77,56 @@ class User return $user; } + /** + * Get user groupIds (DN) + * + * 1) If configured, use memberUid and posixGroup + * 2) Otherwise, use memberOf + * + * @access protected + * @param Entry $entry + * @param string $username + * @return string[] + */ + protected function getGroups(Entry $entry, $username) + { + $groupIds = array(); + + if (! empty($username) && $this->group !== null && $this->hasGroupUserFilter()) { + $groups = $this->group->find(sprintf($this->getGroupUserFilter(), $username)); + + foreach ($groups as $group) { + $groupIds[] = $group->getExternalId(); + } + } else { + $groupIds = $entry->getAll($this->getAttributeGroup()); + } + + return $groupIds; + } + + /** + * Get role from LDAP groups + * + * @access protected + * @param string[] $groupIds + * @return string + */ + protected function getRole(array $groupIds) + { + foreach ($groupIds as $groupId) { + $groupId = strtolower($groupId); + + if ($groupId === strtolower($this->getGroupAdminDn())) { + return Role::APP_ADMIN; + } elseif ($groupId === strtolower($this->getGroupManagerDn())) { + return Role::APP_MANAGER; + } + } + + return Role::APP_USER; + } + /** * Build user profile * @@ -76,21 +136,16 @@ class User protected function build() { $entry = $this->query->getEntries()->getFirstEntry(); - $role = Role::APP_USER; - - if ($entry->hasValue($this->getAttributeGroup(), $this->getGroupAdminDn())) { - $role = Role::APP_ADMIN; - } elseif ($entry->hasValue($this->getAttributeGroup(), $this->getGroupManagerDn())) { - $role = Role::APP_MANAGER; - } + $username = $entry->getFirstValue($this->getAttributeUsername()); + $groupIds = $this->getGroups($entry, $username); return new LdapUserProvider( $entry->getDn(), - $entry->getFirstValue($this->getAttributeUsername()), + $username, $entry->getFirstValue($this->getAttributeName()), $entry->getFirstValue($this->getAttributeEmail()), - $role, - $entry->getAll($this->getAttributeGroup()) + $this->getRole($groupIds), + $groupIds ); } @@ -124,7 +179,7 @@ class User throw new LogicException('LDAP username attribute empty, check the parameter LDAP_USER_ATTRIBUTE_USERNAME'); } - return LDAP_USER_ATTRIBUTE_USERNAME; + return strtolower(LDAP_USER_ATTRIBUTE_USERNAME); } /** @@ -139,7 +194,7 @@ class User throw new LogicException('LDAP full name attribute empty, check the parameter LDAP_USER_ATTRIBUTE_FULLNAME'); } - return LDAP_USER_ATTRIBUTE_FULLNAME; + return strtolower(LDAP_USER_ATTRIBUTE_FULLNAME); } /** @@ -154,18 +209,40 @@ class User throw new LogicException('LDAP email attribute empty, check the parameter LDAP_USER_ATTRIBUTE_EMAIL'); } - return LDAP_USER_ATTRIBUTE_EMAIL; + return strtolower(LDAP_USER_ATTRIBUTE_EMAIL); } /** - * Get LDAP account memberof attribute + * Get LDAP account memberOf attribute * * @access public * @return string */ public function getAttributeGroup() { - return LDAP_USER_ATTRIBUTE_GROUPS; + return strtolower(LDAP_USER_ATTRIBUTE_GROUPS); + } + + /** + * Get LDAP Group User filter + * + * @access public + * @return string + */ + public function getGroupUserFilter() + { + return LDAP_GROUP_USER_FILTER; + } + + /** + * Return true if LDAP Group User filter is defined + * + * @access public + * @return string + */ + public function hasGroupUserFilter() + { + return $this->getGroupUserFilter() !== '' && $this->getGroupUserFilter() !== null; } /** @@ -176,7 +253,7 @@ class User */ public function getGroupAdminDn() { - return LDAP_GROUP_ADMIN_DN; + return strtolower(LDAP_GROUP_ADMIN_DN); } /** diff --git a/app/User/LdapUserProvider.php b/app/User/LdapUserProvider.php index 153450d9..8d5d4b1f 100644 --- a/app/User/LdapUserProvider.php +++ b/app/User/LdapUserProvider.php @@ -170,10 +170,10 @@ class LdapUserProvider implements UserProviderInterface } /** - * Get groups + * Get groups DN * * @access public - * @return array + * @return string[] */ public function getExternalGroupIds() { diff --git a/app/constants.php b/app/constants.php index 0f438535..7ee3f16d 100644 --- a/app/constants.php +++ b/app/constants.php @@ -64,6 +64,7 @@ defined('LDAP_GROUP_MANAGER_DN') or define('LDAP_GROUP_MANAGER_DN', ''); defined('LDAP_GROUP_PROVIDER') or define('LDAP_GROUP_PROVIDER', false); defined('LDAP_GROUP_BASE_DN') or define('LDAP_GROUP_BASE_DN', ''); defined('LDAP_GROUP_FILTER') or define('LDAP_GROUP_FILTER', ''); +defined('LDAP_GROUP_USER_FILTER') or define('LDAP_GROUP_USER_FILTER', ''); defined('LDAP_GROUP_ATTRIBUTE_NAME') or define('LDAP_GROUP_ATTRIBUTE_NAME', 'cn'); // Proxy authentication -- cgit v1.2.3