Skip to content

Commit

Permalink
LDAP-Auth backend config: Add support for custom LDAP filter rules
Browse files Browse the repository at this point in the history
refs #8365
  • Loading branch information
Johannes Meyer committed Mar 11, 2015
1 parent 0758be4 commit 39a74c4
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 19 deletions.
58 changes: 48 additions & 10 deletions application/forms/Config/Authentication/LdapBackendForm.php
Expand Up @@ -55,7 +55,7 @@ public function createElements(array $formData)
'required' => true,
'label' => $this->translate('Backend Name'),
'description' => $this->translate(
'The name of this authentication provider that is used to differentiate it from others'
'The name of this authentication provider that is used to differentiate it from others.'
)
)
);
Expand All @@ -64,8 +64,10 @@ public function createElements(array $formData)
'resource',
array(
'required' => true,
'label' => $this->translate('LDAP Resource'),
'description' => $this->translate('The resource to use for authenticating with this provider'),
'label' => $this->translate('LDAP Connection'),
'description' => $this->translate(
'The LDAP connection to use for authenticating with this provider.'
),
'multiOptions' => false === empty($this->resources)
? array_combine($this->resources, $this->resources)
: array()
Expand All @@ -77,18 +79,48 @@ public function createElements(array $formData)
array(
'required' => true,
'label' => $this->translate('LDAP User Object Class'),
'description' => $this->translate('The object class used for storing users on the ldap server'),
'description' => $this->translate('The object class used for storing users on the LDAP server.'),
'value' => 'inetOrgPerson'
)
);
$this->addElement(
'text',
'filter',
array(
'allowEmpty' => true,
'label' => $this->translate('LDAP Filter'),
'description' => $this->translate(
'An additional filter to use when looking up users using the specified connection. '
. 'Leave empty to not to use any additional filter rules.'
),
'requirement' => $this->translate(
'The filter needs to be expressed as standard LDAP expression, without'
. ' outer parentheses. (e.g. &(foo=bar)(bar=foo) or foo=bar)'
),
'validators' => array(
array(
'Callback',
false,
array(
'callback' => function ($v) {
return strpos($v, '(') !== 0;
},
'messages' => array(
'callbackValue' => $this->translate('The filter must not be wrapped in parantheses.')
)
)
)
)
)
);
$this->addElement(
'text',
'user_name_attribute',
array(
'required' => true,
'label' => $this->translate('LDAP User Name Attribute'),
'description' => $this->translate(
'The attribute name used for storing the user name on the ldap server'
'The attribute name used for storing the user name on the LDAP server.'
),
'value' => 'uid'
)
Expand All @@ -106,10 +138,10 @@ public function createElements(array $formData)
'base_dn',
array(
'required' => false,
'label' => $this->translate('Base DN'),
'label' => $this->translate('LDAP Base DN'),
'description' => $this->translate(
'The path where users can be found on the ldap server. Leave ' .
'empty to select all users available on the specified resource.'
'The path where users can be found on the LDAP server. Leave ' .
'empty to select all users available using the specified connection.'
)
)
);
Expand Down Expand Up @@ -142,11 +174,17 @@ public static function isValidAuthenticationBackend(Form $form)
ResourceFactory::createResource($form->getResourceConfig()),
$form->getElement('user_class')->getValue(),
$form->getElement('user_name_attribute')->getValue(),
$form->getElement('base_dn')->getValue()
$form->getElement('base_dn')->getValue(),
$form->getElement('filter')->getValue()
);
$ldapUserBackend->assertAuthenticationPossible();
} catch (AuthenticationException $e) {
$form->addError($e->getMessage());
if (($previous = $e->getPrevious()) !== null) {
$form->addError($previous->getMessage());
} else {
$form->addError($e->getMessage());
}

return false;
} catch (Exception $e) {
$form->addError(sprintf($form->translate('Unable to validate authentication: %s'), $e->getMessage()));
Expand Down
29 changes: 23 additions & 6 deletions library/Icinga/Authentication/Backend/LdapUserBackend.php
Expand Up @@ -9,6 +9,7 @@
use Icinga\Protocol\Ldap\Connection;
use Icinga\Exception\AuthenticationException;
use Icinga\Protocol\Ldap\Exception as LdapException;
use Icinga\Protocol\Ldap\Expression;

class LdapUserBackend extends UserBackend
{
Expand All @@ -25,14 +26,23 @@ class LdapUserBackend extends UserBackend

protected $userNameAttribute;

protected $customFilter;

protected $groupOptions;

public function __construct(Connection $conn, $userClass, $userNameAttribute, $baseDn, $groupOptions = null)
{
public function __construct(
Connection $conn,
$userClass,
$userNameAttribute,
$baseDn,
$cutomFilter,
$groupOptions = null
) {
$this->conn = $conn;
$this->baseDn = trim($baseDn) !== '' ? $baseDn : $conn->getDN();
$this->baseDn = trim($baseDn) ?: $conn->getDN();
$this->userClass = $userClass;
$this->userNameAttribute = $userNameAttribute;
$this->customFilter = trim($cutomFilter);
$this->groupOptions = $groupOptions;
}

Expand All @@ -43,12 +53,18 @@ public function __construct(Connection $conn, $userClass, $userNameAttribute, $b
*/
protected function selectUsers()
{
return $this->conn->select()->setBase($this->baseDn)->from(
$query = $this->conn->select()->setBase($this->baseDn)->from(
$this->userClass,
array(
$this->userNameAttribute
)
);

if ($this->customFilter) {
$query->addFilter(new Expression($this->customFilter));
}

return $query;
}

/**
Expand Down Expand Up @@ -88,9 +104,10 @@ public function assertAuthenticationPossible()

if ($result === null) {
throw new AuthenticationException(
'No objects with objectClass="%s" in DN="%s" found.',
'No objects with objectClass="%s" in DN="%s" found. (Filter: %s)',
$this->userClass,
$this->baseDn
$this->baseDn,
$this->customFilter ?: 'None'
);
}

Expand Down
2 changes: 2 additions & 0 deletions library/Icinga/Authentication/UserBackend.php
Expand Up @@ -103,6 +103,7 @@ public static function create($name, ConfigObject $backendConfig)
$backendConfig->get('user_class', 'user'),
$backendConfig->get('user_name_attribute', 'sAMAccountName'),
$backendConfig->get('base_dn', $resource->getDN()),
$backendConfig->get('filter'),
$groupOptions
);
break;
Expand Down Expand Up @@ -130,6 +131,7 @@ public static function create($name, ConfigObject $backendConfig)
$backendConfig->user_class,
$backendConfig->user_name_attribute,
$backendConfig->get('base_dn', $resource->getDN()),
$backendConfig->get('filter'),
$groupOptions
);
break;
Expand Down
3 changes: 2 additions & 1 deletion modules/setup/application/forms/AdminAccountPage.php
Expand Up @@ -272,7 +272,8 @@ protected function fetchUsers()
ResourceFactory::createResource(new ConfigObject($this->resourceConfig)),
$this->backendConfig['user_class'],
$this->backendConfig['user_name_attribute'],
$this->backendConfig['base_dn']
$this->backendConfig['base_dn'],
$this->backendConfig['filter']
);
} else {
throw new LogicException(
Expand Down
8 changes: 6 additions & 2 deletions modules/setup/library/Setup/Steps/AuthenticationStep.php
Expand Up @@ -126,11 +126,15 @@ public function getSummary()
. '</tr>'
. ($authType === 'ldap' ? (
'<tr>'
. '<td><strong>' . t('User Object Class') . '</strong></td>'
. '<td><strong>' . mt('setup', 'User Object Class') . '</strong></td>'
. '<td>' . $this->data['backendConfig']['user_class'] . '</td>'
. '</tr>'
. '<tr>'
. '<td><strong>' . t('User Name Attribute') . '</strong></td>'
. '<td><strong>' . mt('setup', 'Custom Filter') . '</strong></td>'
. '<td>' . trim($this->data['backendConfig']['filter']) ?: t('None', 'auth.ldap.filter') . '</td>'
. '</tr>'
. '<tr>'
. '<td><strong>' . mt('setup', 'User Name Attribute') . '</strong></td>'
. '<td>' . $this->data['backendConfig']['user_name_attribute'] . '</td>'
. '</tr>'
) : ($authType === 'external' ? (
Expand Down

0 comments on commit 39a74c4

Please sign in to comment.