mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-26 23:34:08 +02:00
commit
346ab198bb
@ -1,26 +1,32 @@
|
|||||||
[users]
|
; authentication.ini
|
||||||
backend=ldap
|
;
|
||||||
hostname=localhost
|
; Each section listed in this configuration represents a single backend
|
||||||
|
; that can be used to authenticate users or groups. Each databse backend must refer
|
||||||
|
; to a resource defined in resources.ini,
|
||||||
|
;
|
||||||
|
; The order of entries in this configuration is used to determine the fallback
|
||||||
|
; priority in case of an error. If the resource referenced in the first
|
||||||
|
; entry is not reachable, the next lower entry will be used for authentication.
|
||||||
|
; Please be aware that this behaviour is not valid for the authentication itself.
|
||||||
|
; The authentication will only be done against the one available resource with the highest
|
||||||
|
; priority.
|
||||||
|
|
||||||
|
[users-ldap]
|
||||||
|
backend = "ldap"
|
||||||
|
target = "user"
|
||||||
|
hostname = "localhost"
|
||||||
root_dn = "ou=people,dc=icinga,dc=org"
|
root_dn = "ou=people,dc=icinga,dc=org"
|
||||||
bind_dn = "cn=admin,cn=config"
|
bind_dn = "cn=admin,cn=config"
|
||||||
bind_pw=admin
|
bind_pw = "admin"
|
||||||
user_class=inetOrgPerson
|
user_class = "inetOrgPerson"
|
||||||
user_name_attribute=uid
|
user_name_attribute = "uid"
|
||||||
|
|
||||||
[users-mysql]
|
|
||||||
backend=Db
|
|
||||||
dbtype=mysql
|
|
||||||
table=account
|
|
||||||
host=localhost
|
|
||||||
password=icinga
|
|
||||||
user=icingaweb
|
|
||||||
db=icingaweb
|
|
||||||
|
|
||||||
[users-pgsql]
|
[users-pgsql]
|
||||||
backend=Db
|
backend = "db"
|
||||||
dbtype=pgsql
|
target = "user"
|
||||||
table=account
|
resource = "icingaweb-pgsql"
|
||||||
host=localhost
|
|
||||||
password=icinga
|
[users-mysql]
|
||||||
user=icingaweb
|
backend = "db"
|
||||||
db=icingaweb
|
target = "user"
|
||||||
|
resource = "icingaweb-mysql"
|
||||||
|
@ -27,8 +27,4 @@ type=ini
|
|||||||
; Use database to store preference into mysql or postgres
|
; Use database to store preference into mysql or postgres
|
||||||
;[preferences]
|
;[preferences]
|
||||||
;type=db
|
;type=db
|
||||||
;dbtype=pgsql
|
;resource=icingaweb-mysql
|
||||||
;dbhost=127.0.0.1
|
|
||||||
;dbpassword=icingaweb
|
|
||||||
;dbuser=icingaweb
|
|
||||||
;dbname=icingaweb
|
|
||||||
|
0
config/preferences/KEEP.md
Normal file → Executable file
0
config/preferences/KEEP.md
Normal file → Executable file
38
config/resources.ini
Normal file
38
config/resources.ini
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
; resources.ini
|
||||||
|
;
|
||||||
|
; The configuration file *resources.ini* contains data sources that
|
||||||
|
; can be referenced in other configurations. This allows you to manage
|
||||||
|
; all connections to SQL databases in one single place, avoiding the need
|
||||||
|
: to edit several different configuration files, when the connection
|
||||||
|
; information of a resource change.
|
||||||
|
;
|
||||||
|
; Each section represents a resource, with the section name being the
|
||||||
|
; identifier used to reference this certain section. Depending on the
|
||||||
|
; resource type, each section contains different properties. The property
|
||||||
|
; *type* defines the resource type and thus how the properties are going to
|
||||||
|
; be interpreted. Currently only the resource type *db* is available.
|
||||||
|
|
||||||
|
|
||||||
|
[icingaweb-pgsql]
|
||||||
|
type = db
|
||||||
|
db = pgsql ; PostgreSQL
|
||||||
|
host = localhost
|
||||||
|
password = icinga
|
||||||
|
username = icingaweb
|
||||||
|
dbname = icingaweb
|
||||||
|
|
||||||
|
[icingaweb-mysql]
|
||||||
|
type = db
|
||||||
|
db = mysql ; MySQL
|
||||||
|
host = localhost
|
||||||
|
password = icinga
|
||||||
|
username = icingaweb
|
||||||
|
dbname = icingaweb
|
||||||
|
|
||||||
|
[ido]
|
||||||
|
type = db
|
||||||
|
dbname = mysql
|
||||||
|
host = localhost
|
||||||
|
password = icinga
|
||||||
|
username = icingaweb
|
||||||
|
db = icingaweb
|
@ -1,29 +1,62 @@
|
|||||||
# Authentication via internal DB
|
# Authentication
|
||||||
|
|
||||||
The class DbUserBackend allows to handle the user authentication internally in a database.
|
The authentication manager can use different backend types like LDAP or Databases as data sources. During
|
||||||
|
the application bootstrap the different available resources are checked for availability and
|
||||||
|
the resource with the highest priority will be used for authentication. This behaviour is useful for setting
|
||||||
|
up fallback accounts, that are available when the regular authentication backend is not available.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
The internal authentication is configured in *config/authentication.ini*. The value
|
The internal authentication is configured in *config/authentication.ini*.
|
||||||
of the configuration key "backend" will determine which UserBackend class to
|
|
||||||
|
Each section listed in this configuration represents a single backend
|
||||||
|
that can be used to authenticate users or groups.
|
||||||
|
|
||||||
|
The order of entries in this configuration is used to determine the fallback
|
||||||
|
priority in case of an error. If the resource referenced in the first entry (the one at the top if the file)
|
||||||
|
is not reachable, the next lower entry will be used for authentication.
|
||||||
|
Please be aware that this behaviour is not valid for the authentication itself.
|
||||||
|
The authentication will only be done against the one available resource with the highest
|
||||||
|
priority. When an account is only present in a backend with lower priority, it will not
|
||||||
|
be able to authenticate when a backend with higher priority is active that does not contain
|
||||||
|
this account.
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
The value of the configuration key *backend* will determine which UserBackend class to
|
||||||
load. To use the internal backend you need to specifiy the value "Db"
|
load. To use the internal backend you need to specifiy the value "Db"
|
||||||
which will cause the class "DbUserBackend" to be loaded.
|
which will cause the class "DbUserBackend" to be loaded.
|
||||||
|
|
||||||
There are various configuration keys in "Authentication.ini" and some are only
|
Currently these types of backends are allowed:
|
||||||
used by specific backends. The internal DB uses the values
|
* ldap
|
||||||
*dbtype*,*table*,*host*,*password*,*user* and *db*, which define the used
|
* db
|
||||||
connection parameters, the database and the table.
|
|
||||||
|
|
||||||
## Database support
|
#### db
|
||||||
|
|
||||||
The module currently supports these databases:
|
The authentication source is a SQL database and points to a resource defined in *resources.ini*, which
|
||||||
|
contains all the connection information. Every entry should therefore contain a property *resource*
|
||||||
|
with the name of the assigned resource. For a more detailed description about how to set up resources,
|
||||||
|
please read the chapter *Resources*.
|
||||||
|
|
||||||
- mysql (dbtype=mysql)
|
The authentication currently supports the databases MySQL and PostgreSQL.
|
||||||
- PostgreSQL (dbtype=pgsql)
|
|
||||||
|
#### ldap
|
||||||
|
|
||||||
|
The authentication source is an ldap server. The connection information should be directly present
|
||||||
|
in the *authentication.ini*, like described in the example configuration.
|
||||||
|
|
||||||
|
|
||||||
## Authentication
|
### target
|
||||||
|
|
||||||
The backend will store the salted hash of the password in the column "password" and the salt in the column "salt".
|
The value of the configuration key *target* defines the type of authentication the described backend provides.
|
||||||
|
The allowed values are *user* for a backend that provides user authentication or *group* for group authentication.
|
||||||
|
|
||||||
|
|
||||||
|
## Technical description
|
||||||
|
|
||||||
|
If an ldap-backend is used, the standard ldap bind will be executed and all user credentials will be managed
|
||||||
|
directly by the ldap server.
|
||||||
|
|
||||||
|
In case of an SQL-backend, the backend will store the salted hash of the password in the column "password" and the salt in the column "salt".
|
||||||
When a password is checked, the hash is calculated with the function hash_hmac("sha256",salt,password) and compared
|
When a password is checked, the hash is calculated with the function hash_hmac("sha256",salt,password) and compared
|
||||||
to the stored value.
|
to the stored value.
|
@ -29,27 +29,12 @@ example:
|
|||||||
|
|
||||||
[preferences]
|
[preferences]
|
||||||
type=db
|
type=db
|
||||||
dbtype=pgsql
|
resource=icingaweb-pgsql
|
||||||
dbhost=127.0.0.1
|
|
||||||
dbpassword=icingaweb
|
|
||||||
dbuser=icingaweb
|
|
||||||
dbname=icingaweb
|
|
||||||
|
|
||||||
### Settings
|
### Settings
|
||||||
|
|
||||||
* **dbtype**: Database adapter, currently supporting ***mysql*** or ***pgsql***
|
* **resource**: A reference to a database declared in *resources.ini*. Please read the chapter about
|
||||||
|
resources for a detailed description about how to set up resources.
|
||||||
* **dbhost**: Host of the database server, use localhost or 127.0.0.1
|
|
||||||
for unix socket transport
|
|
||||||
|
|
||||||
* **dbpassword**: Password for the configured database user
|
|
||||||
|
|
||||||
* **dbuser**: User who can connect to database
|
|
||||||
|
|
||||||
* **dbname**: Name of the database
|
|
||||||
|
|
||||||
* **port**(optional): For network connections the specific port if not default
|
|
||||||
(3306 for mysql and 5432 for postgres)
|
|
||||||
|
|
||||||
### Preparation
|
### Preparation
|
||||||
|
|
||||||
|
78
doc/resources.md
Normal file
78
doc/resources.md
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# Resources
|
||||||
|
|
||||||
|
The configuration file *config/resources.ini* contains data sources that can be referenced
|
||||||
|
in other configurations. This allows you to manage all connections to databases at one central
|
||||||
|
place, avoiding the need to edit several different files, when the connection information of a resource change.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Each section represents a resource, with the section name being the identifier used to
|
||||||
|
reference this certain section. Depending on the resource type, each section contains different properties.
|
||||||
|
The property *type* defines the resource type and thus how the properties are going to be interpreted.
|
||||||
|
Currently only the resource type *db* is available.
|
||||||
|
|
||||||
|
### db
|
||||||
|
|
||||||
|
This resource type describes a SQL database. The property *db* defines the used database vendor, which
|
||||||
|
could be a value like *mysql* or *pgsql*. The other properties like *host*, *password*, *username* and
|
||||||
|
*dbname* are the connection information for the resource.
|
||||||
|
|
||||||
|
|
||||||
|
## Factory Implementations
|
||||||
|
|
||||||
|
This section contains documentation documentation for the Icinga2-Web developers that want to
|
||||||
|
use resources defined in the *resources.ini*. Each supported resource type should have an own
|
||||||
|
factory class, that can be used to comfortably create instances of classes that provide access
|
||||||
|
to the data of the resources.
|
||||||
|
|
||||||
|
|
||||||
|
### DbAdapterFactory
|
||||||
|
|
||||||
|
The DbAdapterFactory can be used to retrieve instances of Zend_Db_Adapter_Abstract for accessing
|
||||||
|
the data of the SQL database.
|
||||||
|
|
||||||
|
Lets assume for the following examples, that we have an *resources.ini* that looks like this:
|
||||||
|
|
||||||
|
[resource1]
|
||||||
|
type = "db"
|
||||||
|
db = "mysql"
|
||||||
|
dbname = "resource1"
|
||||||
|
host = "host"
|
||||||
|
username = "username1"
|
||||||
|
password = "password1"
|
||||||
|
|
||||||
|
[resource2]
|
||||||
|
type = "db"
|
||||||
|
db = "pgsql"
|
||||||
|
dbname = "resource2"
|
||||||
|
host = "host"
|
||||||
|
username = "username2"
|
||||||
|
password = "password2"
|
||||||
|
|
||||||
|
[resource3]
|
||||||
|
type = "other"
|
||||||
|
foo = "foo"
|
||||||
|
bar = "bar"
|
||||||
|
|
||||||
|
|
||||||
|
In the most simple use-case you can create an adapter by calling the
|
||||||
|
*getDbAdapter* function. The created adapter will be an instance of
|
||||||
|
Zend_Db_Adapter_Pdo_Mysql
|
||||||
|
|
||||||
|
$adapter = DbAdapterFactory::getDbAdapter('resource1');
|
||||||
|
|
||||||
|
|
||||||
|
If you specify a resource that does not exist or has the wrong type,
|
||||||
|
the factory will throw an ConfigurationException. You can make sure
|
||||||
|
a resource exists and has the right type, by calling the function *resourceExists*:
|
||||||
|
|
||||||
|
if (DbAdapterFactory::resourceExists('resource3')) {
|
||||||
|
$adapter = DbAdapterFactory::getDbAdapter('resource3');
|
||||||
|
} else {
|
||||||
|
// This returned false, because resource3 has a different type than "db"
|
||||||
|
echo 'resource does not exist, adapter could not be created...'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
You can retrieve a list of all available resources by calling *getResources*. You will
|
||||||
|
get an array of all resources that have the type 'db'.
|
@ -34,6 +34,8 @@ use Zend_Loader_Autoloader;
|
|||||||
use Icinga\Application\Modules\Manager as ModuleManager;
|
use Icinga\Application\Modules\Manager as ModuleManager;
|
||||||
use Icinga\Application\Platform;
|
use Icinga\Application\Platform;
|
||||||
use \Icinga\Application\Config;
|
use \Icinga\Application\Config;
|
||||||
|
use Icinga\Exception\ProgrammingError;
|
||||||
|
use \Icinga\Application\DbAdapterFactory;
|
||||||
use Icinga\Exception\ConfigurationError;
|
use Icinga\Exception\ConfigurationError;
|
||||||
use Icinga\Util\DateTimeFactory;
|
use Icinga\Util\DateTimeFactory;
|
||||||
|
|
||||||
@ -341,7 +343,19 @@ abstract class ApplicationBootstrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup time zone
|
* Setup factories that provide access to the resources
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
protected function setupResourceFactories()
|
||||||
|
{
|
||||||
|
$config = Config::app('resources');
|
||||||
|
DbAdapterFactory::setConfig($config);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup default timezone
|
||||||
*
|
*
|
||||||
* @return self
|
* @return self
|
||||||
* @throws ConfigurationError if the timezone in config.ini isn't valid
|
* @throws ConfigurationError if the timezone in config.ini isn't valid
|
||||||
|
202
library/Icinga/Application/DbAdapterFactory.php
Normal file
202
library/Icinga/Application/DbAdapterFactory.php
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
/**
|
||||||
|
* This file is part of Icinga 2 Web.
|
||||||
|
*
|
||||||
|
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||||
|
* Copyright (C) 2013 Icinga Development Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||||
|
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||||
|
* @author Icinga Development Team <info@icinga.org>
|
||||||
|
*/
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Icinga\Application;
|
||||||
|
|
||||||
|
use Zend_Config;
|
||||||
|
use Zend_Db;
|
||||||
|
use Icinga\Application\Logger;
|
||||||
|
use Icinga\Util\ConfigAwareFactory;
|
||||||
|
use Icinga\Exception\ConfigurationError;
|
||||||
|
use Icinga\Exception\ProgrammingError;
|
||||||
|
use Tests\Icinga\Application\ZendDbMock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create resources using short identifiers referring to configuration entries
|
||||||
|
*/
|
||||||
|
class DbAdapterFactory implements ConfigAwareFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Resource definitions
|
||||||
|
*
|
||||||
|
* @var Zend_Config
|
||||||
|
*/
|
||||||
|
private static $resources;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The factory class used to create instances of Zend_Db_Adapter
|
||||||
|
*
|
||||||
|
* @var String
|
||||||
|
*/
|
||||||
|
private static $factoryClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource cache to allow multiple use
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $resourceCache = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the configuration that stores the available resources
|
||||||
|
*
|
||||||
|
* @param mixed $config The configuration containing the resources
|
||||||
|
*
|
||||||
|
* @param array $options Additional options that affect the factories behaviour:
|
||||||
|
* * factory : Set the factory class that creates instances
|
||||||
|
* of Zend_Db_Adapter for the different database types
|
||||||
|
* (used for testing)
|
||||||
|
*/
|
||||||
|
public static function setConfig($config, array $options = null)
|
||||||
|
{
|
||||||
|
if (is_array($config)) {
|
||||||
|
$config = new Zend_Config($config);
|
||||||
|
}
|
||||||
|
self::$resources = $config;
|
||||||
|
if (isset($options['factory'])) {
|
||||||
|
self::$factoryClass = $options['factory'];
|
||||||
|
} else {
|
||||||
|
self::$factoryClass = 'Zend_Db';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the factory configuration back to the default state
|
||||||
|
*/
|
||||||
|
public static function resetConfig()
|
||||||
|
{
|
||||||
|
unset(self::$resources);
|
||||||
|
unset(self::$factoryClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of all resources available to this factory
|
||||||
|
*
|
||||||
|
* @return array An array containing all resources compatible to this factory
|
||||||
|
*/
|
||||||
|
public static function getResources()
|
||||||
|
{
|
||||||
|
$resources = self::$resources->toArray();
|
||||||
|
foreach ($resources as $identifier => $resource) {
|
||||||
|
if ($resource['type'] !== 'db') {
|
||||||
|
unset($resources[$identifier]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if a resource with the given identifier exists
|
||||||
|
*
|
||||||
|
* @param $identifier The name of the resource
|
||||||
|
*
|
||||||
|
* @return boolean If the resource exists and is compatible
|
||||||
|
*/
|
||||||
|
public static function resourceExists($identifier)
|
||||||
|
{
|
||||||
|
return isset(self::$resources->{$identifier})
|
||||||
|
&& (self::$resources->{$identifier}->type === 'db');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the resource with the given $identifier
|
||||||
|
*
|
||||||
|
* @param $identifier The name of the resource
|
||||||
|
*/
|
||||||
|
public static function getDbAdapter($identifier)
|
||||||
|
{
|
||||||
|
if (!isset(self::$resources)) {
|
||||||
|
$msg = 'Creation of resource ' . $identifier . ' not possible, because there is no configuration present.'
|
||||||
|
. ' Make shure this factory class was initialised correctly during the application bootstrap.';
|
||||||
|
Logger::error($msg);
|
||||||
|
throw new ProgrammingError($msg);
|
||||||
|
}
|
||||||
|
if (!isset(self::$resources->{$identifier})) {
|
||||||
|
$msg = 'Creation of resource "'
|
||||||
|
. $identifier
|
||||||
|
. '" not possible, because there is no matching resource present in the configuration ';
|
||||||
|
Logger::error($msg);
|
||||||
|
throw new ConfigurationError($msg);
|
||||||
|
}
|
||||||
|
if (array_key_exists($identifier, self::$resourceCache)) {
|
||||||
|
return self::$resourceCache[$identifier];
|
||||||
|
} else {
|
||||||
|
$res = self::createDbAdapter(self::$resources->{$identifier});
|
||||||
|
self::$resourceCache[$identifier] = $res;
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the Db_Adapter for the given configuration section
|
||||||
|
*
|
||||||
|
* @param mixed $config The configuration section containing the
|
||||||
|
* db information
|
||||||
|
*
|
||||||
|
* @return \Zend_Db_Adapter_Abstract The created Zend_Db_Adapter
|
||||||
|
*
|
||||||
|
* @throws \ConfigurationError When the specified db type is invalid
|
||||||
|
*/
|
||||||
|
private static function createDbAdapter($config)
|
||||||
|
{
|
||||||
|
if ($config->type !== 'db') {
|
||||||
|
throw new ConfigurationError(
|
||||||
|
'Resource type must be "db" but is "' . $config->type . '"'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$options = array(
|
||||||
|
'dbname' => $config->dbname,
|
||||||
|
'host' => $config->host,
|
||||||
|
'username' => $config->username,
|
||||||
|
'password' => $config->password,
|
||||||
|
);
|
||||||
|
switch ($config->db) {
|
||||||
|
case 'mysql':
|
||||||
|
return self::callFactory('Pdo_Mysql', $options);
|
||||||
|
case 'pgsql':
|
||||||
|
return self::callFactory('Pdo_Pgsql', $options);
|
||||||
|
default:
|
||||||
|
throw new ConfigurationError('Unsupported db type ' . $config->db . '.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the currently set factory class
|
||||||
|
*
|
||||||
|
* @param $adapter The name of the used db adapter
|
||||||
|
* @param $options OPTIONAL: an array or Zend_Config object with adapter
|
||||||
|
* parameters
|
||||||
|
*
|
||||||
|
* @return Zend_Db_Adapter_Abstract The created adapter
|
||||||
|
*/
|
||||||
|
private static function callFactory($adapter, $options)
|
||||||
|
{
|
||||||
|
$factory = self::$factoryClass;
|
||||||
|
return $factory::factory($adapter, $options);
|
||||||
|
}
|
||||||
|
}
|
@ -93,6 +93,7 @@ class Web extends ApplicationBootstrap
|
|||||||
return $this->setupConfig()
|
return $this->setupConfig()
|
||||||
->setupErrorHandling()
|
->setupErrorHandling()
|
||||||
->setupTimezone()
|
->setupTimezone()
|
||||||
|
->setupResourceFactories()
|
||||||
->setupRequest()
|
->setupRequest()
|
||||||
->setupZendMvc()
|
->setupZendMvc()
|
||||||
->setupTranslation()
|
->setupTranslation()
|
||||||
|
@ -29,11 +29,11 @@
|
|||||||
|
|
||||||
namespace Icinga\Authentication\Backend;
|
namespace Icinga\Authentication\Backend;
|
||||||
|
|
||||||
use Icinga\User;
|
use \Icinga\User;
|
||||||
use Icinga\Authentication\UserBackend;
|
use \Icinga\Authentication\UserBackend;
|
||||||
use Icinga\Authentication\Credentials;
|
use \Icinga\Authentication\Credentials;
|
||||||
use Icinga\Authentication;
|
use \Icinga\Authentication;
|
||||||
use Icinga\Application\Logger;
|
use \Icinga\Application\Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User authentication backend (@see Icinga\Authentication\UserBackend) for
|
* User authentication backend (@see Icinga\Authentication\UserBackend) for
|
||||||
@ -43,7 +43,29 @@ use Icinga\Application\Logger;
|
|||||||
* See the UserBackend class (@see Icinga\Authentication\UserBackend) for
|
* See the UserBackend class (@see Icinga\Authentication\UserBackend) for
|
||||||
* usage information
|
* usage information
|
||||||
*/
|
*/
|
||||||
class DbUserBackend implements UserBackend {
|
class DbUserBackend implements UserBackend
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Mapping of all table column names
|
||||||
|
*/
|
||||||
|
|
||||||
|
const USER_NAME_COLUMN = 'user_name';
|
||||||
|
|
||||||
|
const FIRST_NAME_COLUMN = 'first_name';
|
||||||
|
|
||||||
|
const LAST_NAME_COLUMN = 'last_name';
|
||||||
|
|
||||||
|
const LAST_LOGIN_COLUMN = 'last_login';
|
||||||
|
|
||||||
|
const SALT_COLUMN = 'salt';
|
||||||
|
|
||||||
|
const PASSWORD_COLUMN = 'password';
|
||||||
|
|
||||||
|
const ACTIVE_COLUMN = 'active';
|
||||||
|
|
||||||
|
const DOMAIN_COLUMN = 'domain';
|
||||||
|
|
||||||
|
const EMAIL_COLUMN = 'email';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The database connection that will be used for fetching users
|
* The database connection that will be used for fetching users
|
||||||
@ -53,72 +75,31 @@ class DbUserBackend implements UserBackend {
|
|||||||
private $db = null;
|
private $db = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the user table as provided by the configuration
|
* The name of the user table
|
||||||
*
|
*
|
||||||
* @var String
|
* @var String
|
||||||
*/
|
*/
|
||||||
private $userTable;
|
private $userTable = "account";
|
||||||
|
|
||||||
/**
|
|
||||||
* Mapping of columns
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $USER_NAME_COLUMN = 'user_name',
|
|
||||||
$FIRST_NAME_COLUMN = 'first_name',
|
|
||||||
$LAST_NAME_COLUMN = 'last_name',
|
|
||||||
$LAST_LOGIN_COLUMN = 'last_login',
|
|
||||||
$SALT_COLUMN = 'salt',
|
|
||||||
$PASSWORD_COLUMN = 'password',
|
|
||||||
$ACTIVE_COLUMN = 'active',
|
|
||||||
$DOMAIN_COLUMN = 'domain',
|
|
||||||
$EMAIL_COLUMN = 'email';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map the configuration dbtypes to the corresponding Zend-PDOs
|
|
||||||
*
|
|
||||||
* @var Array
|
|
||||||
*/
|
|
||||||
private $dbTypeMap = Array(
|
|
||||||
'mysql' => 'PDO_MYSQL',
|
|
||||||
'pgsql' => 'PDO_PGSQL'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a DbUserBackend
|
* Create a DbUserBackend
|
||||||
*
|
*
|
||||||
* @param $config The configuration-object containing the members host,user,password,db
|
* @param Zend_Db The database that provides the authentication data
|
||||||
*/
|
*/
|
||||||
public function __construct($config)
|
public function __construct($database)
|
||||||
{
|
{
|
||||||
$this->dbtype = $config->dbtype;
|
$this->db = $database;
|
||||||
$this->userTable = $config->table;
|
|
||||||
try {
|
|
||||||
$this->db = \Zend_Db::factory(
|
|
||||||
$this->dbTypeMap[$config->dbtype],
|
|
||||||
array(
|
|
||||||
'host' => $config->host,
|
|
||||||
'username' => $config->user,
|
|
||||||
'password' => $config->password,
|
|
||||||
'dbname' => $config->db
|
|
||||||
));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test the connection settings
|
* Test if the connection is available
|
||||||
*/
|
*/
|
||||||
$this->db->getConnection();
|
$this->db->getConnection();
|
||||||
$this->db->select()->from($this->userTable,new \Zend_Db_Expr('TRUE'));
|
|
||||||
} catch (\Zend_Db_Adapter_Exception $exc) {
|
|
||||||
Logger::error('Could not authenticate via database : %s ', $exc->getMessage());
|
|
||||||
$this->db = null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the user identified by the given credentials is available
|
* Check if the user identified by the given credentials is available
|
||||||
*
|
*
|
||||||
* @param Credentials $credentials The login credentials
|
* @param Credentials $credentials The login credentials
|
||||||
|
*
|
||||||
* @return boolean True when the username is known and currently active.
|
* @return boolean True when the username is known and currently active.
|
||||||
*/
|
*/
|
||||||
public function hasUsername(Credentials $credential)
|
public function hasUsername(Credentials $credential)
|
||||||
@ -135,6 +116,7 @@ class DbUserBackend implements UserBackend {
|
|||||||
* Authenticate a user with the given credentials
|
* Authenticate a user with the given credentials
|
||||||
*
|
*
|
||||||
* @param Credentials $credentials The login credentials
|
* @param Credentials $credentials The login credentials
|
||||||
|
*
|
||||||
* @return User|null The authenticated user or Null.
|
* @return User|null The authenticated user or Null.
|
||||||
*/
|
*/
|
||||||
public function authenticate(Credentials $credential)
|
public function authenticate(Credentials $credential)
|
||||||
@ -146,11 +128,15 @@ class DbUserBackend implements UserBackend {
|
|||||||
$this->db->getConnection();
|
$this->db->getConnection();
|
||||||
$res = $this->db
|
$res = $this->db
|
||||||
->select()->from($this->userTable)
|
->select()->from($this->userTable)
|
||||||
->where($this->USER_NAME_COLUMN.' = ?',$credential->getUsername())
|
->where(self::USER_NAME_COLUMN.' = ?', $credential->getUsername())
|
||||||
->where($this->ACTIVE_COLUMN. ' = ?',true)
|
->where(self::ACTIVE_COLUMN. ' = ?', true)
|
||||||
->where($this->PASSWORD_COLUMN. ' = ?',hash_hmac('sha256',
|
->where(
|
||||||
|
self::PASSWORD_COLUMN. ' = ?',
|
||||||
|
hash_hmac(
|
||||||
|
'sha256',
|
||||||
$this->getUserSalt($credential->getUsername()),
|
$this->getUserSalt($credential->getUsername()),
|
||||||
$credential->getPassword())
|
$credential->getPassword()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
->query()->fetch();
|
->query()->fetch();
|
||||||
if (!empty($res)) {
|
if (!empty($res)) {
|
||||||
@ -171,31 +157,34 @@ class DbUserBackend implements UserBackend {
|
|||||||
$this->db->update(
|
$this->db->update(
|
||||||
$this->userTable,
|
$this->userTable,
|
||||||
array(
|
array(
|
||||||
$this->LAST_LOGIN_COLUMN => new \Zend_Db_Expr('NOW()')
|
self::LAST_LOGIN_COLUMN => new \Zend_Db_Expr('NOW()')
|
||||||
),
|
),
|
||||||
$this->USER_NAME_COLUMN.' = '.$this->db->quoteInto('?',$username));
|
self::USER_NAME_COLUMN.' = '.$this->db->quoteInto('?', $username)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the users salt from the database
|
* Fetch the users salt from the database
|
||||||
*
|
*
|
||||||
* @param $username The user whose salt should be fetched.
|
* @param $username The user whose salt should be fetched.
|
||||||
|
*
|
||||||
* @return String|null Returns the salt-string or Null, when the user does not exist.
|
* @return String|null Returns the salt-string or Null, when the user does not exist.
|
||||||
*/
|
*/
|
||||||
private function getUserSalt($username)
|
private function getUserSalt($username)
|
||||||
{
|
{
|
||||||
$this->db->getConnection();
|
$this->db->getConnection();
|
||||||
$res = $this->db->select()
|
$res = $this->db->select()
|
||||||
->from($this->userTable,$this->SALT_COLUMN)
|
->from($this->userTable, self::SALT_COLUMN)
|
||||||
->where($this->USER_NAME_COLUMN.' = ?',$username)
|
->where(self::USER_NAME_COLUMN.' = ?', $username)
|
||||||
->query()->fetch();
|
->query()->fetch();
|
||||||
return $res[$this->SALT_COLUMN];
|
return $res[self::SALT_COLUMN];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the user information from the database
|
* Fetch the user information from the database
|
||||||
*
|
*
|
||||||
* @param $username The name of the user.
|
* @param $username The name of the user.
|
||||||
|
*
|
||||||
* @return User|null Returns the user object, or null when the user does not exist.
|
* @return User|null Returns the user object, or null when the user does not exist.
|
||||||
*/
|
*/
|
||||||
private function getUserByName($username)
|
private function getUserByName($username)
|
||||||
@ -208,8 +197,8 @@ class DbUserBackend implements UserBackend {
|
|||||||
$this->db->getConnection();
|
$this->db->getConnection();
|
||||||
$res = $this->db->
|
$res = $this->db->
|
||||||
select()->from($this->userTable)
|
select()->from($this->userTable)
|
||||||
->where($this->USER_NAME_COLUMN.' = ?',$username)
|
->where(self::USER_NAME_COLUMN.' = ?', $username)
|
||||||
->where($this->ACTIVE_COLUMN.' = ?',true)
|
->where(self::ACTIVE_COLUMN.' = ?', true)
|
||||||
->query()->fetch();
|
->query()->fetch();
|
||||||
if (empty($res)) {
|
if (empty($res)) {
|
||||||
return null;
|
return null;
|
||||||
@ -225,16 +214,18 @@ class DbUserBackend implements UserBackend {
|
|||||||
* Create a new instance of User from a query result
|
* Create a new instance of User from a query result
|
||||||
*
|
*
|
||||||
* @param array $result The query result-array containing the column
|
* @param array $result The query result-array containing the column
|
||||||
|
*
|
||||||
* @return User The created instance of User.
|
* @return User The created instance of User.
|
||||||
*/
|
*/
|
||||||
private function createUserFromResult(Array $result)
|
private function createUserFromResult(Array $result)
|
||||||
{
|
{
|
||||||
$usr = new User(
|
$usr = new User(
|
||||||
$result[$this->USER_NAME_COLUMN],
|
$result[self::USER_NAME_COLUMN],
|
||||||
$result[$this->FIRST_NAME_COLUMN],
|
$result[self::FIRST_NAME_COLUMN],
|
||||||
$result[$this->LAST_NAME_COLUMN],
|
$result[self::LAST_NAME_COLUMN],
|
||||||
$result[$this->EMAIL_COLUMN]);
|
$result[self::EMAIL_COLUMN]
|
||||||
$usr->setDomain($result[$this->DOMAIN_COLUMN]);
|
);
|
||||||
|
$usr->setDomain($result[self::DOMAIN_COLUMN]);
|
||||||
return $usr;
|
return $usr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,13 @@ class LdapUserBackend implements UserBackend
|
|||||||
**/
|
**/
|
||||||
protected $connection;
|
protected $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ldap connection information
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
private $config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Authentication backend using the
|
* Creates a new Authentication backend using the
|
||||||
* connection information provided in $config
|
* connection information provided in $config
|
||||||
@ -58,6 +65,7 @@ class LdapUserBackend implements UserBackend
|
|||||||
public function __construct($config)
|
public function __construct($config)
|
||||||
{
|
{
|
||||||
$this->connection = new Ldap\Connection($config);
|
$this->connection = new Ldap\Connection($config);
|
||||||
|
$this->config = $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,13 +103,13 @@ class LdapUserBackend implements UserBackend
|
|||||||
{
|
{
|
||||||
return $this->connection->select()
|
return $this->connection->select()
|
||||||
->from(
|
->from(
|
||||||
IcingaConfig::app('authentication')->users->user_class,
|
$this->config->user_class,
|
||||||
array(
|
array(
|
||||||
IcingaConfig::app('authentication')->users->user_name_attribute
|
$this->config->user_name_attribute
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
->where(
|
->where(
|
||||||
IcingaConfig::app('authentication')->users->user_name_attribute,
|
$this->config->user_name_attribute,
|
||||||
$this->stripAsterisks($username)
|
$this->stripAsterisks($username)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,11 @@
|
|||||||
|
|
||||||
namespace Icinga\Authentication;
|
namespace Icinga\Authentication;
|
||||||
|
|
||||||
use Icinga\Application\Logger;
|
use \Icinga\Application\Logger;
|
||||||
use \Icinga\Application\Config as IcingaConfig;
|
use \Icinga\Application\Config as IcingaConfig;
|
||||||
use Icinga\Exception\ConfigurationError as ConfigError;
|
use \Icinga\Application\DbAdapterFactory;
|
||||||
use Icinga\User;
|
use \Icinga\Exception\ConfigurationError as ConfigError;
|
||||||
|
use \Icinga\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The authentication manager allows to identify users and
|
* The authentication manager allows to identify users and
|
||||||
@ -103,14 +104,14 @@ class Manager
|
|||||||
}
|
}
|
||||||
if (isset($options["userBackendClass"])) {
|
if (isset($options["userBackendClass"])) {
|
||||||
$this->userBackend = $options["userBackendClass"];
|
$this->userBackend = $options["userBackendClass"];
|
||||||
} elseif ($config->users !== null) {
|
} else {
|
||||||
$this->userBackend = $this->initBackend(self::BACKEND_TYPE_USER, $config->users);
|
$this->userBackend = $this->initBestBackend(self::BACKEND_TYPE_USER, $config);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($options["groupBackendClass"])) {
|
if (isset($options["groupBackendClass"])) {
|
||||||
$this->groupBackend = $options["groupBackendClass"];
|
$this->groupBackend = $options["groupBackendClass"];
|
||||||
} elseif ($config->groups != null) {
|
} else {
|
||||||
$this->groupBackend = $this->initBackend(self::BACKEND_TYPE_GROUP, $config->groups);
|
$this->groupBackend = $this->initBestBackend(self::BACKEND_TYPE_GROUP, $config);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($options["sessionClass"])) {
|
if (!isset($options["sessionClass"])) {
|
||||||
@ -137,7 +138,7 @@ class Manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the instance (this is mostly needed for testing and shouldn't be called otherwise)
|
* Clear the instance (this is mostly needed for testing and shouldn't be called otherwise)
|
||||||
**/
|
**/
|
||||||
public static function clearInstance()
|
public static function clearInstance()
|
||||||
{
|
{
|
||||||
@ -145,35 +146,67 @@ class Manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a backend for the the given authenticationTarget (User or Group) and the
|
* Create a connection to the best available backend
|
||||||
* Authenticaiton source.
|
|
||||||
*
|
*
|
||||||
* initBackend("User", "Ldap") would create a UserLdapBackend,
|
* @param String $target "User" or "Group", depending on what
|
||||||
* initBackend("Group", "MySource") would create a GroupMySourceBackend,
|
* authentication information the backend should provide
|
||||||
*
|
* @param Mixed $backends The configuration containing all backend configurations
|
||||||
* Supported backends can be found in the Authentication\Backend folder
|
* in falling priority
|
||||||
*
|
|
||||||
* @param String $authenticationTarget "User" or "Group", depending on what
|
|
||||||
* authentication information the backend should
|
|
||||||
* provide
|
|
||||||
* @param String $authenticationSource The Source, see the above examples
|
|
||||||
*
|
*
|
||||||
* @return (null|UserBackend|GroupBackend)
|
* @return (null|UserBackend|GroupBackend)
|
||||||
**/
|
*/
|
||||||
private function initBackend($authenticationTarget, $authenticationSource)
|
private function initBestBackend($target, $backends)
|
||||||
{
|
{
|
||||||
$backend = ucwords(strtolower($authenticationSource->backend));
|
foreach ($backends as $backend) {
|
||||||
|
if (strtolower($target) === strtolower($backend->target)) {
|
||||||
if (!$backend) {
|
$db = $this->tryToInitBackend($target, $backend);
|
||||||
|
if (isset($db)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isset($db)) {
|
||||||
|
$msg = 'Failed to create any authentication backend, login will not be possible.';
|
||||||
|
Logger::error($msg);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return $db;
|
||||||
$class = '\\Icinga\\Authentication\\Backend\\' . $backend . $authenticationTarget. 'Backend';
|
|
||||||
return new $class($authenticationSource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to authenticate the current user with the Credentials (@see Credentials).
|
* Try to create the backend with the given configuration
|
||||||
|
*
|
||||||
|
* @param String $target "User" or "Group", depending on what
|
||||||
|
* authentication information the backend should provide
|
||||||
|
* @param $backendConfig The configuration containing backend description
|
||||||
|
*
|
||||||
|
* @return UserBackend|null Return the created backend or null
|
||||||
|
*/
|
||||||
|
private function tryToInitBackend($target, $backendConfig)
|
||||||
|
{
|
||||||
|
$type = ucwords(strtolower($backendConfig->backend));
|
||||||
|
if (!$type) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if ($backendConfig->backend === 'db') {
|
||||||
|
$resource = DbAdapterFactory::getDbAdapter($backendConfig->resource);
|
||||||
|
} else {
|
||||||
|
$resource = $backendConfig;
|
||||||
|
}
|
||||||
|
$class = '\\Icinga\\Authentication\\Backend\\' . $type . $target. 'Backend';
|
||||||
|
return new $class($resource);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$msg = 'Not able to create backend: ' .
|
||||||
|
print_r($backendConfig->backend, true)
|
||||||
|
. '. Exception: ' . $e->getMessage();
|
||||||
|
Logger::warn($msg);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to authenticate the current user with the Credentials (@see Credentials).
|
||||||
*
|
*
|
||||||
* @param Credentials $credentials The credentials to use for authentication
|
* @param Credentials $credentials The credentials to use for authentication
|
||||||
* @param Boolean $persist Whether to persist the authentication result
|
* @param Boolean $persist Whether to persist the authentication result
|
||||||
@ -212,7 +245,6 @@ class Manager
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the current user to the session (only usable when writeSession = true)
|
* Writes the current user to the session (only usable when writeSession = true)
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
public function persistCurrentUser()
|
public function persistCurrentUser()
|
||||||
{
|
{
|
||||||
@ -244,7 +276,6 @@ class Manager
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Purges the current authorisation information and deletes the session
|
* Purges the current authorisation information and deletes the session
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
public function removeAuthorization()
|
public function removeAuthorization()
|
||||||
{
|
{
|
||||||
|
@ -30,6 +30,7 @@ namespace Icinga\User\Preferences;
|
|||||||
|
|
||||||
use Icinga\User;
|
use Icinga\User;
|
||||||
use Icinga\Exception\ProgrammingError;
|
use Icinga\Exception\ProgrammingError;
|
||||||
|
use \Icinga\Application\DbAdapterFactory;
|
||||||
use \Zend_Config;
|
use \Zend_Config;
|
||||||
use \Zend_Db;
|
use \Zend_Db;
|
||||||
|
|
||||||
@ -53,6 +54,7 @@ final class StoreFactory
|
|||||||
*
|
*
|
||||||
* @param Zend_Config $config
|
* @param Zend_Config $config
|
||||||
* @param User $user
|
* @param User $user
|
||||||
|
*
|
||||||
* @return FlushObserverInterface
|
* @return FlushObserverInterface
|
||||||
* @throws ProgrammingError
|
* @throws ProgrammingError
|
||||||
*/
|
*/
|
||||||
@ -68,33 +70,12 @@ final class StoreFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
$items = $config->toArray();
|
$items = $config->toArray();
|
||||||
|
|
||||||
|
if ($items['type'] == 'db') {
|
||||||
|
$items['dbAdapter'] = DbAdapterFactory::getDbAdapter($items['resource']);
|
||||||
|
}
|
||||||
unset($items['type']);
|
unset($items['type']);
|
||||||
|
|
||||||
// TODO(mh): Encapsulate into a db adapter factory (#4503)
|
|
||||||
if (isset($items['dbname'])
|
|
||||||
&& isset($items['dbuser'])
|
|
||||||
&& isset($items['dbpassword'])
|
|
||||||
&& isset($items['dbhost'])
|
|
||||||
&& isset($items['dbtype'])
|
|
||||||
) {
|
|
||||||
$zendDbType = 'PDO_'. strtoupper($items['dbtype']);
|
|
||||||
|
|
||||||
$zendDbOptions = array(
|
|
||||||
'host' => $items['dbhost'],
|
|
||||||
'username' => $items['dbuser'],
|
|
||||||
'password' => $items['dbpassword'],
|
|
||||||
'dbname' => $items['dbname']
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isset($items['port'])) {
|
|
||||||
$zendDbOptions['port'] = $items['port'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$dbAdapter = Zend_Db::factory($zendDbType, $zendDbOptions);
|
|
||||||
|
|
||||||
$items['dbAdapter'] = $dbAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($items as $key => $value) {
|
foreach ($items as $key => $value) {
|
||||||
$setter = 'set'. ucfirst($key);
|
$setter = 'set'. ucfirst($key);
|
||||||
if (is_callable(array($store, $setter))) {
|
if (is_callable(array($store, $setter))) {
|
||||||
|
@ -1,5 +1,29 @@
|
|||||||
<?php
|
<?php
|
||||||
// {{{ICINGA_LICENSE_HEADER}}}
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
/**
|
||||||
|
* This file is part of Icinga 2 Web.
|
||||||
|
*
|
||||||
|
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||||
|
* Copyright (C) 2013 Icinga Development Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||||
|
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||||
|
* @author Icinga Development Team <info@icinga.org>
|
||||||
|
*/
|
||||||
// {{{ICINGA_LICENSE_HEADER}}}
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
namespace Icinga\Util;
|
namespace Icinga\Util;
|
||||||
|
180
test/php/library/Icinga/Application/DbAdapterFactoryTest.php
Normal file
180
test/php/library/Icinga/Application/DbAdapterFactoryTest.php
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
/**
|
||||||
|
* This file is part of Icinga 2 Web.
|
||||||
|
*
|
||||||
|
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||||
|
* Copyright (C) 2013 Icinga Development Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||||
|
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||||
|
* @author Icinga Development Team <info@icinga.org>
|
||||||
|
*/
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Tests\Icinga\Application;
|
||||||
|
|
||||||
|
require_once('Zend/Db.php');
|
||||||
|
require_once('Zend/Db/Adapter/Pdo/Mysql.php');
|
||||||
|
require_once('Zend/Config.php');
|
||||||
|
require_once('Zend/Log.php');
|
||||||
|
require_once('Zend/Config.php');
|
||||||
|
require_once('../../library/Icinga/Application/Logger.php');
|
||||||
|
require_once('library/Icinga/Application/ZendDbMock.php');
|
||||||
|
require_once('../../library/Icinga/Exception/ConfigurationError.php');
|
||||||
|
require_once('../../library/Icinga/Exception/ProgrammingError.php');
|
||||||
|
require_once('../../library/Icinga/Util/ConfigAwareFactory.php');
|
||||||
|
require_once('../../library/Icinga/Application/DbAdapterFactory.php');
|
||||||
|
|
||||||
|
use \Tests\Icinga\Application\ZendDbMock;
|
||||||
|
use \Icinga\Application\DbAdapterFactory;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unit test for the class DbAdapterFactory
|
||||||
|
*/
|
||||||
|
class DbAdapterFactoryTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The resources used for this test
|
||||||
|
*/
|
||||||
|
private $resources;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the test fixture
|
||||||
|
*/
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->resources = array(
|
||||||
|
/*
|
||||||
|
* PostgreSQL databse
|
||||||
|
*/
|
||||||
|
'resource1' => array(
|
||||||
|
'type' => 'db',
|
||||||
|
'db' => 'pgsql',
|
||||||
|
'dbname' => 'resource1',
|
||||||
|
'host' => 'host1',
|
||||||
|
'username' => 'username1',
|
||||||
|
'password' => 'password1'
|
||||||
|
),
|
||||||
|
/*
|
||||||
|
* MySQL database
|
||||||
|
*/
|
||||||
|
'resource2' => array(
|
||||||
|
'type' => 'db',
|
||||||
|
'db' => 'mysql',
|
||||||
|
'dbname' => 'resource2',
|
||||||
|
'host' => 'host2',
|
||||||
|
'username' => 'username2',
|
||||||
|
'password' => 'password2'
|
||||||
|
),
|
||||||
|
/*
|
||||||
|
* Unsupported database type
|
||||||
|
*/
|
||||||
|
'resource3' => array(
|
||||||
|
'type' => 'db',
|
||||||
|
'db' => 'mssql',
|
||||||
|
'dbname' => 'resource3',
|
||||||
|
'host' => 'host3',
|
||||||
|
'username' => 'username3',
|
||||||
|
'password' => 'password3'
|
||||||
|
),
|
||||||
|
/*
|
||||||
|
* Unsupported resource type
|
||||||
|
*/
|
||||||
|
'resource4' => array(
|
||||||
|
'type' => 'ldap',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
DbAdapterFactory::setConfig(
|
||||||
|
$this->resources,
|
||||||
|
array(
|
||||||
|
'factory' => 'Tests\Icinga\Application\ZendDbMock'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetValidResource()
|
||||||
|
{
|
||||||
|
DbAdapterFactory::getDbAdapter('resource2');
|
||||||
|
$this->assertEquals(
|
||||||
|
'Pdo_Mysql',
|
||||||
|
ZendDbMock::getAdapter(),
|
||||||
|
'The db adapter name must be Pdo_Mysql.');
|
||||||
|
$this->assertEquals(
|
||||||
|
$this->getOptions($this->resources['resource2']),
|
||||||
|
ZendDbMock::getConfig(),
|
||||||
|
'The options must match the original config file content'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResourceExists()
|
||||||
|
{
|
||||||
|
$this->assertTrue(DbAdapterFactory::resourceExists('resource2'),
|
||||||
|
'resourceExists() called with an existing resource should return true');
|
||||||
|
|
||||||
|
$this->assertFalse(DbAdapterFactory::resourceExists('not existing'),
|
||||||
|
'resourceExists() called with an existing resource should return false');
|
||||||
|
|
||||||
|
$this->assertFalse(DbAdapterFactory::resourceExists('resource4'),
|
||||||
|
'resourceExists() called with an incompatible resource should return false');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetResources()
|
||||||
|
{
|
||||||
|
$withoutIncompatible = array_merge(array(),$this->resources);
|
||||||
|
unset($withoutIncompatible['resource4']);
|
||||||
|
$this->assertEquals(
|
||||||
|
$withoutIncompatible,
|
||||||
|
DbAdapterFactory::getResources(),
|
||||||
|
'getResources should return an array of all existing resources that are compatible');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if an exception is thrown, when an invalid database is used.
|
||||||
|
*
|
||||||
|
* @expectedException Icinga\Exception\ConfigurationError
|
||||||
|
*/
|
||||||
|
public function testGetInvalidDatabase()
|
||||||
|
{
|
||||||
|
DbAdapterFactory::getDbAdapter('resource3');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if an exception is thrown, when an invalid type is used.
|
||||||
|
*
|
||||||
|
* @expectedException Icinga\Exception\ConfigurationError
|
||||||
|
*/
|
||||||
|
public function testGetInvalidType()
|
||||||
|
{
|
||||||
|
DbAdapterFactory::getDbAdapter('resource4');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the options object for assertions
|
||||||
|
*
|
||||||
|
* @param Zend_Config $config The configuration to prepare
|
||||||
|
*
|
||||||
|
* @return array The prepared options object
|
||||||
|
*/
|
||||||
|
private function getOptions($config)
|
||||||
|
{
|
||||||
|
$options = array_merge(array(),$config);
|
||||||
|
unset($options['type']);
|
||||||
|
unset($options['db']);
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
}
|
87
test/php/library/Icinga/Application/ZendDbMock.php
Normal file
87
test/php/library/Icinga/Application/ZendDbMock.php
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
/**
|
||||||
|
* This file is part of Icinga 2 Web.
|
||||||
|
*
|
||||||
|
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||||
|
* Copyright (C) 2013 Icinga Development Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||||
|
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||||
|
* @author Icinga Development Team <info@icinga.org>
|
||||||
|
*/
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Tests\Icinga\Application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partially emulate the functionality of Zend_Db
|
||||||
|
*/
|
||||||
|
class ZendDbMock
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The config that was used in the last call of the factory function
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private static $config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the adapter class that was used in the last call of the factory function
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private static $adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock the factory-method of Zend_Db and save the given parameters
|
||||||
|
*
|
||||||
|
* @param $adapter String name of base adapter class, or Zend_Config object
|
||||||
|
* @param $config mixed OPTIONAL; an array or Zend_Config object with adapter
|
||||||
|
* parameters
|
||||||
|
*
|
||||||
|
* @return stdClass Empty object
|
||||||
|
*/
|
||||||
|
public static function factory($adapter, $config)
|
||||||
|
{
|
||||||
|
self::$config = $config;
|
||||||
|
self::$adapter = $adapter;
|
||||||
|
return new \stdClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the adapter class that was used in the last call
|
||||||
|
* of the factory function
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static function getAdapter()
|
||||||
|
{
|
||||||
|
return self::$adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the config that was used in the last call of the factory function
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function getConfig()
|
||||||
|
{
|
||||||
|
return self::$config;
|
||||||
|
}
|
||||||
|
}
|
@ -29,9 +29,6 @@
|
|||||||
|
|
||||||
namespace Tests\Icinga\Authentication;
|
namespace Tests\Icinga\Authentication;
|
||||||
|
|
||||||
//use Icinga\Protocol\Ldap\Exception;
|
|
||||||
//use Zend_Config_Ini;
|
|
||||||
|
|
||||||
require_once('Zend/Config/Ini.php');
|
require_once('Zend/Config/Ini.php');
|
||||||
require_once('Zend/Db.php');
|
require_once('Zend/Db.php');
|
||||||
require_once('../../library/Icinga/Authentication/UserBackend.php');
|
require_once('../../library/Icinga/Authentication/UserBackend.php');
|
||||||
@ -147,7 +144,7 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||||||
$config->dbtype = $dbType;
|
$config->dbtype = $dbType;
|
||||||
$db = $this->createDb($dbType,$config);
|
$db = $this->createDb($dbType,$config);
|
||||||
$this->setUpDb($db);
|
$this->setUpDb($db);
|
||||||
return new DbUserBackend($config);
|
return new DbUserBackend($db);
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
echo 'CREATE_BACKEND_ERROR:'.$e->getMessage();
|
echo 'CREATE_BACKEND_ERROR:'.$e->getMessage();
|
||||||
return null;
|
return null;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user