mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-29 16:54:04 +02:00
Merge branch 'master' into feature/monitoring-restrictions-9009
This commit is contained in:
commit
d5dffe9a7a
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -6,3 +6,6 @@ Vagrantfile export-ignore
|
|||||||
|
|
||||||
# Normalize puppet manifests' line endings to LF on checkin and prevent conversion to CRLF when the files are checked out
|
# Normalize puppet manifests' line endings to LF on checkin and prevent conversion to CRLF when the files are checked out
|
||||||
.puppet* eol=lf
|
.puppet* eol=lf
|
||||||
|
|
||||||
|
# Include version information on `git archive'
|
||||||
|
/application/VERSION export-subst
|
||||||
|
1
application/VERSION
Normal file
1
application/VERSION
Normal file
@ -0,0 +1 @@
|
|||||||
|
$Format:%H%d %ci$
|
15
application/controllers/AboutController.php
Normal file
15
application/controllers/AboutController.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
# namespace Icinga\Application\Controllers;
|
||||||
|
|
||||||
|
use Icinga\Web\Controller\ActionController;
|
||||||
|
use Icinga\Application\Version;
|
||||||
|
|
||||||
|
class AboutController extends ActionController
|
||||||
|
{
|
||||||
|
public function indexAction()
|
||||||
|
{
|
||||||
|
$this->view->version = Version::get();
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,10 @@ class GroupController extends AuthBackendController
|
|||||||
function ($b) { return $b->getName(); },
|
function ($b) { return $b->getName(); },
|
||||||
$this->loadUserGroupBackends('Icinga\Data\Selectable')
|
$this->loadUserGroupBackends('Icinga\Data\Selectable')
|
||||||
);
|
);
|
||||||
|
if (empty($backendNames)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->view->backendSelection = new Form();
|
$this->view->backendSelection = new Form();
|
||||||
$this->view->backendSelection->setAttrib('class', 'backend-selection');
|
$this->view->backendSelection->setAttrib('class', 'backend-selection');
|
||||||
$this->view->backendSelection->setUidDisabled();
|
$this->view->backendSelection->setUidDisabled();
|
||||||
@ -100,6 +104,7 @@ class GroupController extends AuthBackendController
|
|||||||
|
|
||||||
$filterEditor = Widget::create('filterEditor')
|
$filterEditor = Widget::create('filterEditor')
|
||||||
->setQuery($members)
|
->setQuery($members)
|
||||||
|
->setSearchColumns(array('user'))
|
||||||
->preserveParams('limit', 'sort', 'dir', 'view', 'backend', 'group')
|
->preserveParams('limit', 'sort', 'dir', 'view', 'backend', 'group')
|
||||||
->ignoreParams('page')
|
->ignoreParams('page')
|
||||||
->handleRequest($this->getRequest());
|
->handleRequest($this->getRequest());
|
||||||
|
@ -28,6 +28,10 @@ class UserController extends AuthBackendController
|
|||||||
function ($b) { return $b->getName(); },
|
function ($b) { return $b->getName(); },
|
||||||
$this->loadUserBackends('Icinga\Data\Selectable')
|
$this->loadUserBackends('Icinga\Data\Selectable')
|
||||||
);
|
);
|
||||||
|
if (empty($backendNames)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->view->backendSelection = new Form();
|
$this->view->backendSelection = new Form();
|
||||||
$this->view->backendSelection->setAttrib('class', 'backend-selection');
|
$this->view->backendSelection->setAttrib('class', 'backend-selection');
|
||||||
$this->view->backendSelection->setUidDisabled();
|
$this->view->backendSelection->setUidDisabled();
|
||||||
@ -99,6 +103,7 @@ class UserController extends AuthBackendController
|
|||||||
|
|
||||||
$filterEditor = Widget::create('filterEditor')
|
$filterEditor = Widget::create('filterEditor')
|
||||||
->setQuery($memberships)
|
->setQuery($memberships)
|
||||||
|
->setSearchColumns(array('group_name'))
|
||||||
->preserveParams('limit', 'sort', 'dir', 'view', 'backend', 'user')
|
->preserveParams('limit', 'sort', 'dir', 'view', 'backend', 'user')
|
||||||
->ignoreParams('page')
|
->ignoreParams('page')
|
||||||
->handleRequest($this->getRequest());
|
->handleRequest($this->getRequest());
|
||||||
|
@ -52,7 +52,7 @@ class UsergroupbackendController extends Controller
|
|||||||
$form->setIniConfig(Config::app('groups'));
|
$form->setIniConfig(Config::app('groups'));
|
||||||
$form->setOnSuccess(function (UserGroupBackendForm $form) {
|
$form->setOnSuccess(function (UserGroupBackendForm $form) {
|
||||||
try {
|
try {
|
||||||
$form->add($form->getValues());
|
$form->add(array_filter($form->getValues()));
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$form->error($e->getMessage());
|
$form->error($e->getMessage());
|
||||||
return false;
|
return false;
|
||||||
@ -85,7 +85,12 @@ class UsergroupbackendController extends Controller
|
|||||||
$form->setIniConfig(Config::app('groups'));
|
$form->setIniConfig(Config::app('groups'));
|
||||||
$form->setOnSuccess(function (UserGroupBackendForm $form) use ($backendName) {
|
$form->setOnSuccess(function (UserGroupBackendForm $form) use ($backendName) {
|
||||||
try {
|
try {
|
||||||
$form->edit($backendName, $form->getValues());
|
$form->edit($backendName, array_map(
|
||||||
|
function ($v) {
|
||||||
|
return $v !== '' ? $v : null;
|
||||||
|
},
|
||||||
|
$form->getValues()
|
||||||
|
));
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$form->error($e->getMessage());
|
$form->error($e->getMessage());
|
||||||
return false;
|
return false;
|
||||||
|
@ -8,7 +8,7 @@ use Icinga\Web\Form;
|
|||||||
use Icinga\Data\ConfigObject;
|
use Icinga\Data\ConfigObject;
|
||||||
use Icinga\Data\ResourceFactory;
|
use Icinga\Data\ResourceFactory;
|
||||||
use Icinga\Exception\AuthenticationException;
|
use Icinga\Exception\AuthenticationException;
|
||||||
use Icinga\Authentication\User\LdapUserBackend;
|
use Icinga\Authentication\User\UserBackend;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Form class for adding/modifying LDAP user backends
|
* Form class for adding/modifying LDAP user backends
|
||||||
@ -48,6 +48,8 @@ class LdapBackendForm extends Form
|
|||||||
*/
|
*/
|
||||||
public function createElements(array $formData)
|
public function createElements(array $formData)
|
||||||
{
|
{
|
||||||
|
$isAd = isset($formData['type']) ? $formData['type'] === 'msldap' : false;
|
||||||
|
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
'text',
|
'text',
|
||||||
'name',
|
'name',
|
||||||
@ -77,10 +79,13 @@ class LdapBackendForm extends Form
|
|||||||
'text',
|
'text',
|
||||||
'user_class',
|
'user_class',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'preserveDefault' => true,
|
||||||
'label' => $this->translate('LDAP User Object Class'),
|
'required' => ! $isAd,
|
||||||
'description' => $this->translate('The object class used for storing users on the LDAP server.'),
|
'ignore' => $isAd,
|
||||||
'value' => 'inetOrgPerson'
|
'disabled' => $isAd ?: null,
|
||||||
|
'label' => $this->translate('LDAP User Object Class'),
|
||||||
|
'description' => $this->translate('The object class used for storing users on the LDAP server.'),
|
||||||
|
'value' => $isAd ? 'user' : 'inetOrgPerson'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -117,12 +122,15 @@ class LdapBackendForm extends Form
|
|||||||
'text',
|
'text',
|
||||||
'user_name_attribute',
|
'user_name_attribute',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'preserveDefault' => true,
|
||||||
'label' => $this->translate('LDAP User Name Attribute'),
|
'required' => ! $isAd,
|
||||||
'description' => $this->translate(
|
'ignore' => $isAd,
|
||||||
|
'disabled' => $isAd ?: null,
|
||||||
|
'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'
|
'value' => $isAd ? 'sAMAccountName' : 'uid'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -130,7 +138,7 @@ class LdapBackendForm extends Form
|
|||||||
'backend',
|
'backend',
|
||||||
array(
|
array(
|
||||||
'disabled' => true,
|
'disabled' => true,
|
||||||
'value' => 'ldap'
|
'value' => $isAd ? 'msldap' : 'ldap'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -170,8 +178,7 @@ class LdapBackendForm extends Form
|
|||||||
public static function isValidUserBackend(Form $form)
|
public static function isValidUserBackend(Form $form)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$ldapUserBackend = new LdapUserBackend(ResourceFactory::createResource($form->getResourceConfig()));
|
$ldapUserBackend = UserBackend::create(null, new ConfigObject($form->getValues()));
|
||||||
$ldapUserBackend->setConfig(new ConfigObject($form->getValues()));
|
|
||||||
$ldapUserBackend->assertAuthenticationPossible();
|
$ldapUserBackend->assertAuthenticationPossible();
|
||||||
} catch (AuthenticationException $e) {
|
} catch (AuthenticationException $e) {
|
||||||
if (($previous = $e->getPrevious()) !== null) {
|
if (($previous = $e->getPrevious()) !== null) {
|
||||||
@ -193,6 +200,8 @@ class LdapBackendForm extends Form
|
|||||||
* Return the configuration for the chosen resource
|
* Return the configuration for the chosen resource
|
||||||
*
|
*
|
||||||
* @return ConfigObject
|
* @return ConfigObject
|
||||||
|
*
|
||||||
|
* @todo Check whether it's possible to drop this (Or even all occurences!)
|
||||||
*/
|
*/
|
||||||
public function getResourceConfig()
|
public function getResourceConfig()
|
||||||
{
|
{
|
||||||
|
@ -60,16 +60,24 @@ class UserBackendConfigForm extends ConfigForm
|
|||||||
*/
|
*/
|
||||||
public function getBackendForm($type)
|
public function getBackendForm($type)
|
||||||
{
|
{
|
||||||
if ($type === 'db') {
|
switch ($type)
|
||||||
$form = new DbBackendForm();
|
{
|
||||||
$form->setResources(isset($this->resources['db']) ? $this->resources['db'] : array());
|
case 'db':
|
||||||
} elseif ($type === 'ldap') {
|
$form = new DbBackendForm();
|
||||||
$form = new LdapBackendForm();
|
$form->setResources(isset($this->resources['db']) ? $this->resources['db'] : array());
|
||||||
$form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array());
|
break;
|
||||||
} elseif ($type === 'external') {
|
case 'ldap':
|
||||||
$form = new ExternalBackendForm();
|
case 'msldap':
|
||||||
} else {
|
$form = new LdapBackendForm();
|
||||||
throw new InvalidArgumentException(sprintf($this->translate('Invalid backend type "%s" provided'), $type));
|
$form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array());
|
||||||
|
break;
|
||||||
|
case 'external':
|
||||||
|
$form = new ExternalBackendForm();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
sprintf($this->translate('Invalid backend type "%s" provided'), $type)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
@ -296,6 +304,7 @@ class UserBackendConfigForm extends ConfigForm
|
|||||||
}
|
}
|
||||||
if (isset($this->resources['ldap']) && ($backendType === 'ldap' || Platform::extensionLoaded('ldap'))) {
|
if (isset($this->resources['ldap']) && ($backendType === 'ldap' || Platform::extensionLoaded('ldap'))) {
|
||||||
$backendTypes['ldap'] = 'LDAP';
|
$backendTypes['ldap'] = 'LDAP';
|
||||||
|
$backendTypes['msldap'] = 'ActiveDirectory';
|
||||||
}
|
}
|
||||||
|
|
||||||
$externalBackends = array_filter(
|
$externalBackends = array_filter(
|
||||||
|
310
application/forms/Config/UserGroup/LdapUserGroupBackendForm.php
Normal file
310
application/forms/Config/UserGroup/LdapUserGroupBackendForm.php
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Forms\Config\UserGroup;
|
||||||
|
|
||||||
|
use Icinga\Application\Config;
|
||||||
|
use Icinga\Authentication\User\UserBackend;
|
||||||
|
use Icinga\Authentication\UserGroup\LdapUserGroupBackend;
|
||||||
|
use Icinga\Data\ConfigObject;
|
||||||
|
use Icinga\Data\ResourceFactory;
|
||||||
|
use Icinga\Protocol\Ldap\Connection;
|
||||||
|
use Icinga\Web\Form;
|
||||||
|
use Icinga\Web\Notification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form for managing LDAP user group backends
|
||||||
|
*/
|
||||||
|
class LdapUserGroupBackendForm extends Form
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initialize this form
|
||||||
|
*/
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
$this->setName('form_config_ldapusergroupbackend');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and add elements to this form
|
||||||
|
*
|
||||||
|
* @param array $formData
|
||||||
|
*/
|
||||||
|
public function createElements(array $formData)
|
||||||
|
{
|
||||||
|
$resourceNames = $this->getLdapResourceNames();
|
||||||
|
$this->addElement(
|
||||||
|
'select',
|
||||||
|
'resource',
|
||||||
|
array(
|
||||||
|
'required' => true,
|
||||||
|
'autosubmit' => true,
|
||||||
|
'label' => $this->translate('LDAP Connection'),
|
||||||
|
'description' => $this->translate('The LDAP connection to use for this backend.'),
|
||||||
|
'multiOptions' => array_combine($resourceNames, $resourceNames)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$resource = ResourceFactory::create(
|
||||||
|
isset($formData['resource']) && in_array($formData['resource'], $resourceNames)
|
||||||
|
? $formData['resource']
|
||||||
|
: $resourceNames[0]
|
||||||
|
);
|
||||||
|
|
||||||
|
$userBackends = array('none' => $this->translate('None', 'usergroupbackend.ldap.user_backend'));
|
||||||
|
$userBackendNames = $this->getLdapUserBackendNames($resource);
|
||||||
|
if (! empty($userBackendNames)) {
|
||||||
|
$userBackends = array_merge($userBackends, array_combine($userBackendNames, $userBackendNames));
|
||||||
|
}
|
||||||
|
$this->addElement(
|
||||||
|
'select',
|
||||||
|
'user_backend',
|
||||||
|
array(
|
||||||
|
'required' => true,
|
||||||
|
'autosubmit' => true,
|
||||||
|
'label' => $this->translate('User Backend'),
|
||||||
|
'description' => $this->translate('The user backend to link with this user group backend.'),
|
||||||
|
'multiOptions' => $userBackends
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$groupBackend = new LdapUserGroupBackend($resource);
|
||||||
|
if ($formData['type'] === 'ldap') {
|
||||||
|
$defaults = $groupBackend->getOpenLdapDefaults();
|
||||||
|
$groupConfigDisabled = $userConfigDisabled = null; // MUST BE null, do NOT change this to false!
|
||||||
|
} else { // $formData['type'] === 'msldap'
|
||||||
|
$defaults = $groupBackend->getActiveDirectoryDefaults();
|
||||||
|
$groupConfigDisabled = $userConfigDisabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dnDisabled = null; // MUST BE null
|
||||||
|
if (isset($formData['user_backend']) && $formData['user_backend'] !== 'none') {
|
||||||
|
$userBackend = UserBackend::create($formData['user_backend']);
|
||||||
|
$defaults->merge(array(
|
||||||
|
'user_base_dn' => $userBackend->getBaseDn(),
|
||||||
|
'user_class' => $userBackend->getUserClass(),
|
||||||
|
'user_name_attribute' => $userBackend->getUserNameAttribute(),
|
||||||
|
'user_filter' => $userBackend->getFilter()
|
||||||
|
));
|
||||||
|
$userConfigDisabled = $dnDisabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->createGroupConfigElements($defaults, $groupConfigDisabled);
|
||||||
|
$this->createUserConfigElements($defaults, $userConfigDisabled, $dnDisabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and add all elements to this form required for the group configuration
|
||||||
|
*
|
||||||
|
* @param ConfigObject $defaults
|
||||||
|
* @param null|bool $disabled
|
||||||
|
*/
|
||||||
|
protected function createGroupConfigElements(ConfigObject $defaults, $disabled)
|
||||||
|
{
|
||||||
|
$this->addElement(
|
||||||
|
'text',
|
||||||
|
'group_class',
|
||||||
|
array(
|
||||||
|
'preserveDefault' => true,
|
||||||
|
'ignore' => $disabled,
|
||||||
|
'disabled' => $disabled,
|
||||||
|
'label' => $this->translate('LDAP Group Object Class'),
|
||||||
|
'description' => $this->translate('The object class used for storing groups on the LDAP server.'),
|
||||||
|
'value' => $defaults->group_class
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->addElement(
|
||||||
|
'text',
|
||||||
|
'group_filter',
|
||||||
|
array(
|
||||||
|
'preserveDefault' => true,
|
||||||
|
'allowEmpty' => true,
|
||||||
|
'label' => $this->translate('LDAP Group Filter'),
|
||||||
|
'description' => $this->translate(
|
||||||
|
'An additional filter to use when looking up groups 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.')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'value' => $defaults->group_filter
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->addElement(
|
||||||
|
'text',
|
||||||
|
'group_name_attribute',
|
||||||
|
array(
|
||||||
|
'preserveDefault' => true,
|
||||||
|
'ignore' => $disabled,
|
||||||
|
'disabled' => $disabled,
|
||||||
|
'label' => $this->translate('LDAP Group Name Attribute'),
|
||||||
|
'description' => $this->translate(
|
||||||
|
'The attribute name used for storing a group\'s name on the LDAP server.'
|
||||||
|
),
|
||||||
|
'value' => $defaults->group_name_attribute
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->addElement(
|
||||||
|
'text',
|
||||||
|
'base_dn',
|
||||||
|
array(
|
||||||
|
'preserveDefault' => true,
|
||||||
|
'label' => $this->translate('LDAP Group Base DN'),
|
||||||
|
'description' => $this->translate(
|
||||||
|
'The path where groups can be found on the LDAP server. Leave ' .
|
||||||
|
'empty to select all users available using the specified connection.'
|
||||||
|
),
|
||||||
|
'value' => $defaults->base_dn
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and add all elements to this form required for the user configuration
|
||||||
|
*
|
||||||
|
* @param ConfigObject $defaults
|
||||||
|
* @param null|bool $disabled
|
||||||
|
* @param null|bool $dnDisabled
|
||||||
|
*/
|
||||||
|
protected function createUserConfigElements(ConfigObject $defaults, $disabled, $dnDisabled)
|
||||||
|
{
|
||||||
|
$this->addElement(
|
||||||
|
'text',
|
||||||
|
'user_class',
|
||||||
|
array(
|
||||||
|
'preserveDefault' => true,
|
||||||
|
'ignore' => $disabled,
|
||||||
|
'disabled' => $disabled,
|
||||||
|
'label' => $this->translate('LDAP User Object Class'),
|
||||||
|
'description' => $this->translate('The object class used for storing users on the LDAP server.'),
|
||||||
|
'value' => $defaults->user_class
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->addElement(
|
||||||
|
'text',
|
||||||
|
'user_filter',
|
||||||
|
array(
|
||||||
|
'preserveDefault' => true,
|
||||||
|
'allowEmpty' => true,
|
||||||
|
'ignore' => $dnDisabled,
|
||||||
|
'disabled' => $dnDisabled,
|
||||||
|
'label' => $this->translate('LDAP User 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.')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'value' => $defaults->user_filter
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->addElement(
|
||||||
|
'text',
|
||||||
|
'user_name_attribute',
|
||||||
|
array(
|
||||||
|
'preserveDefault' => true,
|
||||||
|
'ignore' => $disabled,
|
||||||
|
'disabled' => $disabled,
|
||||||
|
'label' => $this->translate('LDAP User Name Attribute'),
|
||||||
|
'description' => $this->translate(
|
||||||
|
'The attribute name used for storing a user\'s name on the LDAP server.'
|
||||||
|
),
|
||||||
|
'value' => $defaults->user_name_attribute
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->addElement(
|
||||||
|
'text',
|
||||||
|
'user_base_dn',
|
||||||
|
array(
|
||||||
|
'preserveDefault' => true,
|
||||||
|
'ignore' => $dnDisabled,
|
||||||
|
'disabled' => $dnDisabled,
|
||||||
|
'label' => $this->translate('LDAP User Base DN'),
|
||||||
|
'description' => $this->translate(
|
||||||
|
'The path where users can be found on the LDAP server. Leave ' .
|
||||||
|
'empty to select all users available using the specified connection.'
|
||||||
|
),
|
||||||
|
'value' => $defaults->user_base_dn
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the names of all configured LDAP resources
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getLdapResourceNames()
|
||||||
|
{
|
||||||
|
$names = array();
|
||||||
|
foreach (ResourceFactory::getResourceConfigs() as $name => $config) {
|
||||||
|
if (in_array(strtolower($config->type), array('ldap', 'msldap'))) {
|
||||||
|
$names[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($names)) {
|
||||||
|
Notification::error(
|
||||||
|
$this->translate('No LDAP resources available. Please configure an LDAP resource first.')
|
||||||
|
);
|
||||||
|
$this->getResponse()->redirectAndExit('config/createresource');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $names;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the names of all configured LDAP user backends
|
||||||
|
*
|
||||||
|
* @param Connection $resource
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getLdapUserBackendNames(Connection $resource)
|
||||||
|
{
|
||||||
|
$names = array();
|
||||||
|
foreach (Config::app('authentication') as $name => $config) {
|
||||||
|
if (in_array(strtolower($config->backend), array('ldap', 'msldap'))) {
|
||||||
|
$backendResource = ResourceFactory::create($config->resource);
|
||||||
|
if (
|
||||||
|
$backendResource->getHostname() === $resource->getHostname()
|
||||||
|
&& $backendResource->getPort() === $resource->getPort()
|
||||||
|
) {
|
||||||
|
$names[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $names;
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,13 @@ use Icinga\Forms\ConfigForm;
|
|||||||
*/
|
*/
|
||||||
class UserGroupBackendForm extends ConfigForm
|
class UserGroupBackendForm extends ConfigForm
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The backend to load when displaying the form for the first time
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $backendToLoad;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize this form
|
* Initialize this form
|
||||||
*/
|
*/
|
||||||
@ -31,10 +38,17 @@ class UserGroupBackendForm extends ConfigForm
|
|||||||
*/
|
*/
|
||||||
public function getBackendForm($type)
|
public function getBackendForm($type)
|
||||||
{
|
{
|
||||||
if ($type === 'db') {
|
switch ($type)
|
||||||
return new DbUserGroupBackendForm();
|
{
|
||||||
} else {
|
case 'db':
|
||||||
throw new InvalidArgumentException(sprintf($this->translate('Invalid backend type "%s" provided'), $type));
|
return new DbUserGroupBackendForm();
|
||||||
|
case 'ldap':
|
||||||
|
case 'msldap':
|
||||||
|
return new LdapUserGroupBackendForm();
|
||||||
|
default:
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
sprintf($this->translate('Invalid backend type "%s" provided'), $type)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,10 +67,7 @@ class UserGroupBackendForm extends ConfigForm
|
|||||||
throw new NotFoundError('No user group backend called "%s" found', $name);
|
throw new NotFoundError('No user group backend called "%s" found', $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $this->config->getSection($name)->toArray();
|
$this->backendToLoad = $name;
|
||||||
$data['type'] = $data['backend'];
|
|
||||||
$data['name'] = $name;
|
|
||||||
$this->populate($data);
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,13 +114,23 @@ class UserGroupBackendForm extends ConfigForm
|
|||||||
}
|
}
|
||||||
|
|
||||||
$backendConfig = $this->config->getSection($name);
|
$backendConfig = $this->config->getSection($name);
|
||||||
if (isset($data['name']) && $data['name'] !== $name) {
|
if (isset($data['name'])) {
|
||||||
$this->config->removeSection($name);
|
if ($data['name'] !== $name) {
|
||||||
$name = $data['name'];
|
$this->config->removeSection($name);
|
||||||
|
$name = $data['name'];
|
||||||
|
}
|
||||||
|
|
||||||
unset($data['name']);
|
unset($data['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->config->setSection($name, $backendConfig->merge($data));
|
$backendConfig->merge($data);
|
||||||
|
foreach ($backendConfig->toArray() as $k => $v) {
|
||||||
|
if ($v === null) {
|
||||||
|
unset($backendConfig->$k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->config->setSection($name, $backendConfig);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +182,9 @@ class UserGroupBackendForm extends ConfigForm
|
|||||||
|
|
||||||
// TODO(jom): We did not think about how to configure custom group backends yet!
|
// TODO(jom): We did not think about how to configure custom group backends yet!
|
||||||
$backendTypes = array(
|
$backendTypes = array(
|
||||||
'db' => $this->translate('Database')
|
'db' => $this->translate('Database'),
|
||||||
|
'ldap' => 'LDAP',
|
||||||
|
'msldap' => 'ActiveDirectory'
|
||||||
);
|
);
|
||||||
|
|
||||||
$backendType = isset($formData['type']) ? $formData['type'] : null;
|
$backendType = isset($formData['type']) ? $formData['type'] : null;
|
||||||
@ -191,8 +214,34 @@ class UserGroupBackendForm extends ConfigForm
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$backendForm = $this->getBackendForm($backendType);
|
$this->addSubForm($this->getBackendForm($backendType)->create($formData), 'backend_form');
|
||||||
$backendForm->createElements($formData);
|
}
|
||||||
$this->addElements($backendForm->getElements());
|
|
||||||
|
/**
|
||||||
|
* Populate the configuration of the backend to load
|
||||||
|
*/
|
||||||
|
public function onRequest()
|
||||||
|
{
|
||||||
|
if ($this->backendToLoad) {
|
||||||
|
$data = $this->config->getSection($this->backendToLoad)->toArray();
|
||||||
|
$data['type'] = $data['backend'];
|
||||||
|
$data['name'] = $this->backendToLoad;
|
||||||
|
$this->populate($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all form element values
|
||||||
|
*
|
||||||
|
* @param bool $suppressArrayNotation Ignored
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getValues($suppressArrayNotation = false)
|
||||||
|
{
|
||||||
|
$values = parent::getValues();
|
||||||
|
$values = array_merge($values, $values['backend_form']);
|
||||||
|
unset($values['backend_form']);
|
||||||
|
return $values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
application/views/scripts/about/index.phtml
Normal file
25
application/views/scripts/about/index.phtml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<div class="content">
|
||||||
|
<h1>Icinga Web 2</h1>
|
||||||
|
<?php
|
||||||
|
$versionInfo = array();
|
||||||
|
if ($version !== false) {
|
||||||
|
foreach (array(
|
||||||
|
'appVersion' => $this->translate('Version: %s'),
|
||||||
|
'gitCommitID' => $this->translate('Git commit ID: %s'),
|
||||||
|
'gitCommitDate' => $this->translate('Git commit date: %s')
|
||||||
|
) as $key => $label) {
|
||||||
|
if (array_key_exists($key, $version) && null !== ($value = $version[$key])) {
|
||||||
|
$versionInfo[] = sprintf($label, htmlspecialchars($value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo (
|
||||||
|
0 === count($versionInfo)
|
||||||
|
? '<p class="message-error">' . $this->translate(
|
||||||
|
'Can\'t determine Icinga Web 2\'s version'
|
||||||
|
)
|
||||||
|
: '<p>' . nl2br(implode("\n", $versionInfo), false)
|
||||||
|
) . '</p>';
|
||||||
|
?>
|
||||||
|
</div>
|
@ -18,7 +18,7 @@ if (! $this->compact): ?>
|
|||||||
<div class="content groups">
|
<div class="content groups">
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
if ($backend === null) {
|
if (! isset($backend)) {
|
||||||
echo $this->translate('No backend found which is able to list groups') . '</div>';
|
echo $this->translate('No backend found which is able to list groups') . '</div>';
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<a data-base-target="_next" href="<?= $this->href('role/new') ?>">
|
<a data-base-target="_next" href="<?= $this->href('role/add') ?>">
|
||||||
<?= $this->translate('Create a New Role') ?>
|
<?= $this->translate('Create a New Role') ?>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,7 @@ if (! $this->compact): ?>
|
|||||||
<div class="content users">
|
<div class="content users">
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
if ($backend === null) {
|
if (! isset($backend)) {
|
||||||
echo $this->translate('No backend found which is able to list users') . '</div>';
|
echo $this->translate('No backend found which is able to list users') . '</div>';
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,6 +218,7 @@ rm -rf %{buildroot}
|
|||||||
%{basedir}/application/forms
|
%{basedir}/application/forms
|
||||||
%{basedir}/application/layouts
|
%{basedir}/application/layouts
|
||||||
%{basedir}/application/views
|
%{basedir}/application/views
|
||||||
|
%{basedir}/application/VERSION
|
||||||
%{basedir}/doc
|
%{basedir}/doc
|
||||||
%{basedir}/modules
|
%{basedir}/modules
|
||||||
%{basedir}/public
|
%{basedir}/public
|
||||||
|
@ -59,6 +59,122 @@ class Platform
|
|||||||
return strtoupper(substr(self::getOperatingSystemName(), 0, 5)) === 'LINUX';
|
return strtoupper(substr(self::getOperatingSystemName(), 0, 5)) === 'LINUX';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Linux distribution's name
|
||||||
|
* or 'linux' if the name could not be found out
|
||||||
|
* or false if the OS isn't Linux or an error occurred
|
||||||
|
*
|
||||||
|
* @param int $reliable
|
||||||
|
* 3: Only parse /etc/os-release (or /usr/lib/os-release).
|
||||||
|
* For the paranoid ones.
|
||||||
|
* 2: If that (3) doesn't help, check /etc/*-release, too.
|
||||||
|
* If something is unclear, return 'linux'.
|
||||||
|
* 1: Almost equal to mode 2. The possible return values also include:
|
||||||
|
* 'redhat' -- unclear whether RHEL/Fedora/...
|
||||||
|
* 'suse' -- unclear whether SLES/openSUSE/...
|
||||||
|
* 0: If even that (1) doesn't help, check /proc/version, too.
|
||||||
|
* This may not work (as expected) on LXC containers!
|
||||||
|
* (No reliability at all!)
|
||||||
|
*
|
||||||
|
* @return string|bool
|
||||||
|
*/
|
||||||
|
public static function getLinuxDistro($reliable = 2)
|
||||||
|
{
|
||||||
|
if (! self::isLinux()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array('/etc/os-release', '/usr/lib/os-release') as $osReleaseFile) {
|
||||||
|
if (false === ($osRelease = @file(
|
||||||
|
$osReleaseFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
|
||||||
|
))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($osRelease as $osInfo) {
|
||||||
|
if (false === ($res = @preg_match('/(?<!.)[ \t]*#/ms', $osInfo))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($res === 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$matches = array();
|
||||||
|
if (false === ($res = @preg_match(
|
||||||
|
'/(?<!.)[ \t]*ID[ \t]*=[ \t]*(\'|"|)(.*?)(?:\1)[ \t]*(?!.)/msi',
|
||||||
|
$osInfo,
|
||||||
|
$matches
|
||||||
|
))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (! ($res === 0 || $matches[2] === '' || $matches[2] === 'linux')) {
|
||||||
|
return $matches[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($reliable > 2) {
|
||||||
|
return 'linux';
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array(
|
||||||
|
'fedora' => '/etc/fedora-release',
|
||||||
|
'centos' => '/etc/centos-release'
|
||||||
|
) as $distro => $releaseFile) {
|
||||||
|
if (! (false === (
|
||||||
|
$release = @file_get_contents($releaseFile)
|
||||||
|
) || false === strpos(strtolower($release), $distro))) {
|
||||||
|
return $distro;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false !== ($release = @file_get_contents('/etc/redhat-release'))) {
|
||||||
|
$release = strtolower($release);
|
||||||
|
if (false !== strpos($release, 'red hat enterprise linux')) {
|
||||||
|
return 'rhel';
|
||||||
|
}
|
||||||
|
foreach (array('fedora', 'centos') as $distro) {
|
||||||
|
if (false !== strpos($release, $distro)) {
|
||||||
|
return $distro;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $reliable < 2 ? 'redhat' : 'linux';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false !== ($release = @file_get_contents('/etc/SuSE-release'))) {
|
||||||
|
$release = strtolower($release);
|
||||||
|
foreach (array(
|
||||||
|
'opensuse' => 'opensuse',
|
||||||
|
'sles' => 'suse linux enterprise server',
|
||||||
|
'sled' => 'suse linux enterprise desktop'
|
||||||
|
) as $distro => $name) {
|
||||||
|
if (false !== strpos($release, $name)) {
|
||||||
|
return $distro;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $reliable < 2 ? 'suse' : 'linux';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($reliable < 1) {
|
||||||
|
if (false === ($procVersion = @file_get_contents('/proc/version'))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$procVersion = strtolower($procVersion);
|
||||||
|
foreach (array(
|
||||||
|
'redhat' => 'red hat',
|
||||||
|
'suse' => 'suse linux',
|
||||||
|
'ubuntu' => 'ubuntu',
|
||||||
|
'debian' => 'debian'
|
||||||
|
) as $distro => $name) {
|
||||||
|
if (false !== strpos($procVersion, $name)) {
|
||||||
|
return $distro;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'linux';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of CLI environment
|
* Test of CLI environment
|
||||||
*
|
*
|
||||||
|
37
library/Icinga/Application/Version.php
Normal file
37
library/Icinga/Application/Version.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Application;
|
||||||
|
|
||||||
|
class Version
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the version of this instance of Icinga Web 2
|
||||||
|
*
|
||||||
|
* @return array|bool array on success, false otherwise
|
||||||
|
*/
|
||||||
|
public static function get()
|
||||||
|
{
|
||||||
|
if (false === ($appVersion = @file_get_contents(
|
||||||
|
Icinga::app()->getApplicationDir() . DIRECTORY_SEPARATOR . 'VERSION'
|
||||||
|
))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$matches = array();
|
||||||
|
if (false === ($res = preg_match(
|
||||||
|
'/(?<!.)\s*(?P<gitCommitID>\w+)(?:\s*\(.*?(?:(?<=[\(,])\s*tag\s*:\s*v(?P<appVersion>.+?)\s*(?=[\),]).*?)?\))?\s*(?P<gitCommitDate>\S+)/ms',
|
||||||
|
$appVersion,
|
||||||
|
$matches
|
||||||
|
)) || $res === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($matches as $key => $value) {
|
||||||
|
if (is_int($key) || $value === '') {
|
||||||
|
unset($matches[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $matches;
|
||||||
|
}
|
||||||
|
}
|
@ -4,17 +4,16 @@
|
|||||||
namespace Icinga\Authentication\User;
|
namespace Icinga\Authentication\User;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use Icinga\Application\Logger;
|
|
||||||
use Icinga\Data\ConfigObject;
|
use Icinga\Data\ConfigObject;
|
||||||
use Icinga\Exception\AuthenticationException;
|
use Icinga\Exception\AuthenticationException;
|
||||||
use Icinga\Exception\ProgrammingError;
|
use Icinga\Exception\ProgrammingError;
|
||||||
use Icinga\Repository\Repository;
|
use Icinga\Repository\LdapRepository;
|
||||||
use Icinga\Repository\RepositoryQuery;
|
use Icinga\Repository\RepositoryQuery;
|
||||||
use Icinga\Protocol\Ldap\Exception as LdapException;
|
use Icinga\Protocol\Ldap\Exception as LdapException;
|
||||||
use Icinga\Protocol\Ldap\Expression;
|
use Icinga\Protocol\Ldap\Expression;
|
||||||
use Icinga\User;
|
use Icinga\User;
|
||||||
|
|
||||||
class LdapUserBackend extends Repository implements UserBackendInterface
|
class LdapUserBackend extends LdapRepository implements UserBackendInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The base DN to use for a query
|
* The base DN to use for a query
|
||||||
@ -65,20 +64,6 @@ class LdapUserBackend extends Repository implements UserBackendInterface
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
protected $groupOptions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normed attribute names based on known LDAP environments
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $normedAttributes = array(
|
|
||||||
'uid' => 'uid',
|
|
||||||
'user' => 'user',
|
|
||||||
'inetorgperson' => 'inetOrgPerson',
|
|
||||||
'samaccountname' => 'sAMAccountName'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the base DN to use for a query
|
* Set the base DN to use for a query
|
||||||
*
|
*
|
||||||
@ -179,34 +164,6 @@ class LdapUserBackend extends Repository implements UserBackendInterface
|
|||||||
return $this->filter;
|
return $this->filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setGroupOptions(array $options)
|
|
||||||
{
|
|
||||||
$this->groupOptions = $options;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGroupOptions()
|
|
||||||
{
|
|
||||||
return $this->groupOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the given attribute name normed to known LDAP enviroments, if possible
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function getNormedAttribute($name)
|
|
||||||
{
|
|
||||||
$loweredName = strtolower($name);
|
|
||||||
if (array_key_exists($loweredName, $this->normedAttributes)) {
|
|
||||||
return $this->normedAttributes[$loweredName];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the given configuration to this backend
|
* Apply the given configuration to this backend
|
||||||
*
|
*
|
||||||
@ -325,37 +282,6 @@ class LdapUserBackend extends Repository implements UserBackendInterface
|
|||||||
return ((int) $value & $ADS_UF_ACCOUNTDISABLE) === 0;
|
return ((int) $value & $ADS_UF_ACCOUNTDISABLE) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the given value based on the ASN.1 standard (GeneralizedTime) and return its timestamp representation
|
|
||||||
*
|
|
||||||
* @param string|null $value
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
protected function retrieveGeneralizedTime($value)
|
|
||||||
{
|
|
||||||
if ($value === null) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
($dateTime = DateTime::createFromFormat('YmdHis.uO', $value)) !== false
|
|
||||||
|| ($dateTime = DateTime::createFromFormat('YmdHis.uZ', $value)) !== false
|
|
||||||
|| ($dateTime = DateTime::createFromFormat('YmdHis.u', $value)) !== false
|
|
||||||
|| ($dateTime = DateTime::createFromFormat('YmdHis', $value)) !== false
|
|
||||||
|| ($dateTime = DateTime::createFromFormat('YmdHi', $value)) !== false
|
|
||||||
|| ($dateTime = DateTime::createFromFormat('YmdH', $value)) !== false
|
|
||||||
) {
|
|
||||||
return $dateTime->getTimeStamp();
|
|
||||||
} else {
|
|
||||||
Logger::debug(sprintf(
|
|
||||||
'Failed to parse "%s" based on the ASN.1 standard (GeneralizedTime) for user backend "%s".',
|
|
||||||
$value,
|
|
||||||
$this->getName()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether the given shadowExpire value defines that a user is permitted to login
|
* Return whether the given shadowExpire value defines that a user is permitted to login
|
||||||
*
|
*
|
||||||
@ -413,41 +339,6 @@ class LdapUserBackend extends Repository implements UserBackendInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the user groups
|
|
||||||
*
|
|
||||||
* @TODO: Subject to change, see #7343
|
|
||||||
*
|
|
||||||
* @param string $dn
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getGroups($dn)
|
|
||||||
{
|
|
||||||
if (empty($this->groupOptions) || ! isset($this->groupOptions['group_base_dn'])) {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->ds->select()
|
|
||||||
->setBase($this->groupOptions['group_base_dn'])
|
|
||||||
->from(
|
|
||||||
$this->groupOptions['group_class'],
|
|
||||||
array($this->groupOptions['group_attribute'])
|
|
||||||
)
|
|
||||||
->where(
|
|
||||||
$this->groupOptions['group_member_attribute'],
|
|
||||||
$dn
|
|
||||||
)
|
|
||||||
->fetchAll();
|
|
||||||
|
|
||||||
$groups = array();
|
|
||||||
foreach ($result as $group) {
|
|
||||||
$groups[] = $group->{$this->groupOptions['group_attribute']};
|
|
||||||
}
|
|
||||||
|
|
||||||
return $groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticate the given user
|
* Authenticate the given user
|
||||||
*
|
*
|
||||||
@ -472,15 +363,7 @@ class LdapUserBackend extends Repository implements UserBackendInterface
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$authenticated = $this->ds->testCredentials($userDn, $password);
|
return $this->ds->testCredentials($userDn, $password);
|
||||||
if ($authenticated) {
|
|
||||||
$groups = $this->getGroups($userDn);
|
|
||||||
if ($groups !== null) {
|
|
||||||
$user->setGroups($groups);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $authenticated;
|
|
||||||
} catch (LdapException $e) {
|
} catch (LdapException $e) {
|
||||||
throw new AuthenticationException(
|
throw new AuthenticationException(
|
||||||
'Failed to authenticate user "%s" against backend "%s". An exception was thrown:',
|
'Failed to authenticate user "%s" against backend "%s". An exception was thrown:',
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
namespace Icinga\Authentication\User;
|
namespace Icinga\Authentication\User;
|
||||||
|
|
||||||
|
use Icinga\Application\Config;
|
||||||
use Icinga\Application\Logger;
|
use Icinga\Application\Logger;
|
||||||
use Icinga\Application\Icinga;
|
use Icinga\Application\Icinga;
|
||||||
use Icinga\Data\ConfigObject;
|
use Icinga\Data\ConfigObject;
|
||||||
@ -106,8 +107,17 @@ class UserBackend
|
|||||||
*
|
*
|
||||||
* @throws ConfigurationError
|
* @throws ConfigurationError
|
||||||
*/
|
*/
|
||||||
public static function create($name, ConfigObject $backendConfig)
|
public static function create($name, ConfigObject $backendConfig = null)
|
||||||
{
|
{
|
||||||
|
if ($backendConfig === null) {
|
||||||
|
$authConfig = Config::app('authentication');
|
||||||
|
if ($authConfig->hasSection($name)) {
|
||||||
|
$backendConfig = $authConfig->getSection($name);
|
||||||
|
} else {
|
||||||
|
throw new ConfigurationError('User backend "%s" does not exist', $name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($backendConfig->name !== null) {
|
if ($backendConfig->name !== null) {
|
||||||
$name = $backendConfig->name;
|
$name = $backendConfig->name;
|
||||||
}
|
}
|
||||||
@ -165,12 +175,6 @@ class UserBackend
|
|||||||
$backend->setUserClass($backendConfig->get('user_class', 'user'));
|
$backend->setUserClass($backendConfig->get('user_class', 'user'));
|
||||||
$backend->setUserNameAttribute($backendConfig->get('user_name_attribute', 'sAMAccountName'));
|
$backend->setUserNameAttribute($backendConfig->get('user_name_attribute', 'sAMAccountName'));
|
||||||
$backend->setFilter($backendConfig->filter);
|
$backend->setFilter($backendConfig->filter);
|
||||||
$backend->setGroupOptions(array(
|
|
||||||
'group_base_dn' => $backendConfig->get('group_base_dn', $resource->getDN()),
|
|
||||||
'group_attribute' => $backendConfig->get('group_attribute', 'sAMAccountName'),
|
|
||||||
'group_member_attribute' => $backendConfig->get('group_member_attribute', 'member'),
|
|
||||||
'group_class' => $backendConfig->get('group_class', 'group')
|
|
||||||
));
|
|
||||||
break;
|
break;
|
||||||
case 'ldap':
|
case 'ldap':
|
||||||
$backend = new LdapUserBackend($resource);
|
$backend = new LdapUserBackend($resource);
|
||||||
@ -178,12 +182,6 @@ class UserBackend
|
|||||||
$backend->setUserClass($backendConfig->get('user_class', 'inetOrgPerson'));
|
$backend->setUserClass($backendConfig->get('user_class', 'inetOrgPerson'));
|
||||||
$backend->setUserNameAttribute($backendConfig->get('user_name_attribute', 'uid'));
|
$backend->setUserNameAttribute($backendConfig->get('user_name_attribute', 'uid'));
|
||||||
$backend->setFilter($backendConfig->filter);
|
$backend->setFilter($backendConfig->filter);
|
||||||
$backend->setGroupOptions(array(
|
|
||||||
'group_base_dn' => $backendConfig->group_base_dn,
|
|
||||||
'group_attribute' => $backendConfig->group_attribute,
|
|
||||||
'group_member_attribute' => $backendConfig->group_member_attribute,
|
|
||||||
'group_class' => $backendConfig->group_class
|
|
||||||
));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
627
library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php
Normal file
627
library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php
Normal file
@ -0,0 +1,627 @@
|
|||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Authentication\UserGroup;
|
||||||
|
|
||||||
|
use Icinga\Authentication\User\UserBackend;
|
||||||
|
use Icinga\Authentication\User\LdapUserBackend;
|
||||||
|
use Icinga\Data\ConfigObject;
|
||||||
|
use Icinga\Exception\ConfigurationError;
|
||||||
|
use Icinga\Exception\ProgrammingError;
|
||||||
|
use Icinga\Protocol\Ldap\Expression;
|
||||||
|
use Icinga\Repository\LdapRepository;
|
||||||
|
use Icinga\Repository\RepositoryQuery;
|
||||||
|
use Icinga\User;
|
||||||
|
|
||||||
|
class LdapUserGroupBackend /*extends LdapRepository*/ implements UserGroupBackendInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The base DN to use for a user query
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $userBaseDn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base DN to use for a group query
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $groupBaseDn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The objectClass where look for users
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $userClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The objectClass where look for groups
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $groupClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attribute name where to find a user's name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $userNameAttribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attribute name where to find a group's name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $groupNameAttribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attribute name where to find a group's member
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $groupMemberAttribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The custom LDAP filter to apply on a user query
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $userFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The custom LDAP filter to apply on a group query
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $groupFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The columns which are not permitted to be queried
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $filterColumns = array('group', 'user');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default sort rules to be applied on a query
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $sortRules = array(
|
||||||
|
'group_name' => array(
|
||||||
|
'order' => 'asc'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normed attribute names based on known LDAP environments
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $normedAttributes = array(
|
||||||
|
'uid' => 'uid',
|
||||||
|
'gid' => 'gid',
|
||||||
|
'user' => 'user',
|
||||||
|
'group' => 'group',
|
||||||
|
'member' => 'member',
|
||||||
|
'inetorgperson' => 'inetOrgPerson',
|
||||||
|
'samaccountname' => 'sAMAccountName'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this repository
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The datasource being used
|
||||||
|
*
|
||||||
|
* @var Connection
|
||||||
|
*/
|
||||||
|
protected $ds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new LDAP repository object
|
||||||
|
*
|
||||||
|
* @param Connection $ds The data source to use
|
||||||
|
*/
|
||||||
|
public function __construct($ds)
|
||||||
|
{
|
||||||
|
$this->ds = $ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the given attribute name normed to known LDAP enviroments, if possible
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getNormedAttribute($name)
|
||||||
|
{
|
||||||
|
$loweredName = strtolower($name);
|
||||||
|
if (array_key_exists($loweredName, $this->normedAttributes)) {
|
||||||
|
return $this->normedAttributes[$loweredName];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this repository's name
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return this repository's name
|
||||||
|
*
|
||||||
|
* In case no name has been explicitly set yet, the class name is returned.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the base DN to use for a user query
|
||||||
|
*
|
||||||
|
* @param string $baseDn
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setUserBaseDn($baseDn)
|
||||||
|
{
|
||||||
|
if (($baseDn = trim($baseDn))) {
|
||||||
|
$this->userBaseDn = $baseDn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the base DN to use for a user query
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUserBaseDn()
|
||||||
|
{
|
||||||
|
return $this->userBaseDn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the base DN to use for a group query
|
||||||
|
*
|
||||||
|
* @param string $baseDn
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setGroupBaseDn($baseDn)
|
||||||
|
{
|
||||||
|
if (($baseDn = trim($baseDn))) {
|
||||||
|
$this->groupBaseDn = $baseDn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the base DN to use for a group query
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getGroupBaseDn()
|
||||||
|
{
|
||||||
|
return $this->groupBaseDn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the objectClass where to look for users
|
||||||
|
*
|
||||||
|
* @param string $userClass
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setUserClass($userClass)
|
||||||
|
{
|
||||||
|
$this->userClass = $this->getNormedAttribute($userClass);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the objectClass where to look for users
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUserClass()
|
||||||
|
{
|
||||||
|
return $this->userClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the objectClass where to look for groups
|
||||||
|
*
|
||||||
|
* Sets also the base table name for the underlying repository.
|
||||||
|
*
|
||||||
|
* @param string $groupClass
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setGroupClass($groupClass)
|
||||||
|
{
|
||||||
|
$this->baseTable = $this->groupClass = $this->getNormedAttribute($groupClass);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the objectClass where to look for groups
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getGroupClass()
|
||||||
|
{
|
||||||
|
return $this->groupClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the attribute name where to find a user's name
|
||||||
|
*
|
||||||
|
* @param string $userNameAttribute
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setUserNameAttribute($userNameAttribute)
|
||||||
|
{
|
||||||
|
$this->userNameAttribute = $this->getNormedAttribute($userNameAttribute);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the attribute name where to find a user's name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUserNameAttribute()
|
||||||
|
{
|
||||||
|
return $this->userNameAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the attribute name where to find a group's name
|
||||||
|
*
|
||||||
|
* @param string $groupNameAttribute
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setGroupNameAttribute($groupNameAttribute)
|
||||||
|
{
|
||||||
|
$this->groupNameAttribute = $this->getNormedAttribute($groupNameAttribute);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the attribute name where to find a group's name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getGroupNameAttribute()
|
||||||
|
{
|
||||||
|
return $this->groupNameAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the attribute name where to find a group's member
|
||||||
|
*
|
||||||
|
* @param string $groupMemberAttribute
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setGroupMemberAttribute($groupMemberAttribute)
|
||||||
|
{
|
||||||
|
$this->groupMemberAttribute = $this->getNormedAttribute($groupMemberAttribute);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the attribute name where to find a group's member
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getGroupMemberAttribute()
|
||||||
|
{
|
||||||
|
return $this->groupMemberAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the custom LDAP filter to apply on a user query
|
||||||
|
*
|
||||||
|
* @param string $filter
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setUserFilter($filter)
|
||||||
|
{
|
||||||
|
if (($filter = trim($filter))) {
|
||||||
|
$this->userFilter = $filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the custom LDAP filter to apply on a user query
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUserFilter()
|
||||||
|
{
|
||||||
|
return $this->userFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the custom LDAP filter to apply on a group query
|
||||||
|
*
|
||||||
|
* @param string $filter
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setGroupFilter($filter)
|
||||||
|
{
|
||||||
|
if (($filter = trim($filter))) {
|
||||||
|
$this->groupFilter = $filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the custom LDAP filter to apply on a group query
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getGroupFilter()
|
||||||
|
{
|
||||||
|
return $this->groupFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new query for the given columns
|
||||||
|
*
|
||||||
|
* @param array $columns The desired columns, if null all columns will be queried
|
||||||
|
*
|
||||||
|
* @return RepositoryQuery
|
||||||
|
*/
|
||||||
|
public function select(array $columns = null)
|
||||||
|
{
|
||||||
|
$query = parent::select($columns);
|
||||||
|
$query->getQuery()->setBase($this->groupBaseDn);
|
||||||
|
if ($this->groupFilter) {
|
||||||
|
// TODO(jom): This should differentiate between groups and their memberships
|
||||||
|
$query->getQuery()->where(new Expression($this->groupFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize this repository's query columns
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @throws ProgrammingError In case either $this->groupNameAttribute or $this->groupClass has not been set yet
|
||||||
|
*/
|
||||||
|
protected function initializeQueryColumns()
|
||||||
|
{
|
||||||
|
if ($this->groupClass === null) {
|
||||||
|
throw new ProgrammingError('It is required to set the objectClass where to look for groups first');
|
||||||
|
}
|
||||||
|
if ($this->groupNameAttribute === null) {
|
||||||
|
throw new ProgrammingError('It is required to set a attribute name where to find a group\'s name first');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->ds->getCapabilities()->hasAdOid()) {
|
||||||
|
$createdAtAttribute = 'whenCreated';
|
||||||
|
$lastModifiedAttribute = 'whenChanged';
|
||||||
|
} else {
|
||||||
|
$createdAtAttribute = 'createTimestamp';
|
||||||
|
$lastModifiedAttribute = 'modifyTimestamp';
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jom): Fetching memberships does not work currently, we'll need some aggregate functionality!
|
||||||
|
$columns = array(
|
||||||
|
'group' => $this->groupNameAttribute,
|
||||||
|
'group_name' => $this->groupNameAttribute,
|
||||||
|
'user' => $this->groupMemberAttribute,
|
||||||
|
'user_name' => $this->groupMemberAttribute,
|
||||||
|
'created_at' => $createdAtAttribute,
|
||||||
|
'last_modified' => $lastModifiedAttribute
|
||||||
|
);
|
||||||
|
return array('group' => $columns, 'group_membership' => $columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize this repository's conversion rules
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @throws ProgrammingError In case $this->groupClass has not been set yet
|
||||||
|
*/
|
||||||
|
protected function initializeConversionRules()
|
||||||
|
{
|
||||||
|
if ($this->groupClass === null) {
|
||||||
|
throw new ProgrammingError('It is required to set the objectClass where to look for groups first');
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$this->groupClass => array(
|
||||||
|
'created_at' => 'generalized_time',
|
||||||
|
'last_modified' => 'generalized_time'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that the requested table exists
|
||||||
|
*
|
||||||
|
* This will return $this->groupClass in case $table equals "group" or "group_membership".
|
||||||
|
*
|
||||||
|
* @param string $table The table to validate
|
||||||
|
* @param RepositoryQuery $query An optional query to pass as context
|
||||||
|
* (unused by the base implementation)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @throws ProgrammingError In case the given table does not exist
|
||||||
|
*/
|
||||||
|
public function requireTable($table, RepositoryQuery $query = null)
|
||||||
|
{
|
||||||
|
$table = parent::requireTable($table, $query);
|
||||||
|
if ($table === 'group' || $table === 'group_membership') {
|
||||||
|
$table = $this->groupClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the groups the given user is a member of
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getMemberships(User $user)
|
||||||
|
{
|
||||||
|
$userQuery = $this->ds
|
||||||
|
->select()
|
||||||
|
->from($this->userClass)
|
||||||
|
->where($this->userNameAttribute, $user->getUsername())
|
||||||
|
->setBase($this->userBaseDn)
|
||||||
|
->setUsePagedResults(false);
|
||||||
|
if ($this->userFilter) {
|
||||||
|
$userQuery->where(new Expression($this->userFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($userDn = $userQuery->fetchDn()) === null) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$groupQuery = $this->ds
|
||||||
|
->select()
|
||||||
|
->from($this->groupClass, array($this->groupNameAttribute))
|
||||||
|
->where($this->groupMemberAttribute, $userDn)
|
||||||
|
->setBase($this->groupBaseDn);
|
||||||
|
if ($this->groupFilter) {
|
||||||
|
$groupQuery->where(new Expression($this->groupFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
$groups = array();
|
||||||
|
foreach ($groupQuery as $row) {
|
||||||
|
$groups[] = $row->{$this->groupNameAttribute};
|
||||||
|
}
|
||||||
|
|
||||||
|
return $groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the given configuration on this backend
|
||||||
|
*
|
||||||
|
* @param ConfigObject $config
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws ConfigurationError In case a linked user backend does not exist or is invalid
|
||||||
|
*/
|
||||||
|
public function setConfig(ConfigObject $config)
|
||||||
|
{
|
||||||
|
if ($config->backend === 'ldap') {
|
||||||
|
$defaults = $this->getOpenLdapDefaults();
|
||||||
|
} elseif ($config->backend === 'msldap') {
|
||||||
|
$defaults = $this->getActiveDirectoryDefaults();
|
||||||
|
} else {
|
||||||
|
$defaults = new ConfigObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($config->user_backend && $config->user_backend !== 'none') {
|
||||||
|
$userBackend = UserBackend::create($config->user_backend);
|
||||||
|
if (! $userBackend instanceof LdapUserBackend) {
|
||||||
|
throw new ConfigurationError('User backend "%s" is not of type LDAP', $config->user_backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
$this->ds->getHostname() !== $userBackend->getDataSource()->getHostname()
|
||||||
|
|| $this->ds->getPort() !== $userBackend->getDataSource()->getPort()
|
||||||
|
) {
|
||||||
|
// TODO(jom): Elaborate whether it makes sense to link directories on different hosts
|
||||||
|
throw new ConfigurationError(
|
||||||
|
'It is required that a linked user backend refers to the '
|
||||||
|
. 'same directory as it\'s user group backend counterpart'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$defaults->merge(array(
|
||||||
|
'user_base_dn' => $userBackend->getBaseDn(),
|
||||||
|
'user_class' => $userBackend->getUserClass(),
|
||||||
|
'user_name_attribute' => $userBackend->getUserNameAttribute(),
|
||||||
|
'user_filter' => $userBackend->getFilter()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this
|
||||||
|
->setGroupBaseDn($config->base_dn)
|
||||||
|
->setUserBaseDn($config->get('user_base_dn', $this->getGroupBaseDn()))
|
||||||
|
->setGroupClass($config->get('group_class', $defaults->group_class))
|
||||||
|
->setUserClass($config->get('user_class', $defaults->user_class))
|
||||||
|
->setGroupNameAttribute($config->get('group_name_attribute', $defaults->group_name_attribute))
|
||||||
|
->setUserNameAttribute($config->get('user_name_attribute', $defaults->user_name_attribute))
|
||||||
|
->setGroupMemberAttribute($config->get('group_member_attribute', $defaults->group_member_attribute))
|
||||||
|
->setGroupFilter($config->filter)
|
||||||
|
->setUserFilter($config->user_filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the configuration defaults for an OpenLDAP environment
|
||||||
|
*
|
||||||
|
* @return ConfigObject
|
||||||
|
*/
|
||||||
|
public function getOpenLdapDefaults()
|
||||||
|
{
|
||||||
|
return new ConfigObject(array(
|
||||||
|
'group_class' => 'group',
|
||||||
|
'user_class' => 'inetOrgPerson',
|
||||||
|
'group_name_attribute' => 'gid',
|
||||||
|
'user_name_attribute' => 'uid',
|
||||||
|
'group_member_attribute' => 'member'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the configuration defaults for an ActiveDirectory environment
|
||||||
|
*
|
||||||
|
* @return ConfigObject
|
||||||
|
*/
|
||||||
|
public function getActiveDirectoryDefaults()
|
||||||
|
{
|
||||||
|
return new ConfigObject(array(
|
||||||
|
'group_class' => 'group',
|
||||||
|
'user_class' => 'user',
|
||||||
|
'group_name_attribute' => 'sAMAccountName',
|
||||||
|
'user_name_attribute' => 'sAMAccountName',
|
||||||
|
'group_member_attribute' => 'member'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,8 @@ class UserGroupBackend
|
|||||||
*/
|
*/
|
||||||
protected static $defaultBackends = array(
|
protected static $defaultBackends = array(
|
||||||
'db',
|
'db',
|
||||||
|
'ldap',
|
||||||
|
'msldap',
|
||||||
//'ini'
|
//'ini'
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -156,6 +158,11 @@ class UserGroupBackend
|
|||||||
case 'ini':
|
case 'ini':
|
||||||
$backend = new IniUserGroupBackend($resource);
|
$backend = new IniUserGroupBackend($resource);
|
||||||
break;
|
break;
|
||||||
|
case 'ldap':
|
||||||
|
case 'msldap':
|
||||||
|
$backend = new LdapUserGroupBackend($resource);
|
||||||
|
$backend->setConfig($backendConfig);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$backend->setName($name);
|
$backend->setName($name);
|
||||||
|
@ -313,14 +313,19 @@ class IniEditor
|
|||||||
*/
|
*/
|
||||||
public function getText()
|
public function getText()
|
||||||
{
|
{
|
||||||
$this->cleanUpWhitespaces();
|
$this->normalizeSectionSpacing();
|
||||||
return rtrim(implode(PHP_EOL, $this->text)) . PHP_EOL;
|
|
||||||
|
// trim leading and trailing whitespaces from generated file
|
||||||
|
$txt = trim(implode(PHP_EOL, $this->text)) . PHP_EOL;
|
||||||
|
|
||||||
|
// replace linebreaks, unless they preceed a comment or a section
|
||||||
|
return preg_replace("/\n[\n]*([^;\[])/", "\n$1", $txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all unneeded line breaks between sections
|
* normalize section spacing according to the current settings
|
||||||
*/
|
*/
|
||||||
private function cleanUpWhitespaces()
|
private function normalizeSectionSpacing()
|
||||||
{
|
{
|
||||||
$i = count($this->text) - 1;
|
$i = count($this->text) - 1;
|
||||||
for (; $i > 0; $i--) {
|
for (; $i > 0; $i--) {
|
||||||
@ -328,24 +333,18 @@ class IniEditor
|
|||||||
if ($this->isSectionDeclaration($line) && $i > 0) {
|
if ($this->isSectionDeclaration($line) && $i > 0) {
|
||||||
$i--;
|
$i--;
|
||||||
$line = $this->text[$i];
|
$line = $this->text[$i];
|
||||||
/*
|
// ignore comments that are glued to the section declaration
|
||||||
* Ignore comments that are glued to the section declaration
|
|
||||||
*/
|
|
||||||
while ($i > 0 && $this->isComment($line)) {
|
while ($i > 0 && $this->isComment($line)) {
|
||||||
$i--;
|
$i--;
|
||||||
$line = $this->text[$i];
|
$line = $this->text[$i];
|
||||||
}
|
}
|
||||||
/*
|
// remove whitespaces between the sections
|
||||||
* Remove whitespaces between the sections
|
|
||||||
*/
|
|
||||||
while ($i > 0 && preg_match('/^\s*$/', $line) === 1) {
|
while ($i > 0 && preg_match('/^\s*$/', $line) === 1) {
|
||||||
$this->deleteLine($i);
|
$this->deleteLine($i);
|
||||||
$i--;
|
$i--;
|
||||||
$line = $this->text[$i];
|
$line = $this->text[$i];
|
||||||
}
|
}
|
||||||
/*
|
// refresh section separators
|
||||||
* Refresh section separators
|
|
||||||
*/
|
|
||||||
if ($i !== 0 && $this->sectionSeparators > 0) {
|
if ($i !== 0 && $this->sectionSeparators > 0) {
|
||||||
$this->insertAtLine($i + 1, str_repeat(PHP_EOL, $this->sectionSeparators - 1));
|
$this->insertAtLine($i + 1, str_repeat(PHP_EOL, $this->sectionSeparators - 1));
|
||||||
}
|
}
|
||||||
@ -621,6 +620,6 @@ class IniEditor
|
|||||||
|
|
||||||
private function sanitize($value)
|
private function sanitize($value)
|
||||||
{
|
{
|
||||||
return str_replace('\n', '', $value);
|
return str_replace("\n", '', $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ class IniWriter extends Zend_Config_Writer_FileAbstract
|
|||||||
{
|
{
|
||||||
if (file_exists($this->_filename)) {
|
if (file_exists($this->_filename)) {
|
||||||
$oldconfig = new Zend_Config_Ini($this->_filename);
|
$oldconfig = new Zend_Config_Ini($this->_filename);
|
||||||
$content = file_get_contents($this->_filename);
|
$content = trim(file_get_contents($this->_filename));
|
||||||
} else {
|
} else {
|
||||||
$oldconfig = new Zend_Config(array());
|
$oldconfig = new Zend_Config(array());
|
||||||
$content = '';
|
$content = '';
|
||||||
|
66
library/Icinga/Repository/LdapRepository.php
Normal file
66
library/Icinga/Repository/LdapRepository.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Repository;
|
||||||
|
|
||||||
|
use Icinga\Protocol\Ldap\Connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract base class for concrete LDAP repository implementations
|
||||||
|
*
|
||||||
|
* Additionally provided features:
|
||||||
|
* <ul>
|
||||||
|
* <li>Attribute name normalization</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
abstract class LdapRepository extends Repository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The datasource being used
|
||||||
|
*
|
||||||
|
* @var Connection
|
||||||
|
*/
|
||||||
|
protected $ds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normed attribute names based on known LDAP environments
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $normedAttributes = array(
|
||||||
|
'uid' => 'uid',
|
||||||
|
'gid' => 'gid',
|
||||||
|
'user' => 'user',
|
||||||
|
'group' => 'group',
|
||||||
|
'member' => 'member',
|
||||||
|
'inetorgperson' => 'inetOrgPerson',
|
||||||
|
'samaccountname' => 'sAMAccountName'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new LDAP repository object
|
||||||
|
*
|
||||||
|
* @param Connection $ds The data source to use
|
||||||
|
*/
|
||||||
|
public function __construct(Connection $ds)
|
||||||
|
{
|
||||||
|
parent::__construct($ds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the given attribute name normed to known LDAP enviroments, if possible
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getNormedAttribute($name)
|
||||||
|
{
|
||||||
|
$loweredName = strtolower($name);
|
||||||
|
if (array_key_exists($loweredName, $this->normedAttributes)) {
|
||||||
|
return $this->normedAttributes[$loweredName];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
}
|
@ -599,6 +599,37 @@ abstract class Repository implements Selectable
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the given value based on the ASN.1 standard (GeneralizedTime) and return its timestamp representation
|
||||||
|
*
|
||||||
|
* @param string|null $value
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function retrieveGeneralizedTime($value)
|
||||||
|
{
|
||||||
|
if ($value === null) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
($dateTime = DateTime::createFromFormat('YmdHis.uO', $value)) !== false
|
||||||
|
|| ($dateTime = DateTime::createFromFormat('YmdHis.uZ', $value)) !== false
|
||||||
|
|| ($dateTime = DateTime::createFromFormat('YmdHis.u', $value)) !== false
|
||||||
|
|| ($dateTime = DateTime::createFromFormat('YmdHis', $value)) !== false
|
||||||
|
|| ($dateTime = DateTime::createFromFormat('YmdHi', $value)) !== false
|
||||||
|
|| ($dateTime = DateTime::createFromFormat('YmdH', $value)) !== false
|
||||||
|
) {
|
||||||
|
return $dateTime->getTimeStamp();
|
||||||
|
} else {
|
||||||
|
Logger::debug(sprintf(
|
||||||
|
'Failed to parse "%s" based on the ASN.1 standard (GeneralizedTime) in repository "%s".',
|
||||||
|
$value,
|
||||||
|
$this->getName()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate that the requested table exists
|
* Validate that the requested table exists
|
||||||
*
|
*
|
||||||
|
@ -855,8 +855,19 @@ class Form extends Zend_Form
|
|||||||
public function populate(array $defaults)
|
public function populate(array $defaults)
|
||||||
{
|
{
|
||||||
$this->create($defaults);
|
$this->create($defaults);
|
||||||
|
$this->preserveDefaults($this, $defaults);
|
||||||
|
return parent::populate($defaults);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->getElements() as $name => $_) {
|
/**
|
||||||
|
* Recurse the given form and unset all unchanged default values
|
||||||
|
*
|
||||||
|
* @param Zend_Form $form
|
||||||
|
* @param array $defaults
|
||||||
|
*/
|
||||||
|
protected function preserveDefaults(Zend_Form $form, array & $defaults)
|
||||||
|
{
|
||||||
|
foreach ($form->getElements() as $name => $_) {
|
||||||
if (
|
if (
|
||||||
array_key_exists($name, $defaults)
|
array_key_exists($name, $defaults)
|
||||||
&& array_key_exists($name . static::DEFAULT_SUFFIX, $defaults)
|
&& array_key_exists($name . static::DEFAULT_SUFFIX, $defaults)
|
||||||
@ -866,7 +877,9 @@ class Form extends Zend_Form
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::populate($defaults);
|
foreach ($form->getSubForms() as $_ => $subForm) {
|
||||||
|
$this->preserveDefaults($subForm, $defaults);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -279,6 +279,11 @@ class Menu implements RecursiveIterator
|
|||||||
'priority' => 990,
|
'priority' => 990,
|
||||||
'renderer' => 'ForeignMenuItemRenderer'
|
'renderer' => 'ForeignMenuItemRenderer'
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->add(t('About'), array(
|
||||||
|
'url' => 'about',
|
||||||
|
'priority' => 1000
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,12 @@ $this->addHelperFunction('url', function ($path = null, $params = null) {
|
|||||||
} else {
|
} else {
|
||||||
$url = Url::fromPath($path);
|
$url = Url::fromPath($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($params !== null) {
|
if ($params !== null) {
|
||||||
|
if ($url === $path) {
|
||||||
|
$url = clone $url;
|
||||||
|
}
|
||||||
|
|
||||||
$url->overwriteParams($params);
|
$url->overwriteParams($params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<?php foreach (/** @var \Icinga\Module\Doc\Renderer\DocSearchRenderer[] $searches */ $searches as $title => $search): ?>
|
<?php foreach (/** @var \Icinga\Module\Doc\Renderer\DocSearchRenderer[] $searches */ $searches as $title => $search): ?>
|
||||||
<?php if (! $search->isEmpty()): ?>
|
<h2><?= $this->escape($title) ?></h2>
|
||||||
<h1><?= $this->escape($title) ?></h1>
|
<?= $search->isEmpty()
|
||||||
<?= $search ?>
|
? $this->translate('No documentation found matching the filter')
|
||||||
<?php endif ?>
|
: $search ?>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
</div>
|
</div>
|
||||||
|
@ -132,8 +132,8 @@ $extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$g
|
|||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
<a aria-hidden="true" id="end" href="<?= Url::fromRequest()->remove(
|
<a aria-hidden="true" id="end" href="<?= Url::fromRequest()->remove(
|
||||||
array(
|
array(
|
||||||
'raw_timestamp<',
|
'timestamp<',
|
||||||
'raw_timestamp>'
|
'timestamp>'
|
||||||
)
|
)
|
||||||
)->overwriteParams(
|
)->overwriteParams(
|
||||||
array(
|
array(
|
||||||
|
@ -10,6 +10,39 @@ $configDir = Icinga::app()->getConfigDir();
|
|||||||
$setupTokenPath = rtrim($configDir, '/') . '/setup.token';
|
$setupTokenPath = rtrim($configDir, '/') . '/setup.token';
|
||||||
$cliPath = realpath(Icinga::app()->getApplicationDir() . '/../bin/icingacli');
|
$cliPath = realpath(Icinga::app()->getApplicationDir() . '/../bin/icingacli');
|
||||||
|
|
||||||
|
$groupadd = null;
|
||||||
|
$usermod = null;
|
||||||
|
if (! (false === ($distro = Platform::getLinuxDistro(1)) || $distro === 'linux')) {
|
||||||
|
foreach (array(
|
||||||
|
'groupadd -r icingaweb2' => array(
|
||||||
|
'redhat', 'rhel', 'centos', 'fedora',
|
||||||
|
'suse', 'sles', 'sled', 'opensuse'
|
||||||
|
),
|
||||||
|
'addgroup --system icingaweb2' => array('debian', 'ubuntu')
|
||||||
|
) as $groupadd_ => $distros) {
|
||||||
|
if (in_array($distro, $distros)) {
|
||||||
|
$groupadd = $groupadd_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array(
|
||||||
|
'usermod -a -G icingaweb2 apache' => array(
|
||||||
|
'redhat', 'rhel', 'centos', 'fedora'
|
||||||
|
),
|
||||||
|
'usermod -A icingaweb2 wwwrun' => array(
|
||||||
|
'suse', 'sles', 'sled', 'opensuse'
|
||||||
|
),
|
||||||
|
'usermod -a -G icingaweb2 www-data' => array(
|
||||||
|
'debian', 'ubuntu'
|
||||||
|
)
|
||||||
|
) as $usermod_ => $distros) {
|
||||||
|
if (in_array($distro, $distros)) {
|
||||||
|
$usermod = $usermod_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
<div class="welcome-page">
|
<div class="welcome-page">
|
||||||
<h2><?= $this->translate('Welcome to the configuration of Icinga Web 2!') ?></h2>
|
<h2><?= $this->translate('Welcome to the configuration of Icinga Web 2!') ?></h2>
|
||||||
@ -51,6 +84,12 @@ $cliPath = realpath(Icinga::app()->getApplicationDir() . '/../bin/icingacli');
|
|||||||
<li><?= $this->translate('Your webserver\'s user is a member of the system group "icingaweb2"'); ?></li>
|
<li><?= $this->translate('Your webserver\'s user is a member of the system group "icingaweb2"'); ?></li>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</ul>
|
</ul>
|
||||||
|
<?php if (! ($groupadd === null || $usermod === null)) { ?>
|
||||||
|
<div class="code">
|
||||||
|
<span><?= $this->escape($groupadd . ';') ?></span>
|
||||||
|
<span><?= $this->escape($usermod . ';') ?></span>
|
||||||
|
</div>
|
||||||
|
<?php } ?>
|
||||||
<p><?= $this->translate('If you\'ve got the IcingaCLI installed you can do the following:'); ?></p>
|
<p><?= $this->translate('If you\'ve got the IcingaCLI installed you can do the following:'); ?></p>
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<span><?= $cliPath ? $cliPath : 'icingacli'; ?> setup config directory --group icingaweb2<?= $configDir !== '/etc/icingaweb2' ? ' --config ' . $configDir : ''; ?>;</span>
|
<span><?= $cliPath ? $cliPath : 'icingacli'; ?> setup config directory --group icingaweb2<?= $configDir !== '/etc/icingaweb2' ? ' --config ' . $configDir : ''; ?>;</span>
|
||||||
|
@ -331,8 +331,7 @@ html {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: replace this with .error */
|
.message-error {
|
||||||
.fileNotReadable {
|
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
background-color: @colorCritical;
|
background-color: @colorCritical;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -27,10 +27,9 @@ class LdapBackendFormTest extends BaseTestCase
|
|||||||
*/
|
*/
|
||||||
public function testValidBackendIsValid()
|
public function testValidBackendIsValid()
|
||||||
{
|
{
|
||||||
$this->setUpResourceFactoryMock();
|
$ldapUserBackendMock = Mockery::mock('overload:Icinga\Authentication\User\LdapUserBackend');
|
||||||
Mockery::mock('overload:Icinga\Authentication\User\LdapUserBackend')
|
$ldapUserBackendMock->shouldReceive('assertAuthenticationPossible')->andReturnNull();
|
||||||
->shouldReceive('assertAuthenticationPossible')->andReturnNull()
|
$this->setUpUserBackendMock($ldapUserBackendMock);
|
||||||
->shouldReceive('setConfig')->andReturnNull();
|
|
||||||
|
|
||||||
// Passing array(null) is required to make Mockery call the constructor...
|
// Passing array(null) is required to make Mockery call the constructor...
|
||||||
$form = Mockery::mock('Icinga\Forms\Config\UserBackend\LdapBackendForm[getView]', array(null));
|
$form = Mockery::mock('Icinga\Forms\Config\UserBackend\LdapBackendForm[getView]', array(null));
|
||||||
@ -53,9 +52,9 @@ class LdapBackendFormTest extends BaseTestCase
|
|||||||
*/
|
*/
|
||||||
public function testInvalidBackendIsNotValid()
|
public function testInvalidBackendIsNotValid()
|
||||||
{
|
{
|
||||||
$this->setUpResourceFactoryMock();
|
$ldapUserBackendMock = Mockery::mock('overload:Icinga\Authentication\User\LdapUserBackend');
|
||||||
Mockery::mock('overload:Icinga\Authentication\User\LdapUserBackend')
|
$ldapUserBackendMock->shouldReceive('assertAuthenticationPossible')->andThrow(new AuthenticationException);
|
||||||
->shouldReceive('assertAuthenticationPossible')->andThrow(new AuthenticationException);
|
$this->setUpUserBackendMock($ldapUserBackendMock);
|
||||||
|
|
||||||
// Passing array(null) is required to make Mockery call the constructor...
|
// Passing array(null) is required to make Mockery call the constructor...
|
||||||
$form = Mockery::mock('Icinga\Forms\Config\UserBackend\LdapBackendForm[getView]', array(null));
|
$form = Mockery::mock('Icinga\Forms\Config\UserBackend\LdapBackendForm[getView]', array(null));
|
||||||
@ -72,12 +71,10 @@ class LdapBackendFormTest extends BaseTestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setUpResourceFactoryMock()
|
protected function setUpUserBackendMock($ldapUserBackendMock)
|
||||||
{
|
{
|
||||||
Mockery::mock('alias:Icinga\Data\ResourceFactory')
|
Mockery::mock('alias:Icinga\Authentication\User\UserBackend')
|
||||||
->shouldReceive('createResource')
|
->shouldReceive('create')
|
||||||
->andReturn(Mockery::mock('Icinga\Protocol\Ldap\Connection'))
|
->andReturn($ldapUserBackendMock);
|
||||||
->shouldReceive('getResourceConfig')
|
|
||||||
->andReturn(new ConfigObject());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -719,6 +719,34 @@ EOD;
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testWhetherLinebreaksAreRemoved()
|
||||||
|
{
|
||||||
|
$target = $this->writeConfigToTemporaryFile('');
|
||||||
|
$writer = new IniWriter(
|
||||||
|
array(
|
||||||
|
'config' => Config::fromArray(
|
||||||
|
array(
|
||||||
|
'section' => array(
|
||||||
|
'foo' => 'linebreak
|
||||||
|
in line',
|
||||||
|
'linebreak
|
||||||
|
inkey' => 'blarg'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'filename' => $target
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$rendered = $writer->render();
|
||||||
|
var_dump($rendered);
|
||||||
|
$this->assertEquals(
|
||||||
|
count(explode("\n", $rendered)),
|
||||||
|
4,
|
||||||
|
'generated config should not contain more than three line breaks'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a INI-configuration string to a temporary file and return its path
|
* Write a INI-configuration string to a temporary file and return its path
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user