From a8f765fa3b949c92a6699d5be2807654564dee95 Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Wed, 26 Feb 2014 17:36:20 +0100 Subject: [PATCH 1/2] Add extern authentication Provide a new settings authenticationMode and delegate the authentication handling to the webserver when the external authentication mode is set. Add a new view 'logout' that will be shown after logout from external authentication as the regular redirect to login is not possible. refs #5405 --- .../controllers/AuthenticationController.php | 10 ++- .../views/scripts/authentication/login.phtml | 2 - .../views/scripts/authentication/logout.phtml | 72 +++++++++++++++ config/config.ini.in | 4 + doc/external_authentication.md | 90 +++++++++++++++++++ library/Icinga/Application/Web.php | 5 ++ library/Icinga/Authentication/Manager.php | 37 ++++++++ 7 files changed, 216 insertions(+), 4 deletions(-) create mode 100644 application/views/scripts/authentication/logout.phtml create mode 100644 doc/external_authentication.md diff --git a/application/controllers/AuthenticationController.php b/application/controllers/AuthenticationController.php index 8838b61ae..959da8b0b 100644 --- a/application/controllers/AuthenticationController.php +++ b/application/controllers/AuthenticationController.php @@ -85,10 +85,16 @@ class AuthenticationController extends ActionController */ public function logoutAction() { - $this->_helper->layout->setLayout('inline'); $auth = AuthManager::getInstance(); $auth->removeAuthorization(); - $this->redirectToLogin(); + + if ($auth->isAuthenticatedFromRemoteUser()) { + $this->_helper->layout->setLayout('login'); + $this->_response->setHttpResponseCode(401); + } else { + $this->_helper->layout->setLayout('inline'); + $this->redirectToLogin(); + } } } // @codingStandardsIgnoreEnd diff --git a/application/views/scripts/authentication/login.phtml b/application/views/scripts/authentication/login.phtml index cfa81a9a1..33a9f021c 100644 --- a/application/views/scripts/authentication/login.phtml +++ b/application/views/scripts/authentication/login.phtml @@ -23,8 +23,6 @@ * is useful for preserving the detail view and the selection in that case. * * refs #4833 - * - * TODO: Copy this snipped into the new login.phtml */ var url = document.URL.match(/(^[^#]*)/)[0] + encodeURIComponent(window.location.hash); document.getElementById('form_login').action = url; diff --git a/application/views/scripts/authentication/logout.phtml b/application/views/scripts/authentication/logout.phtml new file mode 100644 index 000000000..eb0d6dc44 --- /dev/null +++ b/application/views/scripts/authentication/logout.phtml @@ -0,0 +1,72 @@ + + +
+
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ + diff --git a/config/config.ini.in b/config/config.ini.in index 4b57a23b4..9c6b8d10c 100755 --- a/config/config.ini.in +++ b/config/config.ini.in @@ -14,6 +14,10 @@ moduleFolder = "@icingaweb_config_path@/enabledModules" ; 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 diff --git a/doc/external_authentication.md b/doc/external_authentication.md new file mode 100644 index 000000000..240713038 --- /dev/null +++ b/doc/external_authentication.md @@ -0,0 +1,90 @@ +# Externel 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. + +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. + + +## Use External Authentication + +Using external authentication in Icingaweb requires two steps to work: + +1. The external authentication must be set up correctly to always + authenticate the users. +2. Icingaweb must be configured to use the external authentication. + + +### 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 + + +#### Example Configuration for Apache and HTTPDigestAuthentication + +The following example will show how to enable external authentication in Apache using +*HTTP Digest Authentication*. + +##### Create 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. + +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. + + + sudo htdigest -c /etc/httpd/conf.d/.icingawebdigest "Icingaweb 2" jdoe + + +##### Set up authentication + +The webserver should require authentication for all public icingaweb files. + + + + AuthType digest + AuthName "Icingaweb 2" + AuthDigestProvider file + AuthUserFile /etc/httpd/conf.d/.icingawebdigest + Require valid-user + + + +### Prepare Icingaweb + +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" + ; ... + diff --git a/library/Icinga/Application/Web.php b/library/Icinga/Application/Web.php index 470f3e54a..a334d36c3 100644 --- a/library/Icinga/Application/Web.php +++ b/library/Icinga/Application/Web.php @@ -230,6 +230,11 @@ class Web extends ApplicationBootstrap { $authenticationManager = AuthenticationManager::getInstance(); + + if ($this->getConfig()->get('global')->get('authenticationMode', 'internal') === 'external') { + $authenticationManager->authenticateFromRemoteUser(); + } + if ($authenticationManager->isAuthenticated() === true) { $user = $authenticationManager->getUser(); diff --git a/library/Icinga/Authentication/Manager.php b/library/Icinga/Authentication/Manager.php index 6307211a1..f46153fd7 100644 --- a/library/Icinga/Authentication/Manager.php +++ b/library/Icinga/Authentication/Manager.php @@ -52,6 +52,7 @@ use Icinga\Authentication\Backend\LdapUserBackend; **/ class Manager { + /** * Singleton instance * @@ -59,6 +60,13 @@ class Manager */ private static $instance; + /** + * If the user was authenticated from the REMOTE_USER server variable + * + * @var Boolean + */ + private $fromRemoteUser = false; + /** * Instance of authenticated user * @@ -387,6 +395,27 @@ class Manager $this->user = Session::getSession()->get('user'); } + /** + * Tries to authenticate the user from the session, and then from the REMOTE_USER superglobal, that can be set by + * an external authentication provider. + */ + public function authenticateFromRemoteUser() + { + $this->fromRemoteUser = true; + $this->authenticateFromSession(); + if ($this->user !== null) { + if ($this->user->getUsername() !== $_SERVER["REMOTE_USER"]) { + // Remote user has changed, clear all sessions + $this->removeAuthorization(); + } + return; + } + if ($_SERVER["REMOTE_USER"] !== null) { + $this->user = new User($_SERVER["REMOTE_USER"]); + $this->persistCurrentUser(); + } + } + /** * Returns true when the user is currently authenticated * @@ -472,4 +501,12 @@ class Manager { return $this->user->getGroups(); } + + /** + * If the session was established from the REMOTE_USER server variable. + */ + public function isAuthenticatedFromRemoteUser() + { + return $this->fromRemoteUser; + } } From b118e9679d1d36eac12c96b4a7fbca0c04a4fb72 Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Wed, 26 Feb 2014 17:57:22 +0100 Subject: [PATCH 2/2] When webserver setting is missing regular authentication will be used Check if the remote user is set and use regular authentication when the key is missing. refs #5405 --- library/Icinga/Authentication/Manager.php | 4 ++-- library/Icinga/Web/Widget/Chart/PieChart.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/Icinga/Authentication/Manager.php b/library/Icinga/Authentication/Manager.php index f46153fd7..a818c6081 100644 --- a/library/Icinga/Authentication/Manager.php +++ b/library/Icinga/Authentication/Manager.php @@ -404,13 +404,13 @@ class Manager $this->fromRemoteUser = true; $this->authenticateFromSession(); if ($this->user !== null) { - if ($this->user->getUsername() !== $_SERVER["REMOTE_USER"]) { + if (array_key_exists('REMOTE_USER', $_SERVER) && $this->user->getUsername() !== $_SERVER["REMOTE_USER"]) { // Remote user has changed, clear all sessions $this->removeAuthorization(); } return; } - if ($_SERVER["REMOTE_USER"] !== null) { + if (array_key_exists('REMOTE_USER', $_SERVER) && $_SERVER["REMOTE_USER"]) { $this->user = new User($_SERVER["REMOTE_USER"]); $this->persistCurrentUser(); } diff --git a/library/Icinga/Web/Widget/Chart/PieChart.php b/library/Icinga/Web/Widget/Chart/PieChart.php index 0e4547135..edc4e78fe 100644 --- a/library/Icinga/Web/Widget/Chart/PieChart.php +++ b/library/Icinga/Web/Widget/Chart/PieChart.php @@ -43,7 +43,7 @@ class PieChart implements Widget */ private $template =<<<'EOD' -
+
EOD;