diff --git a/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb b/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb index f28395e18..87f9f53ed 100644 --- a/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb +++ b/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb @@ -1,5 +1,5 @@ [autologin] -backend = autologin +backend = external [icingaweb-mysql] backend = db diff --git a/application/controllers/AuthenticationController.php b/application/controllers/AuthenticationController.php index 2d7926819..4e70894a1 100644 --- a/application/controllers/AuthenticationController.php +++ b/application/controllers/AuthenticationController.php @@ -8,7 +8,7 @@ use Icinga\Application\Config; use Icinga\Application\Icinga; use Icinga\Application\Logger; use Icinga\Authentication\AuthChain; -use Icinga\Authentication\Backend\AutoLoginBackend; +use Icinga\Authentication\Backend\ExternalBackend; use Icinga\Exception\AuthenticationException; use Icinga\Exception\ConfigurationError; use Icinga\Exception\NotReadableError; @@ -39,6 +39,7 @@ class AuthenticationController extends ActionController $this->redirectNow(Url::fromPath('setup')); } + $triedOnlyExternalAuth = null; $auth = $this->Auth(); $this->view->form = $form = new LoginForm(); $this->view->title = $this->translate('Icingaweb Login'); @@ -82,7 +83,7 @@ class AuthenticationController extends ActionController } foreach ($chain as $backend) { - if ($backend instanceof AutoLoginBackend) { + if ($backend instanceof ExternalBackend) { continue; } ++$backendsTried; @@ -126,7 +127,8 @@ class AuthenticationController extends ActionController } elseif ($request->isGet()) { $user = new User(''); foreach ($chain as $backend) { - if ($backend instanceof AutoLoginBackend) { + $triedOnlyExternalAuth = $triedOnlyExternalAuth === null; + if ($backend instanceof ExternalBackend) { $authenticated = $backend->authenticate($user); if ($authenticated === true) { $auth->setAuthenticated($user); @@ -134,6 +136,8 @@ class AuthenticationController extends ActionController Url::fromPath(Url::fromRequest()->getParam('redirect', 'dashboard')) ); } + } else { + $triedOnlyExternalAuth = false; } } } @@ -141,6 +145,7 @@ class AuthenticationController extends ActionController $this->view->errorInfo = $e->getMessage(); } + $this->view->requiresExternalAuth = $triedOnlyExternalAuth && !$auth->isAuthenticated(); $this->view->requiresSetup = Icinga::app()->requiresSetup(); } diff --git a/application/forms/Config/Authentication/AutologinBackendForm.php b/application/forms/Config/Authentication/ExternalBackendForm.php similarity index 88% rename from application/forms/Config/Authentication/AutologinBackendForm.php rename to application/forms/Config/Authentication/ExternalBackendForm.php index cd09d38ac..51000b2d2 100644 --- a/application/forms/Config/Authentication/AutologinBackendForm.php +++ b/application/forms/Config/Authentication/ExternalBackendForm.php @@ -8,16 +8,16 @@ use Zend_Validate_Callback; use Icinga\Web\Form; /** - * Form class for adding/modifying autologin authentication backends + * Form class for adding/modifying authentication backends of type "external" */ -class AutologinBackendForm extends Form +class ExternalBackendForm extends Form { /** * Initialize this form */ public function init() { - $this->setName('form_config_authbackend_autologin'); + $this->setName('form_config_authbackend_external'); } /** @@ -69,7 +69,7 @@ class AutologinBackendForm extends Form 'backend', array( 'disabled' => true, - 'value' => 'autologin' + 'value' => 'external' ) ); @@ -79,7 +79,7 @@ class AutologinBackendForm extends Form /** * Validate the configuration by creating a backend and requesting the user count * - * Returns always true as autologin backends are just "passive" backends. (The webserver authenticates users.) + * Returns always true as backends of type "external" are just "passive" backends. * * @param Form $form The form to fetch the configuration values from * diff --git a/application/forms/Config/AuthenticationBackendConfigForm.php b/application/forms/Config/AuthenticationBackendConfigForm.php index 076f8cb17..de3093ada 100644 --- a/application/forms/Config/AuthenticationBackendConfigForm.php +++ b/application/forms/Config/AuthenticationBackendConfigForm.php @@ -14,7 +14,7 @@ use Icinga\Data\ResourceFactory; use Icinga\Exception\ConfigurationError; use Icinga\Forms\Config\Authentication\DbBackendForm; use Icinga\Forms\Config\Authentication\LdapBackendForm; -use Icinga\Forms\Config\Authentication\AutologinBackendForm; +use Icinga\Forms\Config\Authentication\ExternalBackendForm; class AuthenticationBackendConfigForm extends ConfigForm { @@ -67,8 +67,8 @@ class AuthenticationBackendConfigForm extends ConfigForm } elseif ($type === 'ldap') { $form = new LdapBackendForm(); $form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array()); - } elseif ($type === 'autologin') { - $form = new AutologinBackendForm(); + } elseif ($type === 'external') { + $form = new ExternalBackendForm(); } else { throw new InvalidArgumentException(sprintf($this->translate('Invalid backend type "%s" provided'), $type)); } @@ -251,14 +251,14 @@ class AuthenticationBackendConfigForm extends ConfigForm $configValues['name'] = $authBackend; $this->populate($configValues); } elseif (empty($this->resources)) { - $autologinBackends = array_filter( + $externalBackends = array_filter( $this->config->toArray(), function ($authBackendCfg) { - return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'autologin'; + return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'external'; } ); - if (false === empty($autologinBackends)) { + if (false === empty($externalBackends)) { throw new ConfigurationError($this->translate('Could not find any resources for authentication')); } } @@ -299,14 +299,14 @@ class AuthenticationBackendConfigForm extends ConfigForm $backendTypes['ldap'] = 'LDAP'; } - $autologinBackends = array_filter( + $externalBackends = array_filter( $this->config->toArray(), function ($authBackendCfg) { - return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'autologin'; + return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'external'; } ); - if ($backendType === 'autologin' || empty($autologinBackends)) { - $backendTypes['autologin'] = $this->translate('Autologin'); + if ($backendType === 'external' || empty($externalBackends)) { + $backendTypes['external'] = $this->translate('External'); } if ($backendType === null) { diff --git a/application/views/scripts/authentication/login.phtml b/application/views/scripts/authentication/login.phtml index 7d8d15df8..805196b96 100644 --- a/application/views/scripts/authentication/login.phtml +++ b/application/views/scripts/authentication/login.phtml @@ -1,11 +1,28 @@
-

Welcome to Icinga Web 2

+ +

translate( + 'It appears that you did not configure Icinga Web 2 yet so it\'s not possible to log in without any defined ' + . 'authentication method. Please define a authentication method by following the instructions in the' + . ' %1$sdocumentation%3$s or by using our %2$sweb-based setup-wizard%3$s.' + ), + '', // TODO: More exact documentation link.. + '', + '' + ); ?>

+ +

translate( + 'You\'re currently not authenticated using any of the web server\'s authentication mechanisms.' + . ' Make sure you\'ll configure such, otherwise you\'ll not be able to login.' + ); ?>

+ +

translate('Welcome to Icinga Web 2'); ?>

errorInfo)): ?> @@ -14,18 +31,6 @@
form ?> - - -
', // TODO: Documentation link - '', - '' - ); ?>
- +
diff --git a/doc/authentication.md b/doc/authentication.md index d36051e8f..542eb9934 100644 --- a/doc/authentication.md +++ b/doc/authentication.md @@ -24,7 +24,7 @@ For delegating authentication to the web server simply add `autologin` to your a ```` [autologin] -backend = autologin +backend = external ```` If your web server is not configured for authentication though the `autologin` section has no effect. diff --git a/doc/external_authentication.md b/doc/external_authentication.md index 240713038..15df1e1cf 100644 --- a/doc/external_authentication.md +++ b/doc/external_authentication.md @@ -1,90 +1,83 @@ -# Externel Authentication +# External Authentication -It is possible to use the authentication mechanism of the webserver, -instead of using the internal authentication-manager to -authenticate users. This might be useful if you only have very few users, and -user management over *.htaccess* is sufficient, or if you must use some other -authentication mechanism that is only available through your webserver. +It is possible to utilize the authentication mechanism of the webserver instead +of the internal authentication of Icinga Web 2 to authenticate users. This might +be useful if you only have very few users and user management over **.htaccess** +is not sufficient or if you are required to use some other authentication +mechanism that is only available by utilizing the webserver. -When external authentication is used, Icingaweb will entrust the -complete authentication process to the external authentication provider (the webserver): -The provider should take care of authenticating the user and declining -all requests with invalid or missing credentials. When the authentication -was succesful, it should provide the authenticated users name to its php-module -and Icingaweb will assume that the user is authorized to access the page. -Because of this it is very important that the webservers authentication is -configured correctly, as wrong configuration could lead to unauthorized -access to the site, or a broken login-process. +Icinga Web 2 will entrust the complete authentication process to the +authentication provider of the webserver, if external authentication is used. +So it is very important that the webserver's authentication is configured +correctly as wrong configuration might lead to unauthorized access or a +malfunction in the login-process. +## Using External Authentication -## Use External Authentication +External authentication in Icinga Web 2 requires the following preparations: -Using external authentication in Icingaweb requires two steps to work: +1. The external authentication must be set up properly to correctly + authenticate users +2. Icinga Web 2 must be configured to use external authentication -1. The external authentication must be set up correctly to always - authenticate the users. -2. Icingaweb must be configured to use the external authentication. +### Preparing the External Authentication Provider +This step depends heavily on the used webserver and authentication mechanism you +want to use. It is not possible to cover all possibillities and you should +probably read the documentation for your webserver to get detailed instructions +on how to set up authentication properly. -### Prepare the External Authentication Provider - -This step depends heavily on the used webserver and authentication -mechanism you want to use. It is not possible to cover all possibillities -and you should probably read the documentation for your webserver for -detailed instructions on how to set up authentication properly. - -In general, you need to make sure that: - - - All routes require authentication - - Only permitted users are allowed to authenticate +In general you need to make sure that: +- All routes require authentication +- Only permitted users are allowed to authenticate #### Example Configuration for Apache and HTTPDigestAuthentication -The following example will show how to enable external authentication in Apache using -*HTTP Digest Authentication*. +The following example will show how to enable external authentication in Apache +using *HTTP Digest Authentication*. -##### Create users +##### Creating users -To create users for a digest authentication we can use the tool *htdigest*. -We choose *.icingawebdigest* as a name for the created file, containing -the user credentials. +To create users for digest authentication you can use the tool *htdigest*. In +this example **.icingawebdigest** is the name of the file containing the user +credentials. -This command will create a new file with the user *jdoe*. *htdigest* -will prompt you for your password, after it has been executed. If you -want to add more users to the file you need to ommit the *-c* parameter -in all further commands to avoInid the file to be overwritten. +This command creates a new file with the user *jdoe*. *htdigest* will prompt +you for a password. If you want to add more users to the file you need to omit +the *-c* parameter in all following commands to not to overwrite the file. +```` +sudo htdigest -c /etc/icingaweb2/.icingawebdigest "Icinga Web 2" jdoe +```` - sudo htdigest -c /etc/httpd/conf.d/.icingawebdigest "Icingaweb 2" jdoe +##### Configuring the Webserver +The webserver should require authentication for all public Icinga Web 2 files. -##### Set up authentication +```` + + AuthType digest + AuthName "Icinga Web 2" + AuthDigestProvider file + AuthUserFile /etc/icingaweb2/.icingawebdigest + Require valid-user + +```` -The webserver should require authentication for all public icingaweb files. +### Preparing Icinga Web 2 +Once external authentication is set up correctly you need to configure Icinga +Web 2. In case you already completed the setup wizard it is likely that you are +now finished. - - AuthType digest - AuthName "Icingaweb 2" - AuthDigestProvider file - AuthUserFile /etc/httpd/conf.d/.icingawebdigest - Require valid-user - +To get Icinga Web 2 to use external authentication the file +**config/authentication.ini** is required. Just add the following section +called "autologin", or any name of your choice, and save your changes: - -### Prepare Icingaweb +```` +[autologin] +backend = external +```` -When the external authentication is set up correctly, we need -to configure IcingaWeb to use it as an authentication source. The -configuration key *authenticationMode* in the section *global* defines -if the authentication should be handled internally or externally. Since -we want to delegate the authentication to the Webserver we choose -"external" as the new value: - - - [global] - ; ... - authenticationMode = "external" - ; ... - +Congratulations! You are now logged in when visiting Icinga Web 2. \ No newline at end of file diff --git a/doc/installation.md b/doc/installation.md index def23ffaf..170199832 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -107,4 +107,4 @@ In case you do not remember the token you can show it using the `icingacli`: **Step 5: Web Setup** -Visit Icinga Web 2 in your browser and complete installation using the web setup. +Visit Icinga Web 2 in your browser and complete installation using the web setup: /icingaweb2/setup diff --git a/library/Icinga/Application/ApplicationBootstrap.php b/library/Icinga/Application/ApplicationBootstrap.php index 909431663..89bca7b97 100644 --- a/library/Icinga/Application/ApplicationBootstrap.php +++ b/library/Icinga/Application/ApplicationBootstrap.php @@ -407,7 +407,7 @@ abstract class ApplicationBootstrap */ protected function loadSetupModuleIfNecessary() { - if (! @file_exists($this->config->resolvePath('config.ini'))) { + if (! @file_exists($this->config->resolvePath('authentication.ini'))) { $this->requiresSetup = true; $this->moduleManager->loadModule('setup'); } elseif ($this->setupTokenExists()) { diff --git a/library/Icinga/Authentication/Backend/AutoLoginBackend.php b/library/Icinga/Authentication/Backend/ExternalBackend.php similarity index 91% rename from library/Icinga/Authentication/Backend/AutoLoginBackend.php rename to library/Icinga/Authentication/Backend/ExternalBackend.php index b4a70bd4f..d5eb491e5 100644 --- a/library/Icinga/Authentication/Backend/AutoLoginBackend.php +++ b/library/Icinga/Authentication/Backend/ExternalBackend.php @@ -11,7 +11,7 @@ use Icinga\User; /** * Test login with external authentication mechanism, e.g. Apache */ -class AutoLoginBackend extends UserBackend +class ExternalBackend extends UserBackend { /** * Regexp expression to strip values from a username @@ -21,7 +21,7 @@ class AutoLoginBackend extends UserBackend private $stripUsernameRegexp; /** - * Create new autologin backend + * Create new authentication backend of type "external" * * @param ConfigObject $config */ @@ -33,7 +33,7 @@ class AutoLoginBackend extends UserBackend /** * Count the available users * - * Autologin backends will always return 1 + * Authenticaton backends of type "external" will always return 1 * * @return int */ diff --git a/library/Icinga/Authentication/UserBackend.php b/library/Icinga/Authentication/UserBackend.php index eaf39e49d..7215f4d41 100644 --- a/library/Icinga/Authentication/UserBackend.php +++ b/library/Icinga/Authentication/UserBackend.php @@ -5,7 +5,7 @@ namespace Icinga\Authentication; use Countable; -use Icinga\Authentication\Backend\AutoLoginBackend; +use Icinga\Authentication\Backend\ExternalBackend; use Icinga\Authentication\Backend\DbUserBackend; use Icinga\Authentication\Backend\LdapUserBackend; use Icinga\Data\ConfigObject; @@ -69,8 +69,8 @@ abstract class UserBackend implements Countable ); } $backendType = strtolower($backendType); - if ($backendType === 'autologin') { - $backend = new AutoLoginBackend($backendConfig); + if ($backendType === 'external') { + $backend = new ExternalBackend($backendConfig); $backend->setName($name); return $backend; } diff --git a/modules/setup/application/forms/AuthBackendPage.php b/modules/setup/application/forms/AuthBackendPage.php index ced0d9c59..b123b5906 100644 --- a/modules/setup/application/forms/AuthBackendPage.php +++ b/modules/setup/application/forms/AuthBackendPage.php @@ -7,7 +7,7 @@ namespace Icinga\Module\Setup\Forms; use Icinga\Web\Form; use Icinga\Forms\Config\Authentication\DbBackendForm; use Icinga\Forms\Config\Authentication\LdapBackendForm; -use Icinga\Forms\Config\Authentication\AutologinBackendForm; +use Icinga\Forms\Config\Authentication\ExternalBackendForm; use Icinga\Data\ConfigObject; /** @@ -80,7 +80,7 @@ class AuthBackendPage extends Form 'Before you are able to authenticate using the LDAP connection defined earlier you need to' . ' provide some more information so that Icinga Web 2 is able to locate account details.' ); - } else { // if ($this->config['type'] === 'autologin' + } else { // if ($this->config['type'] === 'external' $note = $this->translate( 'You\'ve chosen to authenticate using a web server\'s mechanism so it may be necessary' . ' to adjust usernames before any permissions, restrictions, etc. are being applied.' @@ -103,8 +103,8 @@ class AuthBackendPage extends Form } elseif ($this->config['type'] === 'ldap') { $backendForm = new LdapBackendForm(); $backendForm->createElements($formData)->removeElement('resource'); - } else { // $this->config['type'] === 'autologin' - $backendForm = new AutologinBackendForm(); + } else { // $this->config['type'] === 'external' + $backendForm = new ExternalBackendForm(); $backendForm->createElements($formData); } diff --git a/modules/setup/application/forms/AuthenticationPage.php b/modules/setup/application/forms/AuthenticationPage.php index 88db9c6d8..f51ef946a 100644 --- a/modules/setup/application/forms/AuthenticationPage.php +++ b/modules/setup/application/forms/AuthenticationPage.php @@ -36,6 +36,28 @@ class AuthenticationPage extends Form ) ) ); + + if (isset($formData['type']) && $formData['type'] === 'external' && !isset($_SERVER['REMOTE_USER'])) { + $this->addElement( + 'note', + 'external_note', + array( + 'value' => $this->translate( + 'You\'re currently not authenticated using any of the web server\'s authentication ' + . 'mechanisms. Make sure you\'ll configure such, otherwise you\'ll not be able to ' + . 'log into Icinga Web 2.' + ), + 'decorators' => array( + 'ViewHelper', + array( + 'HtmlTag', + array('tag' => 'p', 'class' => 'icon-info info-box') + ) + ) + ) + ); + } + $this->addElement( 'note', 'description', @@ -54,13 +76,14 @@ class AuthenticationPage extends Form if (Platform::extensionLoaded('ldap')) { $backendTypes['ldap'] = 'LDAP'; } - $backendTypes['autologin'] = $this->translate('Autologin'); + $backendTypes['external'] = $this->translate('External'); $this->addElement( 'select', 'type', array( 'required' => true, + 'autosubmit' => true, 'label' => $this->translate('Authentication Type'), 'description' => $this->translate('The type of authentication to use when accessing Icinga Web 2'), 'multiOptions' => $backendTypes diff --git a/modules/setup/library/Setup/Steps/AuthenticationStep.php b/modules/setup/library/Setup/Steps/AuthenticationStep.php index a15198c57..ce0b49f58 100644 --- a/modules/setup/library/Setup/Steps/AuthenticationStep.php +++ b/modules/setup/library/Setup/Steps/AuthenticationStep.php @@ -139,7 +139,7 @@ class AuthenticationStep extends Step . '' . t('User Name Attribute') . '' . '' . $this->data['backendConfig']['user_name_attribute'] . '' . '' - ) : ($authType === 'autologin' ? ( + ) : ($authType === 'external' ? ( '' . '' . t('Filter Pattern') . '' . '' . $this->data['backendConfig']['strip_username_regexp'] . '' diff --git a/public/css/icinga/login.less b/public/css/icinga/login.less index cfae3c478..6b03b476a 100644 --- a/public/css/icinga/login.less +++ b/public/css/icinga/login.less @@ -113,18 +113,33 @@ margin-left: 5em; } - div.config-note { + p.config-note { width: 50%; padding: 1em; - margin: 5em auto 0; + margin: 0 auto 2.5em; text-align: center; color: white; background-color: @colorCritical; + + a { + color: white; + font-weight: bold; + } } - div.config-note a { - color: white; - font-weight: bold; + p.info-box { + width: 50%; + height: 2.2em; + margin: 0 auto 2.5em; + + span.icon-info { + float: left; + height: 100%; + } + + em { + text-decoration: underline; + } } } diff --git a/public/css/icinga/main-content.less b/public/css/icinga/main-content.less index 5b142184d..e3e31b397 100644 --- a/public/css/icinga/main-content.less +++ b/public/css/icinga/main-content.less @@ -203,3 +203,9 @@ table.benchmark { [class^="icon-"]:before, [class*=" icon-"]:before { text-decoration: none; } + +.info-box { + padding: 0.5em; + border: 1px solid lightgrey; + background-color: infobackground; +} diff --git a/public/css/icinga/setup.less b/public/css/icinga/setup.less index 0bf8eb7b2..9dff6fecf 100644 --- a/public/css/icinga/setup.less +++ b/public/css/icinga/setup.less @@ -220,6 +220,10 @@ } } +#setup_authentication_type p.info-box em { + text-decoration: underline; +} + #setup_ldap_discovery_confirm table { margin: 1em 0; border-collapse: separate;