Provide a cleaner interface for the Authentication Backends

refs #4786
This commit is contained in:
Matthias Jentsch 2013-11-06 14:49:16 +01:00
parent 59d4baff0b
commit bd38e998d7
6 changed files with 64 additions and 42 deletions

View File

@ -106,20 +106,27 @@ class DbUserBackend implements UserBackend
/** /**
* Create a new DbUserBackend * Create a new DbUserBackend
* *
* @param DbConnection $resource The db connection to use for the authentication.
* @param Zend_Config $config The configuration for this authentication backend. * @param Zend_Config $config The configuration for this authentication backend.
* 'resource' => The name of the resource to use, or an actual
* instance of Zend_Db_Adapter_Abstract
* 'name' => The name of this authentication backend
* *
* @throws Exception When connection to the resource is not possible. * @throws Exception When the connection to the resource is not possible.
*/ */
public function __construct(DbConnection $resource = null, Zend_Config $config) public function __construct(Zend_Config $config)
{ {
if (!isset($config->resource)) {
throw new ConfigurationError('An authentication backend must provide a resource.');
}
$this->name = $config->name; $this->name = $config->name;
if ($config->resource instanceof Zend_Db_Adapter_Abstract) { if ($config->resource instanceof Zend_Db_Adapter_Abstract) {
$this->db = $config->resource; $this->db = $config->resource;
} else { } else {
$resource = ResourceFactory::createResource(ResourceFactory::getResourceConfig($config->resource));
$this->db = $resource->getConnection(); $this->db = $resource->getConnection();
} }
// will throw an exception when connecting is not possible
// test the connection
$this->db->getConnection(); $this->db->getConnection();
} }

View File

