Authentication: Add backend to handle external authentication
Drop external auth configuration from config.ini and move implementation into a single backend provider named 'autologin'. This provider can strip realm names from username with a custom regexp. fixes #6081
This commit is contained in:
parent
a0459d0172
commit
29f593a357
|
@ -1,3 +1,9 @@
|
|||
[autologin]
|
||||
backend = autologin
|
||||
;
|
||||
; If you want to strip the domain
|
||||
; strip_username_regexp = /\@[^$]+$/
|
||||
|
||||
[internal_ldap_authentication]
|
||||
backend = ldap
|
||||
resource = internal_ldap
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
# namespace Icinga\Application\Controllers;
|
||||
|
||||
use Icinga\Authentication\Backend\AutoLoginBackend;
|
||||
use Icinga\Web\Controller\ActionController;
|
||||
use Icinga\Authentication\Manager as AuthManager;
|
||||
use Icinga\Form\Authentication\LoginForm;
|
||||
|
@ -62,6 +63,8 @@ class AuthenticationController extends ActionController
|
|||
$this->view->form = new LoginForm();
|
||||
$this->view->form->setRequest($this->_request);
|
||||
$this->view->title = $this->translate('Icingaweb Login');
|
||||
$user = new User('');
|
||||
$password = '';
|
||||
|
||||
try {
|
||||
$redirectUrl = Url::fromPath($this->_request->getParam('redirect', 'dashboard'));
|
||||
|
@ -71,29 +74,49 @@ class AuthenticationController extends ActionController
|
|||
}
|
||||
|
||||
$auth = AuthManager::getInstance();
|
||||
|
||||
if ($auth->isAuthenticated()) {
|
||||
$this->redirectNow($redirectUrl);
|
||||
}
|
||||
|
||||
if ($this->view->form->isSubmittedAndValid()) {
|
||||
try {
|
||||
$config = Config::app('authentication');
|
||||
} catch (NotReadableError $e) {
|
||||
Logger::error(
|
||||
new Exception('Cannot load authentication configuration. An exception was thrown:', 0, $e)
|
||||
);
|
||||
throw new ConfigurationError(
|
||||
'No authentication methods available. It seems that none authentication method has been set'
|
||||
. ' up. Please check the system log or Icinga Web 2 log for more information'
|
||||
);
|
||||
try {
|
||||
$config = Config::app('authentication');
|
||||
} catch (NotReadableError $e) {
|
||||
Logger::error(
|
||||
new Exception('Cannot load authentication configuration. An exception was thrown:', 0, $e)
|
||||
);
|
||||
throw new ConfigurationError(
|
||||
'No authentication methods available. It seems that none authentication method has been set'
|
||||
. ' up. Please check the system log or Icinga Web 2 log for more information'
|
||||
);
|
||||
}
|
||||
|
||||
$chain = new AuthChain($config);
|
||||
|
||||
|
||||
if ($this->getRequest()->isGet()) {
|
||||
foreach ($chain as $backend) {
|
||||
if ($backend instanceof AutoLoginBackend) {
|
||||
$authenticated = $backend->authenticate($user, $password);
|
||||
if ($authenticated === true) {
|
||||
$auth->setAuthenticated($user);
|
||||
$this->redirectNow($redirectUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif ($this->view->form->isSubmittedAndValid()) {
|
||||
$user = new User($this->view->form->getValue('username'));
|
||||
$password = $this->view->form->getValue('password');
|
||||
$backendsTried = 0;
|
||||
$backendsWithError = 0;
|
||||
$chain = new AuthChain($config);
|
||||
|
||||
foreach ($chain as $backend) {
|
||||
++$backendsTried;
|
||||
|
||||
if ($backend instanceof AutoLoginBackend) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$authenticated = $backend->authenticate($user, $password);
|
||||
} catch (AuthenticationException $e) {
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
; The backends will be processed from top to bottom using the first backend for authentication which reports that
|
||||
; the user trying to log in is available.
|
||||
|
||||
[autologin]
|
||||
backend = autologin
|
||||
;
|
||||
; If you want to strip the domain
|
||||
; strip_username_regexp = /\@[^$]+$/
|
||||
|
||||
[internal_ldap_authentication]
|
||||
@ldap_auth_disabled@
|
||||
|
|
|
@ -11,10 +11,6 @@ timeFormat = "g:i A"
|
|||
; won't show up in the list of disabled modules
|
||||
; modulePath = "/vagrant/modules:/usr/share/icingaweb/modules"
|
||||
|
||||
; The used authentication-mode can be either "internal" to handle the authentication in IcingaWeb
|
||||
; or "external" to delegate the authentication to the used WebServer
|
||||
authenticationMode = "internal"
|
||||
|
||||
[logging]
|
||||
enable = true
|
||||
; Writing to a Stream
|
||||
|
|
|
@ -211,23 +211,6 @@ class Web extends ApplicationBootstrap
|
|||
|
||||
if ($authenticationManager->isAuthenticated() === true) {
|
||||
$this->user = $authenticationManager->getUser();
|
||||
return $this;
|
||||
}
|
||||
|
||||
try {
|
||||
$config = Config::app();
|
||||
} catch (NotReadableError $e) {
|
||||
Logger::error(
|
||||
new Exception('Cannot load global configuration (config.ini). An exception was thrown:', 0, $e)
|
||||
);
|
||||
$config = null;
|
||||
}
|
||||
|
||||
if ($config !== null && $config->global !== null &&
|
||||
$config->global->get('authenticationMode', 'internal') === 'external'
|
||||
) {
|
||||
$authenticationManager->authenticateFromRemoteUser();
|
||||
$this->user = $authenticationManager->getUser();
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Authentication\Backend;
|
||||
|
||||
use Icinga\Authentication\UserBackend;
|
||||
use Icinga\User;
|
||||
use \Zend_Config;
|
||||
|
||||
/**
|
||||
* Test login with external authentication mechanism, e.g. Apache
|
||||
*/
|
||||
class AutoLoginBackend extends UserBackend
|
||||
{
|
||||
/**
|
||||
* Regexp expression to strip values from a username
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $stripUsernameRegexp;
|
||||
|
||||
/**
|
||||
* Create new autologin backend
|
||||
*
|
||||
* @param Zend_Config $config
|
||||
*/
|
||||
public function __construct(Zend_Config $config)
|
||||
{
|
||||
$this->stripUsernameRegexp = $config->get('strip_username_regexp');
|
||||
}
|
||||
|
||||
/**
|
||||
* (PHP 5 >= 5.1.0)<br/>
|
||||
* Count elements of an object
|
||||
* @link http://php.net/manual/en/countable.count.php
|
||||
* @return int The custom count as an integer.
|
||||
* </p>
|
||||
* <p>
|
||||
* The return value is cast to an integer.
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the given user exists
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasUser(User $user)
|
||||
{
|
||||
if (isset($_SERVER['PHP_AUTH_USER'])
|
||||
&& isset($_SERVER['AUTH_TYPE'])
|
||||
&& in_array($_SERVER['AUTH_TYPE'], array('Basic', 'Digest')) === true
|
||||
) {
|
||||
$username = filter_var(
|
||||
$_SERVER['PHP_AUTH_USER'],
|
||||
FILTER_SANITIZE_STRING,
|
||||
FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW
|
||||
);
|
||||
|
||||
if ($username !== false) {
|
||||
if ($this->stripUsernameRegexp !== null) {
|
||||
$username = preg_replace($this->stripUsernameRegexp, '', $username);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $password
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate(User $user, $password)
|
||||
{
|
||||
return $this->hasUser($user);
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@
|
|||
namespace Icinga\Authentication;
|
||||
|
||||
use Countable;
|
||||
use Icinga\Authentication\Backend\AutoLoginBackend;
|
||||
use Zend_Config;
|
||||
use Icinga\Authentication\Backend\DbUserBackend;
|
||||
use Icinga\Authentication\Backend\LdapUserBackend;
|
||||
|
@ -84,6 +85,11 @@ abstract class UserBackend implements Countable
|
|||
}
|
||||
return new $backendConfig->class($backendConfig);
|
||||
}
|
||||
if ($name === 'autologin') {
|
||||
$backend = new AutoLoginBackend($backendConfig);
|
||||
$backend->setName($name);
|
||||
return $backend;
|
||||
}
|
||||
if ($backendConfig->resource === null) {
|
||||
throw new ConfigurationError(
|
||||
'Authentication configuration for backend "' . $name
|
||||
|
|
|
@ -287,6 +287,9 @@ class Monitoring_ListController extends Controller
|
|||
)
|
||||
)->getQuery();
|
||||
$this->view->contacts = $query->paginate();
|
||||
|
||||
file_put_contents('/tmp/query.txt', (string) $query);
|
||||
|
||||
$this->setupSortControl(array(
|
||||
'contact_name' => 'Name',
|
||||
'contact_alias' => 'Alias',
|
||||
|
|
Loading…
Reference in New Issue