Change 'user' table to 'account', error handling and docs
Fix installation instructions for postgresql, the user table is now 'account', as user is a keyword in some rdbms, now catching exceptions and returning auth failed while logging errors refs #3769
This commit is contained in:
parent
ce95511890
commit
306a51271b
|
@ -1,7 +1,7 @@
|
|||
[users]
|
||||
backend=Db
|
||||
dbtype=mysql
|
||||
table=user
|
||||
dbtype=pgsql
|
||||
table=account
|
||||
host=localhost
|
||||
password=icinga
|
||||
user=icingaweb
|
||||
|
|
|
@ -43,7 +43,7 @@ your backend, take a look at the various options described in `./configure --hel
|
|||
It is required to set up all used Databases correctly, which basically means to create all needed user accounts and to
|
||||
create all database tables. You will find the installation guides for the different databases in the sections below:
|
||||
|
||||
*IMPORTANT*: Select a secure password instead of "icinga" and alter the config/*.ini accordingly.
|
||||
*IMPORTANT*: Select a secure password instead of "icinga" and alter the config/authentication.ini accordingly.
|
||||
|
||||
|
||||
#### MySQL
|
||||
|
@ -51,12 +51,12 @@ create all database tables. You will find the installation guides for the differ
|
|||
1. Create the user and the database
|
||||
|
||||
|
||||
mysql -u root -p
|
||||
mysql> CREATE USER `icingaweb`@`localhost` IDENTIFIED BY 'icinga';
|
||||
mysql> CREATE DATABASE `icingaweb`;
|
||||
mysql> GRANT ALL PRIVILEGES ON `icingaweb`.* TO `icingaweb`@`localhost`;
|
||||
mysql> FLUSH PRIVILEGES;
|
||||
mysql> quit
|
||||
mysql -u root -p
|
||||
mysql> CREATE USER `icingaweb`@`localhost` IDENTIFIED BY 'icinga';
|
||||
mysql> CREATE DATABASE `icingaweb`;
|
||||
mysql> GRANT ALL PRIVILEGES ON `icingaweb`.* TO `icingaweb`@`localhost`;
|
||||
mysql> FLUSH PRIVILEGES;
|
||||
mysql> quit
|
||||
|
||||
|
||||
2. Create all tables (You need to be in the icinga2-web folder)
|
||||
|
@ -80,8 +80,18 @@ create all database tables. You will find the installation guides for the differ
|
|||
2. Create all tables (You need to be in the icinga2-web folder)
|
||||
|
||||
|
||||
bash$ psql -d icingaweb -a -f etc/schema/users.mysql.sql
|
||||
bash$ psql -U icingaweb -a -f etc/schema/users.pgsql.sql
|
||||
|
||||
3. Enable trust authentication on localhost
|
||||
|
||||
Add the following lines to your pg_hba.conf (etc/postgresql/X.x/main/pg_hba.conf under debian, /var/lib/pgsql/data/pg_hba.conf for Redhat/Fedora)
|
||||
to enable trust authentication for the icingaweb user when connecting from the localhost.
|
||||
|
||||
local icingaweb icingaweb trust
|
||||
host icingaweb icingaweb 127.0.0.1/32 trust
|
||||
host icingaweb icingaweb ::1/128 trust
|
||||
|
||||
And restart your databse ('service postgresql restart' or '/etc/init.d/postgresql-X.x reload')
|
||||
|
||||
Quick and Dirty
|
||||
----------------
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
create table user (
|
||||
create table account (
|
||||
user_name varchar(255) NOT NULL,
|
||||
first_name varchar(255),
|
||||
last_name varchar(255),
|
||||
|
@ -15,7 +15,7 @@ create table user (
|
|||
* user: icingaadmin
|
||||
* password: icinga
|
||||
*/
|
||||
INSERT INTO user (
|
||||
INSERT INTO account (
|
||||
user_name,
|
||||
salt,
|
||||
password,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
create table "user" (
|
||||
create table "account" (
|
||||
user_name varchar(255) NOT NULL,
|
||||
first_name varchar(255),
|
||||
last_name varchar(255),
|
||||
|
@ -15,7 +15,7 @@ create table "user" (
|
|||
* user: icingaadmin
|
||||
* password: icinga
|
||||
*/
|
||||
INSERT INTO "user" (
|
||||
INSERT INTO "account" (
|
||||
user_name,
|
||||
salt,
|
||||
password,
|
||||
|
|
|
@ -33,7 +33,7 @@ use Icinga\Authentication\User as User;
|
|||
use Icinga\Authentication\UserBackend;
|
||||
use Icinga\Authentication\Credentials;
|
||||
use Icinga\Authentication;
|
||||
|
||||
use Icinga\Application\Logger;
|
||||
|
||||
/**
|
||||
* Authenticates users using a sql db as backend.
|
||||
|
@ -41,26 +41,41 @@ use Icinga\Authentication;
|
|||
*/
|
||||
class DbUserBackend implements UserBackend {
|
||||
|
||||
private $db;
|
||||
/**
|
||||
* The database connection that will be used for fetching users
|
||||
*
|
||||
* @var \Zend_Db
|
||||
*/
|
||||
private $db = null;
|
||||
|
||||
/**
|
||||
* The name of the user table as provided by the configuration
|
||||
*
|
||||
* @var String
|
||||
*/
|
||||
private $userTable;
|
||||
|
||||
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";
|
||||
/**
|
||||
* 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';
|
||||
|
||||
/*
|
||||
* maps the configuration dbtypes to the corresponding Zend-PDOs
|
||||
*/
|
||||
private $dbTypeMap = Array(
|
||||
"mysql" => "PDO_MYSQL",
|
||||
"pgsql" => "PDO_PGSQL"
|
||||
'mysql' => 'PDO_MYSQL',
|
||||
'pgsql' => 'PDO_PGSQL'
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -72,21 +87,26 @@ class DbUserBackend implements UserBackend {
|
|||
{
|
||||
$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 = \Zend_Db::factory(
|
||||
$this->dbTypeMap[$config->dbtype],
|
||||
array(
|
||||
'host' => $config->host,
|
||||
'username' => $config->user,
|
||||
'password' => $config->password,
|
||||
'dbname' => $config->db
|
||||
));
|
||||
/*
|
||||
* 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 the connection settings
|
||||
*/
|
||||
$this->db->getConnection();
|
||||
$this->db->select()->from($this->userTable,new \Zend_Db_Expr("TRUE"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,6 +117,10 @@ class DbUserBackend implements UserBackend {
|
|||
*/
|
||||
public function hasUsername(Credentials $credential)
|
||||
{
|
||||
if ($this->db === null) {
|
||||
Logger::warn('Ignoring hasUsername in database as no connection is available');
|
||||
return false;
|
||||
}
|
||||
$user = $this->getUserByName($credential->getUsername());
|
||||
return !empty($user);
|
||||
}
|
||||
|
@ -109,12 +133,16 @@ class DbUserBackend implements UserBackend {
|
|||
*/
|
||||
public function authenticate(Credentials $credential)
|
||||
{
|
||||
if ($this->db === null) {
|
||||
Logger::warn('Ignoring database authentication as no connection is available');
|
||||
return null;
|
||||
}
|
||||
$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($this->PASSWORD_COLUMN. ' = ?',hash_hmac('sha256',
|
||||
$this->getUserSalt($credential->getUsername()),
|
||||
$credential->getPassword())
|
||||
)
|
||||
|
@ -137,7 +165,7 @@ class DbUserBackend implements UserBackend {
|
|||
$this->db->update(
|
||||
$this->userTable,
|
||||
array(
|
||||
$this->LAST_LOGIN_COLUMN => new \Zend_Db_Expr("NOW()")
|
||||
$this->LAST_LOGIN_COLUMN => new \Zend_Db_Expr('NOW()')
|
||||
),
|
||||
$this->USER_NAME_COLUMN.' = '.$this->db->quoteInto('?',$username));
|
||||
}
|
||||
|
@ -166,16 +194,25 @@ class DbUserBackend implements UserBackend {
|
|||
*/
|
||||
private function getUserByName($username)
|
||||
{
|
||||
$this->db->getConnection();
|
||||
$res = $this->db->
|
||||
select()->from($this->userTable)
|
||||
->where($this->USER_NAME_COLUMN.' = ?',$username)
|
||||
->where($this->ACTIVE_COLUMN.' = ?',true)
|
||||
->query()->fetch();
|
||||
if (empty($res)) {
|
||||
if ($this->db === null) {
|
||||
Logger::warn('Ignoring getUserByName as no database connection is available');
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
$this->db->getConnection();
|
||||
$res = $this->db->
|
||||
select()->from($this->userTable)
|
||||
->where($this->USER_NAME_COLUMN.' = ?',$username)
|
||||
->where($this->ACTIVE_COLUMN.' = ?',true)
|
||||
->query()->fetch();
|
||||
if (empty($res)) {
|
||||
return null;
|
||||
}
|
||||
return $this->createUserFromResult($res);
|
||||
} catch (\Zend_Db_Statement_Exception $exc) {
|
||||
Logger::error("Could not fetch users from db : %s ", $exc->getMessage());
|
||||
return null;
|
||||
}
|
||||
return $this->createUserFromResult($res);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,14 +8,14 @@ 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");
|
||||
require_once("../../library/Icinga/Protocol/Ldap/Exception.php");
|
||||
require_once("../../library/Icinga/Application/Config.php");
|
||||
require_once("../../library/Icinga/Authentication/Credentials.php");
|
||||
require_once("../../library/Icinga/Authentication/Backend/DbUserBackend.php");
|
||||
require_once("../../library/Icinga/Authentication/User.php");
|
||||
require_once('Zend/Config/Ini.php');
|
||||
require_once('Zend/Db.php');
|
||||
require_once('../../library/Icinga/Authentication/UserBackend.php');
|
||||
require_once('../../library/Icinga/Protocol/Ldap/Exception.php');
|
||||
require_once('../../library/Icinga/Application/Config.php');
|
||||
require_once('../../library/Icinga/Authentication/Credentials.php');
|
||||
require_once('../../library/Icinga/Authentication/Backend/DbUserBackend.php');
|
||||
require_once('../../library/Icinga/Authentication/User.php');
|
||||
|
||||
use Icinga\Authentication\Backend\DbUserBackend;
|
||||
use Icinga\Util\Crypto;
|
||||
|
@ -33,21 +33,21 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
|
||||
private $dbUserBackend;
|
||||
private $db;
|
||||
private $testTable = "icinga_users_test";
|
||||
private $testDatabase = "icinga_unittest";
|
||||
private $testTable = 'account';
|
||||
private $testDatabase = 'icinga_unittest';
|
||||
|
||||
/*
|
||||
* Must be identical with the column names defined in DbUserBackend
|
||||
*/
|
||||
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";
|
||||
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';
|
||||
|
||||
private $users;
|
||||
private $mysql;
|
||||
|
@ -67,9 +67,9 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
private function getBackendConfig()
|
||||
{
|
||||
$config = new \stdClass();
|
||||
$config->host = "127.0.0.1";
|
||||
$config->user = "icinga_unittest";
|
||||
$config->password= "icinga_unittest";
|
||||
$config->host = '127.0.0.1';
|
||||
$config->user = 'icinga_unittest';
|
||||
$config->password= 'icinga_unittest';
|
||||
$config->table = $this->testTable;
|
||||
$config->db = $this->testDatabase;
|
||||
return $config;
|
||||
|
@ -78,7 +78,7 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
/**
|
||||
* Create a backend with the given database type
|
||||
*
|
||||
* @param $dbType The database type as a string, like "mysql" or "pgsql".
|
||||
* @param $dbType The database type as a string, like 'mysql' or 'pgsql'.
|
||||
* @return DbUserBackend|null
|
||||
*/
|
||||
private function createBackend($dbType)
|
||||
|
@ -90,7 +90,7 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
$this->setUpDb($db);
|
||||
return new DbUserBackend($config);
|
||||
} catch(\Exception $e) {
|
||||
echo "CREATE_BACKEND_ERROR:".$e->getMessage();
|
||||
echo 'CREATE_BACKEND_ERROR:'.$e->getMessage();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -120,8 +120,8 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
$this->ACTIVE_COLUMN => 0
|
||||
)
|
||||
);
|
||||
$this->mysql = $this->createBackend("mysql");
|
||||
$this->pgsql = $this->createBackend("pgsql");
|
||||
$this->mysql = $this->createBackend('mysql');
|
||||
$this->pgsql = $this->createBackend('pgsql');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,7 +134,7 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
$this->runBackendUsername($this->pgsql);
|
||||
}
|
||||
else{
|
||||
echo "\nSKIPPING PGSQL TEST...\n";
|
||||
echo '\nSKIPPING PGSQL TEST...\n';
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
$this->runBackendUsername($this->mysql);
|
||||
}
|
||||
else{
|
||||
echo "\nSKIPPING MYSQL TEST...\n";
|
||||
echo '\nSKIPPING MYSQL TEST...\n';
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
/**
|
||||
* Create a database with the given config and type
|
||||
*
|
||||
* @param $dbtype The database type as a string, like "mysql" or "pgsql".
|
||||
* @param $dbtype The database type as a string, like 'mysql' or 'pgsql'.
|
||||
* @param $config The configuration-object.
|
||||
* @return mixed
|
||||
*/
|
||||
|
@ -168,7 +168,7 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
'host' => $config->host,
|
||||
'username' => $config->user,
|
||||
'password' => $config->password,
|
||||
"dbname" => "icinga_unittest"
|
||||
'dbname' => 'icinga_unittest'
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -178,11 +178,11 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
public function tearDown()
|
||||
{
|
||||
try{
|
||||
$db = $this->createDb("mysql",$this->getBackendConfig());
|
||||
$db = $this->createDb('mysql',$this->getBackendConfig());
|
||||
$this->tearDownDb($db);
|
||||
} catch(\Exception $e) { }
|
||||
try {
|
||||
$db = $this->createDb("pgsql",$this->getBackendConfig());
|
||||
$db = $this->createDb('pgsql',$this->getBackendConfig());
|
||||
$this->tearDownDb($db);
|
||||
} catch(\Exception $e) { }
|
||||
}
|
||||
|
@ -204,6 +204,11 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
*/
|
||||
private function setUpDb($db)
|
||||
{
|
||||
try {
|
||||
$this->tearDownDb($db);
|
||||
} catch (\Exception $e) {
|
||||
// if no database exists, an exception will be thrown
|
||||
}
|
||||
$db->exec('CREATE TABLE '.$this->testTable.' (
|
||||
'.$this->USER_NAME_COLUMN.' varchar(255) NOT NULL,
|
||||
'.$this->FIRST_NAME_COLUMN.' varchar(255),
|
||||
|
@ -220,7 +225,7 @@ class DbUserBackendTest extends \PHPUnit_Framework_TestCase {
|
|||
$usr = $this->users[$i];
|
||||
$data = Array(
|
||||
$this->USER_NAME_COLUMN => $usr[$this->USER_NAME_COLUMN],
|
||||
$this->PASSWORD_COLUMN => hash_hmac("sha256",
|
||||
$this->PASSWORD_COLUMN => hash_hmac('sha256',
|
||||
$usr[$this->SALT_COLUMN],
|
||||
$usr[$this->PASSWORD_COLUMN]
|
||||
),
|
||||
|
|
Loading…
Reference in New Issue