@ -29,6 +29,7 @@
namespace Icinga\Authentication\Backend; namespace Icinga\Authentication\Backend;
use Icinga\Data\ResourceFactory;
use \stdClass; use \stdClass;
use \Zend_Config; use \Zend_Config;
use \Icinga\User; use \Icinga\User;
@ -37,6 +38,7 @@ use \Icinga\Authentication\Credential;
use \Icinga\Protocol\Ldap; use \Icinga\Protocol\Ldap;
use \Icinga\Protocol\Ldap\Connection as LdapConnection; use \Icinga\Protocol\Ldap\Connection as LdapConnection;
use \Icinga\Application\Config as IcingaConfig; use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Exception\ConfigurationError;
/** /**
* User authentication backend * User authentication backend
@ -65,21 +67,32 @@ class LdapUserBackend implements UserBackend
private $name; private $name;
/** /**
* Create new Ldap User backend * Create a new LdapUserBackend
* *
* @param Zend_Config $connection Connection to use * @param Zend_Config $config The configuration for this authentication backend.
* @param Zend_Config $config Configuration for authentication * 'resource' => The name of the resource to use, or an actual
* instance of \Icinga\Protocol\Ldap\Connection.
* 'name' => The name of this authentication backend.
* *
* @throws Exception When connection to the resource is not possible. * @throws \Exception When the connection to the resource is not possible.
*/ */
public function __construct(LdapConnection $connection, Zend_Config $config) public function __construct(Zend_Config $config)
{ {
$this->connection = $connection; if (!isset($config->resource)) {
throw new ConfigurationError('An authentication backend must provide a resource.');
}
$this->config = $config; $this->config = $config;
$this->name = $config->name; $this->name = $config->name;
if ($config->resource instanceof LdapConnection) {
$this->connection = $config->resource;
} else {
$this->connection = ResourceFactory::createResource(
ResourceFactory::getResourceConfig($config->resource)
);
}
// will throw an exception, when the connection is not possible. // will throw an exception, when the connection is not possible.
$connection->connect(); $this->connection->connect();
} }
/** /**

View File

@ -186,7 +186,6 @@ class Manager
{ {
$target = ucwords(strtolower($backendConfig->target)); $target = ucwords(strtolower($backendConfig->target));
$name = $backendConfig->name; $name = $backendConfig->name;
// TODO: implement support for groups (#4624) and remove OR-Clause // TODO: implement support for groups (#4624) and remove OR-Clause
if ((!$target || strtolower($target) != "user") && !$backendConfig->class) { if ((!$target || strtolower($target) != "user") && !$backendConfig->class) {
Logger::warn('AuthManager: Backend "%s" has no target configuration. (e.g. target=user|group)', $name); Logger::warn('AuthManager: Backend "%s" has no target configuration. (e.g. target=user|group)', $name);
@ -194,24 +193,22 @@ class Manager
} }
try { try {
if (isset($backendConfig->class)) { if (isset($backendConfig->class)) {
// use custom backend class, this is only useful for testing // use a custom backend class, this is probably only useful for testing
if (!class_exists($backendConfig->class)) { if (!class_exists($backendConfig->class)) {
Logger::error('AuthManager: Class not found (%s) for backend %s', $backendConfig->class, $name); Logger::error('AuthManager: Class not found (%s) for backend %s', $backendConfig->class, $name);
return null; return null;
} }
$class = $backendConfig->class; $class = $backendConfig->class;
return new $class($backendConfig); return new $class($backendConfig);
}
} else { switch (ResourceFactory::getResourceConfig($backendConfig->resource)->type) {
$resource = ResourceFactory::createResource(ResourceFactory::getResourceConfig($backendConfig->resource)); case 'db':
if ($resource instanceof DbConnection) { return new DbUserBackend($backendConfig);
return new DbUserBackend($resource, $backendConfig); case 'ldap':
} else if ($resource instanceof LdapConnection) { return new LdapUserBackend($backendConfig);
return new LdapUserBackend($resource, $backendConfig); default:
} else { Logger::warn('AuthManager: Resource type ' . $backendConfig->type . ' not available.');
Logger::warn('AuthManager: Resource class ' . get_class($resource) . ' cannot be used as backend.');
}
} }
} catch (\Exception $e) { } catch (\Exception $e) {
Logger::warn('AuthManager: Not able to create backend. Exception was thrown: %s', $e->getMessage()); Logger::warn('AuthManager: Not able to create backend. Exception was thrown: %s', $e->getMessage());

View File

@ -123,7 +123,6 @@ class Connection
$this->bind_pw = $config->bind_pw; $this->bind_pw = $config->bind_pw;
$this->root_dn = $config->root_dn; $this->root_dn = $config->root_dn;
$this->port = $config->get('port', $this->port); $this->port = $config->get('port', $this->port);
} }
public function getDN() public function getDN()

View File

@ -130,7 +130,7 @@ class DbUserBackendTest extends BaseTestCase
public function testCorrectUserLoginForPgsql($db) public function testCorrectUserLoginForPgsql($db)
{ {
$this->setupDbProvider($db); $this->setupDbProvider($db);
$backend = new DbUserBackend(null, $this->createDbBackendConfig($db)); $backend = new DbUserBackend($this->createDbBackendConfig($db));
$this->runBackendAuthentication($backend); $this->runBackendAuthentication($backend);
$this->runBackendUsername($backend); $this->runBackendUsername($backend);
} }
@ -143,7 +143,7 @@ class DbUserBackendTest extends BaseTestCase
public function testCorrectUserLoginForMySQL($db) public function testCorrectUserLoginForMySQL($db)
{ {
$this->setupDbProvider($db); $this->setupDbProvider($db);
$backend = new DbUserBackend(null, $this->createDbBackendConfig($db)); $backend = new DbUserBackend($this->createDbBackendConfig($db));
$this->runBackendAuthentication($backend); $this->runBackendAuthentication($backend);
$this->runBackendUsername($backend); $this->runBackendUsername($backend);
} }
@ -280,7 +280,7 @@ class DbUserBackendTest extends BaseTestCase
$this->setupDbProvider($db); $this->setupDbProvider($db);
$testName = 'test-name-123123'; $testName = 'test-name-123123';
$backend = new DbUserBackend(null, $this->createDbBackendConfig($db, $testName)); $backend = new DbUserBackend($this->createDbBackendConfig($db, $testName));
$this->assertSame($testName, $backend->getName()); $this->assertSame($testName, $backend->getName());
} }
@ -292,7 +292,7 @@ class DbUserBackendTest extends BaseTestCase
{ {
$this->setupDbProvider($db); $this->setupDbProvider($db);
$testName = 'test-name-123123'; $testName = 'test-name-123123';
$backend = new DbUserBackend(null, $this->createDbBackendConfig($db, $testName)); $backend = new DbUserBackend($this->createDbBackendConfig($db, $testName));
$this->assertGreaterThan(0, $backend->getUserCount()); $this->assertGreaterThan(0, $backend->getUserCount());
} }
@ -304,7 +304,7 @@ class DbUserBackendTest extends BaseTestCase
{ {
$this->setupDbProvider($db); $this->setupDbProvider($db);
$testName = 'test-name-123123'; $testName = 'test-name-123123';
$backend = new DbUserBackend(null, $this->createDbBackendConfig($db, $testName)); $backend = new DbUserBackend($this->createDbBackendConfig($db, $testName));
$this->assertGreaterThan(0, $backend->getUserCount()); $this->assertGreaterThan(0, $backend->getUserCount());
} }

View File

@ -48,7 +48,7 @@ require_once BaseTestCase::$libDir . '/Authentication/Backend/LdapUserBackend.ph
use \Exception; use \Exception;
use \Zend_Config; use \Zend_Config;
use Icinga\Authentication\Backend\LdapUserBackend; use Icinga\Authentication\Backend\LdapUserBackend;
use Icinga\Protocol\Ldap\Connection; use Icinga\Protocol\Ldap\Connection as LdapConnection;
/** /**
* *
@ -161,22 +161,31 @@ class LdapUserBackendTest extends BaseTestCase
ldap_close($conn); ldap_close($conn);
} }
/**
* Create a backend config and initialise the LdapConnection to the testing backend manually,
* to prevent the LdapUserBackend from calling the unitialised ResourceFactory
*
* @return Zend_Config The authentication backend configuration
*/
private function createBackendConfig() private function createBackendConfig()
{ {
$config = new Zend_Config( $resourceConfig = new Zend_Config(
array( array(
'backend' => 'ldap',
'target' => 'user',
'hostname' => 'localhost', 'hostname' => 'localhost',
'root_dn' => 'ou=icinga-unittest,dc=icinga,dc=org', 'root_dn' => 'ou=icinga-unittest,dc=icinga,dc=org',
'bind_dn' => 'cn=admin,cn=config', 'bind_dn' => 'cn=admin,cn=config',
'bind_pw' => 'admin', 'bind_pw' => 'admin'
)
);
$backendConfig = new Zend_Config(
array(
'resource' => new LdapConnection($resourceConfig),
'target' => 'user',
'user_class' => 'inetOrgPerson', 'user_class' => 'inetOrgPerson',
'user_name_attribute' => 'uid' 'user_name_attribute' => 'uid'
) )
); );
return $backendConfig;
return $config;
} }
/** /**
@ -184,8 +193,7 @@ class LdapUserBackendTest extends BaseTestCase
**/ **/
public function testHasUsername() public function testHasUsername()
{ {
$config = $this->createBackendConfig(); $backend = new LdapUserBackend($this->createBackendConfig());
$backend = new LdapUserBackend(new Connection($config), $config);
$this->assertTrue($backend->hasUsername(new Credential('jwoe'))); $this->assertTrue($backend->hasUsername(new Credential('jwoe')));
$this->assertTrue($backend->hasUsername(new Credential('rmiles'))); $this->assertTrue($backend->hasUsername(new Credential('rmiles')));
$this->assertFalse($backend->hasUsername(new Credential('DoesNotExist'))); $this->assertFalse($backend->hasUsername(new Credential('DoesNotExist')));
@ -196,8 +204,7 @@ class LdapUserBackendTest extends BaseTestCase
*/ */
public function testAuthenticate() public function testAuthenticate()
{ {
$config = $this->createBackendConfig(); $backend = new LdapUserBackend($this->createBackendConfig());
$backend = new LdapUserBackend(new Connection($config), $config);
$this->assertInstanceOf( $this->assertInstanceOf(
'\Icinga\User', '\Icinga\User',
@ -220,8 +227,7 @@ class LdapUserBackendTest extends BaseTestCase
*/ */
public function testAuthenticateUnknownUser() public function testAuthenticateUnknownUser()
{ {
$config = $this->createBackendConfig(); $backend = new LdapUserBackend($this->createBackendConfig());
$backend = new LdapUserBackend(new Connection($config), $config);
$this->assertFalse($backend->authenticate(new Credential('unknown123', 'passunknown123'))); $this->assertFalse($backend->authenticate(new Credential('unknown123', 'passunknown123')));
} }
} }