mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-04-08 17:15:08 +02:00
commit
346ab198bb
config
doc
library/Icinga
Application
Authentication
User/Preferences
Util
test/php/library/Icinga
@ -1,26 +1,32 @@
|
||||
[users]
|
||||
backend=ldap
|
||||
hostname=localhost
|
||||
root_dn="ou=people,dc=icinga,dc=org"
|
||||
bind_dn="cn=admin,cn=config"
|
||||
bind_pw=admin
|
||||
user_class=inetOrgPerson
|
||||
user_name_attribute=uid
|
||||
; authentication.ini
|
||||
;
|
||||
; 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-mysql]
|
||||
backend=Db
|
||||
dbtype=mysql
|
||||
table=account
|
||||
host=localhost
|
||||
password=icinga
|
||||
user=icingaweb
|
||||
db=icingaweb
|
||||
[users-ldap]
|
||||
backend = "ldap"
|
||||
target = "user"
|
||||
hostname = "localhost"
|
||||
root_dn = "ou=people,dc=icinga,dc=org"
|
||||
bind_dn = "cn=admin,cn=config"
|
||||
bind_pw = "admin"
|
||||
user_class = "inetOrgPerson"
|
||||
user_name_attribute = "uid"
|
||||
|
||||
[users-pgsql]
|
||||
backend=Db
|
||||
dbtype=pgsql
|
||||
table=account
|
||||
host=localhost
|
||||
password=icinga
|
||||
user=icingaweb
|
||||
db=icingaweb
|
||||
backend = "db"
|
||||
target = "user"
|
||||
resource = "icingaweb-pgsql"
|
||||
|
||||
[users-mysql]
|
||||
backend = "db"
|
||||
target = "user"
|
||||
resource = "icingaweb-mysql"
|
||||
|
@ -27,8 +27,4 @@ type=ini
|
||||
; Use database to store preference into mysql or postgres
|
||||
;[preferences]
|
||||
;type=db
|
||||
;dbtype=pgsql
|
||||
;dbhost=127.0.0.1
|
||||
;dbpassword=icingaweb
|
||||
;dbuser=icingaweb
|
||||
;dbname=icingaweb
|
||||
;resource=icingaweb-mysql
|
||||
|
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
|
||||
|
||||
The internal authentication is configured in *config/authentication.ini*. The value
|
||||
of the configuration key "backend" will determine which UserBackend class to
|
||||
The internal authentication is configured in *config/authentication.ini*.
|
||||
|
||||
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"
|
||||
which will cause the class "DbUserBackend" to be loaded.
|
||||
|
||||
There are various configuration keys in "Authentication.ini" and some are only
|
||||
used by specific backends. The internal DB uses the values
|
||||
*dbtype*,*table*,*host*,*password*,*user* and *db*, which define the used
|
||||
connection parameters, the database and the table.
|
||||
Currently these types of backends are allowed:
|
||||
* ldap
|
||||
* db
|
||||
|
||||
## 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)
|
||||
- PostgreSQL (dbtype=pgsql)
|
||||
The authentication currently supports the databases MySQL and PostgreSQL.
|
||||
|
||||
#### 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
|
||||
to the stored value.
|
||||
to the stored value.
|
||||
|
@ -29,27 +29,12 @@ example:
|
||||
|
||||
[preferences]
|
||||
type=db
|
||||
dbtype=pgsql
|
||||
dbhost=127.0.0.1
|
||||
dbpassword=icingaweb
|
||||
dbuser=icingaweb
|
||||
dbname=icingaweb
|
||||
resource=icingaweb-pgsql
|
||||
|
||||
### Settings
|
||||
|
||||
* **dbtype**: Database adapter, currently supporting ***mysql*** or ***pgsql***
|
||||
|
||||
* **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)
|
||||
* **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.
|
||||
|
||||
### 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\Platform;
|
||||
use \Icinga\Application\Config;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use \Icinga\Application\DbAdapterFactory;
|
||||
use Icinga\Exception\ConfigurationError;
|
||||
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
|
||||
* @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()
|
||||
->setupErrorHandling()
|
||||
->setupTimezone()
|
||||
->setupResourceFactories()
|
||||
->setupRequest()
|
||||
->setupZendMvc()
|
||||
->setupTranslation()
|
||||
|
@ -29,11 +29,11 @@
|
||||
|
||||
namespace Icinga\Authentication\Backend;
|
||||
|
||||
use Icinga\User;
|
||||
use Icinga\Authentication\UserBackend;
|
||||
use Icinga\Authentication\Credentials;
|
||||
use Icinga\Authentication;
|
||||
use Icinga\Application\Logger;
|
||||
use \Icinga\User;
|
||||
use \Icinga\Authentication\UserBackend;
|
||||
use \Icinga\Authentication\Credentials;
|
||||
use \Icinga\Authentication;
|
||||
use \Icinga\Application\Logger;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
@ -53,72 +75,31 @@ class DbUserBackend implements UserBackend {
|
||||
private $db = null;
|
||||
|
||||
/**
|
||||
* The name of the user table as provided by the configuration
|
||||
* The name of the user table
|
||||
*
|
||||
* @var String
|
||||
*/
|
||||
private $userTable;
|
||||
|
||||
/**
|
||||
* 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'
|
||||
);
|
||||
|
||||
private $userTable = "account";
|
||||
/**
|
||||
* 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->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
|
||||
));
|
||||
$this->db = $database;
|
||||
|
||||
/*
|
||||
* Test the connection settings
|
||||
*/
|
||||
$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;
|
||||
|
||||
}
|
||||
/*
|
||||
* Test if the connection is available
|
||||
*/
|
||||
$this->db->getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user identified by the given credentials is available
|
||||
*
|
||||
* @param Credentials $credentials The login credentials
|
||||
*
|
||||
* @return boolean True when the username is known and currently active.
|
||||
*/
|
||||
public function hasUsername(Credentials $credential)
|
||||
@ -135,6 +116,7 @@ class DbUserBackend implements UserBackend {
|
||||
* Authenticate a user with the given credentials
|
||||
*
|
||||
* @param Credentials $credentials The login credentials
|
||||
*
|
||||
* @return User|null The authenticated user or Null.
|
||||
*/
|
||||
public function authenticate(Credentials $credential)
|
||||
@ -146,12 +128,16 @@ class DbUserBackend implements UserBackend {
|
||||
$this->db->getConnection();
|
||||
$res = $this->db
|
||||
->select()->from($this->userTable)
|
||||
->where($this->USER_NAME_COLUMN.' = ?',$credential->getUsername())
|
||||
->where($this->ACTIVE_COLUMN. ' = ?',true)
|
||||
->where($this->PASSWORD_COLUMN. ' = ?',hash_hmac('sha256',
|
||||
->where(self::USER_NAME_COLUMN.' = ?', $credential->getUsername())
|
||||
->where(self::ACTIVE_COLUMN. ' = ?', true)
|
||||
->where(
|
||||
self::PASSWORD_COLUMN. ' = ?',
|
||||
hash_hmac(
|
||||
'sha256',
|
||||
$this->getUserSalt($credential->getUsername()),
|
||||
$credential->getPassword())
|
||||
$credential->getPassword()
|
||||
)
|
||||
)
|
||||
->query()->fetch();
|
||||
if (!empty($res)) {
|
||||
$this->updateLastLogin($credential->getUsername());
|
||||
@ -171,31 +157,34 @@ class DbUserBackend implements UserBackend {
|
||||
$this->db->update(
|
||||
$this->userTable,
|
||||
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
|
||||
*
|
||||
* @param $username The user whose salt should be fetched.
|
||||
*
|
||||
* @return String|null Returns the salt-string or Null, when the user does not exist.
|
||||
*/
|
||||
private function getUserSalt($username)
|
||||
{
|
||||
$this->db->getConnection();
|
||||
$res = $this->db->select()
|
||||
->from($this->userTable,$this->SALT_COLUMN)
|
||||
->where($this->USER_NAME_COLUMN.' = ?',$username)
|
||||
->from($this->userTable, self::SALT_COLUMN)
|
||||
->where(self::USER_NAME_COLUMN.' = ?', $username)
|
||||
->query()->fetch();
|
||||
return $res[$this->SALT_COLUMN];
|
||||
return $res[self::SALT_COLUMN];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the user information from the database
|
||||
*
|
||||
* @param $username The name of the user.
|
||||
*
|
||||
* @return User|null Returns the user object, or null when the user does not exist.
|
||||
*/
|
||||
private function getUserByName($username)
|
||||
@ -208,8 +197,8 @@ class DbUserBackend implements UserBackend {
|
||||
$this->db->getConnection();
|
||||
$res = $this->db->
|
||||
select()->from($this->userTable)
|
||||
->where($this->USER_NAME_COLUMN.' = ?',$username)
|
||||
->where($this->ACTIVE_COLUMN.' = ?',true)
|
||||
->where(self::USER_NAME_COLUMN.' = ?', $username)
|
||||
->where(self::ACTIVE_COLUMN.' = ?', true)
|
||||
->query()->fetch();
|
||||
if (empty($res)) {
|
||||
return null;
|
||||
@ -225,16 +214,18 @@ class DbUserBackend implements UserBackend {
|
||||
* Create a new instance of User from a query result
|
||||
*
|
||||
* @param array $result The query result-array containing the column
|
||||
*
|
||||
* @return User The created instance of User.
|
||||
*/
|
||||
private function createUserFromResult(Array $result)
|
||||
{
|
||||
$usr = new User(
|
||||
$result[$this->USER_NAME_COLUMN],
|
||||
$result[$this->FIRST_NAME_COLUMN],
|
||||
$result[$this->LAST_NAME_COLUMN],
|
||||
$result[$this->EMAIL_COLUMN]);
|
||||
$usr->setDomain($result[$this->DOMAIN_COLUMN]);
|
||||
$result[self::USER_NAME_COLUMN],
|
||||
$result[self::FIRST_NAME_COLUMN],
|
||||
$result[self::LAST_NAME_COLUMN],
|
||||
$result[self::EMAIL_COLUMN]
|
||||
);
|
||||
$usr->setDomain($result[self::DOMAIN_COLUMN]);
|
||||
return $usr;
|
||||
}
|
||||
}
|
||||
|
@ -45,24 +45,32 @@ use \Icinga\Application\Config as IcingaConfig;
|
||||
class LdapUserBackend implements UserBackend
|
||||
{
|
||||
/**
|
||||
* @var Ldap\Connection
|
||||
**/
|
||||
* @var Ldap\Connection
|
||||
**/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* Creates a new Authentication backend using the
|
||||
* connection information provided in $config
|
||||
*
|
||||
* @param object $config The ldap connection information
|
||||
**/
|
||||
* The ldap connection information
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Creates a new Authentication backend using the
|
||||
* connection information provided in $config
|
||||
*
|
||||
* @param object $config The ldap connection information
|
||||
**/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->connection = new Ldap\Connection($config);
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Icinga\Authentication\UserBackend::hasUsername
|
||||
**/
|
||||
* @see Icinga\Authentication\UserBackend::hasUsername
|
||||
**/
|
||||
public function hasUsername(Credentials $credential)
|
||||
{
|
||||
return $this->connection->fetchOne(
|
||||
@ -71,44 +79,44 @@ class LdapUserBackend implements UserBackend
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the '*' characted from $string
|
||||
*
|
||||
* @param String $string
|
||||
*
|
||||
* @return String
|
||||
**/
|
||||
* Removes the '*' characted from $string
|
||||
*
|
||||
* @param String $string
|
||||
*
|
||||
* @return String
|
||||
**/
|
||||
protected function stripAsterisks($string)
|
||||
{
|
||||
return str_replace('*', '', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to fetch the username given in $username from
|
||||
* the ldap connection, using the configuration parameters
|
||||
* given in the Authentication configuration
|
||||
*
|
||||
* @param String $username The username to select
|
||||
*
|
||||
* @return object $result
|
||||
**/
|
||||
* Tries to fetch the username given in $username from
|
||||
* the ldap connection, using the configuration parameters
|
||||
* given in the Authentication configuration
|
||||
*
|
||||
* @param String $username The username to select
|
||||
*
|
||||
* @return object $result
|
||||
**/
|
||||
protected function selectUsername($username)
|
||||
{
|
||||
return $this->connection->select()
|
||||
->from(
|
||||
IcingaConfig::app('authentication')->users->user_class,
|
||||
$this->config->user_class,
|
||||
array(
|
||||
IcingaConfig::app('authentication')->users->user_name_attribute
|
||||
$this->config->user_name_attribute
|
||||
)
|
||||
)
|
||||
->where(
|
||||
IcingaConfig::app('authentication')->users->user_name_attribute,
|
||||
$this->config->user_name_attribute,
|
||||
$this->stripAsterisks($username)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Icinga\Authentication\UserBackend::authenticate
|
||||
**/
|
||||
* @see Icinga\Authentication\UserBackend::authenticate
|
||||
**/
|
||||
public function authenticate(Credentials $credentials)
|
||||
{
|
||||
if (!$this->connection->testCredentials(
|
||||
|
@ -28,74 +28,75 @@
|
||||
|
||||
namespace Icinga\Authentication;
|
||||
|
||||
use Icinga\Application\Logger;
|
||||
use \Icinga\Application\Logger;
|
||||
use \Icinga\Application\Config as IcingaConfig;
|
||||
use Icinga\Exception\ConfigurationError as ConfigError;
|
||||
use Icinga\User;
|
||||
use \Icinga\Application\DbAdapterFactory;
|
||||
use \Icinga\Exception\ConfigurationError as ConfigError;
|
||||
use \Icinga\User;
|
||||
|
||||
/**
|
||||
* The authentication manager allows to identify users and
|
||||
* to persist authentication information in a session.
|
||||
*
|
||||
* Direct instanciation is not permitted, the Authencation manager
|
||||
* must be created using the getInstance method. Subsequent getInstance
|
||||
* calls return the same object and ignore any additional configuration
|
||||
*
|
||||
* When creating the Authentication manager with standard PHP Sessions,
|
||||
* you have to decide whether you want to modify the session on the first
|
||||
* initialization and provide the 'writeSession' option if so, otherwise
|
||||
* session changes won't be written to disk. This is done to prevent PHP
|
||||
* from blockung concurrent requests
|
||||
*
|
||||
* @TODO: Group support is not implemented yet
|
||||
**/
|
||||
* The authentication manager allows to identify users and
|
||||
* to persist authentication information in a session.
|
||||
*
|
||||
* Direct instanciation is not permitted, the Authencation manager
|
||||
* must be created using the getInstance method. Subsequent getInstance
|
||||
* calls return the same object and ignore any additional configuration
|
||||
*
|
||||
* When creating the Authentication manager with standard PHP Sessions,
|
||||
* you have to decide whether you want to modify the session on the first
|
||||
* initialization and provide the 'writeSession' option if so, otherwise
|
||||
* session changes won't be written to disk. This is done to prevent PHP
|
||||
* from blockung concurrent requests
|
||||
*
|
||||
* @TODO: Group support is not implemented yet
|
||||
**/
|
||||
class Manager
|
||||
{
|
||||
const BACKEND_TYPE_USER = "User";
|
||||
const BACKEND_TYPE_GROUP = "Group";
|
||||
|
||||
/**
|
||||
* @var Manager
|
||||
**/
|
||||
* @var Manager
|
||||
**/
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
**/
|
||||
* @var User
|
||||
**/
|
||||
private $user = null;
|
||||
private $groups = array();
|
||||
|
||||
/**
|
||||
* @var UserBackend
|
||||
**/
|
||||
* @var UserBackend
|
||||
**/
|
||||
private $userBackend = null;
|
||||
|
||||
/**
|
||||
* @var GroupBackend
|
||||
**/
|
||||
* @var GroupBackend
|
||||
**/
|
||||
private $groupBackend = null;
|
||||
|
||||
/**
|
||||
* @var Session
|
||||
**/
|
||||
* @var Session
|
||||
**/
|
||||
private $session = null;
|
||||
|
||||
/**
|
||||
* Creates a new authentication manager using the provided config (or the
|
||||
* configuration provided in the authentication.ini if no config is given)
|
||||
* and with the given options.
|
||||
*
|
||||
* @param IcingaConfig $config The configuration to use for authentication
|
||||
* instead of the authentication.ini
|
||||
* @param Array $options Additional options that affect the managers behaviour.
|
||||
* Supported values:
|
||||
* * writeSession : Whether the session should be writable
|
||||
* * userBackendClass : Allows to provide an own user backend class
|
||||
* (used for testing)
|
||||
* * groupBackendClass : Allows to provide an own group backend class
|
||||
* (used for testing)
|
||||
* * sessionClass : Allows to provide a different session implementation)
|
||||
**/
|
||||
* Creates a new authentication manager using the provided config (or the
|
||||
* configuration provided in the authentication.ini if no config is given)
|
||||
* and with the given options.
|
||||
*
|
||||
* @param IcingaConfig $config The configuration to use for authentication
|
||||
* instead of the authentication.ini
|
||||
* @param Array $options Additional options that affect the managers behaviour.
|
||||
* Supported values:
|
||||
* * writeSession : Whether the session should be writable
|
||||
* * userBackendClass : Allows to provide an own user backend class
|
||||
* (used for testing)
|
||||
* * groupBackendClass : Allows to provide an own group backend class
|
||||
* (used for testing)
|
||||
* * sessionClass : Allows to provide a different session implementation)
|
||||
**/
|
||||
private function __construct($config = null, array $options = array())
|
||||
{
|
||||
if ($config === null) {
|
||||
@ -103,14 +104,14 @@ class Manager
|
||||
}
|
||||
if (isset($options["userBackendClass"])) {
|
||||
$this->userBackend = $options["userBackendClass"];
|
||||
} elseif ($config->users !== null) {
|
||||
$this->userBackend = $this->initBackend(self::BACKEND_TYPE_USER, $config->users);
|
||||
} else {
|
||||
$this->userBackend = $this->initBestBackend(self::BACKEND_TYPE_USER, $config);
|
||||
}
|
||||
|
||||
if (isset($options["groupBackendClass"])) {
|
||||
$this->groupBackend = $options["groupBackendClass"];
|
||||
} elseif ($config->groups != null) {
|
||||
$this->groupBackend = $this->initBackend(self::BACKEND_TYPE_GROUP, $config->groups);
|
||||
} else {
|
||||
$this->groupBackend = $this->initBestBackend(self::BACKEND_TYPE_GROUP, $config);
|
||||
}
|
||||
|
||||
if (!isset($options["sessionClass"])) {
|
||||
@ -126,8 +127,8 @@ class Manager
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Manager:__construct()
|
||||
**/
|
||||
* @see Manager:__construct()
|
||||
**/
|
||||
public static function getInstance($config = null, array $options = array())
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
@ -137,50 +138,82 @@ 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()
|
||||
{
|
||||
self::$instance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a backend for the the given authenticationTarget (User or Group) and the
|
||||
* Authenticaiton source.
|
||||
*
|
||||
* initBackend("User", "Ldap") would create a UserLdapBackend,
|
||||
* initBackend("Group", "MySource") would create a GroupMySourceBackend,
|
||||
*
|
||||
* Supported backends can be found in the Authentication\Backend folder
|
||||
*
|
||||
* @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)
|
||||
**/
|
||||
private function initBackend($authenticationTarget, $authenticationSource)
|
||||
* Create a connection to the best available backend
|
||||
*
|
||||
* @param String $target "User" or "Group", depending on what
|
||||
* authentication information the backend should provide
|
||||
* @param Mixed $backends The configuration containing all backend configurations
|
||||
* in falling priority
|
||||
*
|
||||
* @return (null|UserBackend|GroupBackend)
|
||||
*/
|
||||
private function initBestBackend($target, $backends)
|
||||
{
|
||||
$backend = ucwords(strtolower($authenticationSource->backend));
|
||||
|
||||
if (!$backend) {
|
||||
foreach ($backends as $backend) {
|
||||
if (strtolower($target) === strtolower($backend->target)) {
|
||||
$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;
|
||||
}
|
||||
|
||||
$class = '\\Icinga\\Authentication\\Backend\\' . $backend . $authenticationTarget. 'Backend';
|
||||
return new $class($authenticationSource);
|
||||
return $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to authenticate the current user with the Credentials (@see Credentials).
|
||||
*
|
||||
* @param Credentials $credentials The credentials to use for authentication
|
||||
* @param Boolean $persist Whether to persist the authentication result
|
||||
* in the current session
|
||||
*
|
||||
* @return Boolean true on success, otherwise false
|
||||
**/
|
||||
* 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 Boolean $persist Whether to persist the authentication result
|
||||
* in the current session
|
||||
*
|
||||
* @return Boolean true on success, otherwise false
|
||||
**/
|
||||
public function authenticate(Credentials $credentials, $persist = true)
|
||||
{
|
||||
if (!$this->userBackend) {
|
||||
@ -211,29 +244,28 @@ 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()
|
||||
{
|
||||
$this->session->set("user", $this->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to authenticate the user with the current session
|
||||
**/
|
||||
* Tries to authenticate the user with the current session
|
||||
**/
|
||||
public function authenticateFromSession()
|
||||
{
|
||||
$this->user = $this->session->get("user", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the user is currently authenticated
|
||||
*
|
||||
* @param Boolean $ignoreSession Set to true to prevent authentication by session
|
||||
*
|
||||
* @param Boolean
|
||||
**/
|
||||
* Returns true when the user is currently authenticated
|
||||
*
|
||||
* @param Boolean $ignoreSession Set to true to prevent authentication by session
|
||||
*
|
||||
* @param Boolean
|
||||
**/
|
||||
public function isAuthenticated($ignoreSession = false)
|
||||
{
|
||||
if ($this->user === null && !$ignoreSession) {
|
||||
@ -243,9 +275,8 @@ class Manager
|
||||
}
|
||||
|
||||
/**
|
||||
* Purges the current authorisation information and deletes the session
|
||||
*
|
||||
**/
|
||||
* Purges the current authorisation information and deletes the session
|
||||
**/
|
||||
public function removeAuthorization()
|
||||
{
|
||||
$this->user = null;
|
||||
@ -253,18 +284,18 @@ class Manager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current user or null if no user is authenticated
|
||||
*
|
||||
* @return User
|
||||
**/
|
||||
* Returns the current user or null if no user is authenticated
|
||||
*
|
||||
* @return User
|
||||
**/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see User::getGroups
|
||||
**/
|
||||
* @see User::getGroups
|
||||
**/
|
||||
public function getGroups()
|
||||
{
|
||||
return $this->user->getGroups();
|
||||
|
@ -30,6 +30,7 @@ namespace Icinga\User\Preferences;
|
||||
|
||||
use Icinga\User;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use \Icinga\Application\DbAdapterFactory;
|
||||
use \Zend_Config;
|
||||
use \Zend_Db;
|
||||
|
||||
@ -53,6 +54,7 @@ final class StoreFactory
|
||||
*
|
||||
* @param Zend_Config $config
|
||||
* @param User $user
|
||||
*
|
||||
* @return FlushObserverInterface
|
||||
* @throws ProgrammingError
|
||||
*/
|
||||
@ -68,32 +70,11 @@ final class StoreFactory
|
||||
}
|
||||
|
||||
$items = $config->toArray();
|
||||
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;
|
||||
if ($items['type'] == 'db') {
|
||||
$items['dbAdapter'] = DbAdapterFactory::getDbAdapter($items['resource']);
|
||||
}
|
||||
unset($items['type']);
|
||||
|
||||
foreach ($items as $key => $value) {
|
||||
$setter = 'set'. ucfirst($key);
|
||||
|
@ -1,5 +1,29 @@
|
||||
<?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\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;
|
||||
|
||||
//use Icinga\Protocol\Ldap\Exception;
|
||||
//use Zend_Config_Ini;
|
||||
|
||||
require_once('Zend/Config/Ini.php');
|
||||
require_once('Zend/Db.php');
|
||||
require_once('../../library/Icinga/Authentication/UserBackend.php');
|
||||
@ -147,7 +144,7 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
||||
$config->dbtype = $dbType;
|
||||
$db = $this->createDb($dbType,$config);
|
||||
$this->setUpDb($db);
|
||||
return new DbUserBackend($config);
|
||||
return new DbUserBackend($db);
|
||||
} catch(\Exception $e) {
|
||||
echo 'CREATE_BACKEND_ERROR:'.$e->getMessage();
|
||||
return null;
|
||||
|
Loading…
x
Reference in New Issue
Block a user