Skip to content

Commit

Permalink
Add db and ldap validation
Browse files Browse the repository at this point in the history
refs #3761
  • Loading branch information
Johannes Meyer committed Oct 9, 2013
1 parent 5e8e210 commit 135817f
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 14 deletions.
4 changes: 1 addition & 3 deletions install/application/controllers/IndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ private function getDatabaseDetails($session)
* Validate the given database details
*
* @return bool Whether the details are valid
* @todo Validate db connection
*/
private function validateDatabaseDetails($session)
{
Expand Down Expand Up @@ -170,7 +169,6 @@ private function getAuthenticationDetails($session)
* Validate the given authentication details
*
* @return bool Whether the details are valid
* @todo Validate ldap
*/
private function validateAuthenticationDetails($session)
{
Expand Down Expand Up @@ -205,7 +203,7 @@ private function getBackendDetails($session)
* Validate the given backend details
*
* @return bool Whether the details are valid
* @todo Validate ido, dat and live connectivity
* @todo Validate dat and live connectivity
*/
private function validateBackendDetails($session)
{
Expand Down
34 changes: 34 additions & 0 deletions install/application/forms/AuthConfigForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

namespace Icinga\Installer\Pages;

use \Zend_Config;
use \Icinga\Installer\Validators\PasswordValidator;

/**
Expand Down Expand Up @@ -165,6 +166,39 @@ public function create()
$this->setSubmitLabel('Continue');
}

/**
* Validate the form and check if the provided LDAP details are correct
*
* @param array $data The submitted details
* @return bool Whether the form and the details are valid
*/
public function isValid($data)
{
$isValid = parent::isValid($data);

if ($isValid && isset($data['auth_use_ldap']) && $data['auth_use_ldap']) {
$message = $this->checkLdapAuthentication(
new Zend_Config(
array(
'hostname' => $data['auth_ldap_hostname'],
'root_dn' => $data['auth_ldap_root_dn'],
'bind_dn' => $data['auth_ldap_bind_dn'],
'bind_pw' => $data['auth_ldap_bind_pw'],
'user_class' => $data['auth_ldap_user_class'],
'user_name_attribute' => $data['auth_ldap_user_name_attributes']
)
)
);
$isValid = $message === 'OK';

if (!$isValid) {
$this->addErrorNote('Invalid LDAP authentication details: ' . $message, 9);
}
}

return $isValid;
}

/**
* Return the provided details
*
Expand Down
40 changes: 38 additions & 2 deletions install/application/forms/BackendConfigForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

namespace Icinga\Installer\Pages;

use \Zend_Config;

/**
* Wizard-page that prompts the user to configure the authentication
*/
Expand Down Expand Up @@ -61,13 +63,13 @@ public function create()
'multiOptions' => array_merge(
$this->getResources(),
array(
-1 => '... Other existing database'
'other' => '... Other existing database'
)
)
)
);

if ($this->getRequest()->getPost('backend_selection') == 1) {
if ($this->getRequest()->getPost('backend_selection') === 'other') {
$this->addNote('Connection settings for an existing database', 3);

$this->addElement(
Expand Down Expand Up @@ -233,6 +235,40 @@ public function create()
$this->setSubmitLabel('Continue');
}

/**
* Validate the form and check if the provided database details are correct
*
* @param array $data The submitted details
* @return bool Whether the form and the details are valid
*/
public function isValid($data)
{
$isValid = parent::isValid($data);

if ($isValid && $data['backend_selection'] === 'other') {
$message = $this->checkDatabaseConnection(
new Zend_Config(
array(
'type' => 'db',
'db' => $data['backend_provider'],
'dbname' => $data['backend_dbname'],
'host' => $data['backend_host'],
'port' => $data['backend_port'],
'username' => $data['backend_dbuser'],
'password' => $data['backend_dbpass']
)
)
);
$isValid = $message === 'OK';

if (!$isValid) {
$this->addErrorNote('Database connection could not be established: ' . $message, 5);
}
}

return $isValid;
}

/**
* Return the provided details
*
Expand Down
35 changes: 35 additions & 0 deletions install/application/forms/DbConfigForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

namespace Icinga\Installer\Pages;

use \Zend_Config;
use \Icinga\Installer\Validators\PasswordValidator;

/**
Expand Down Expand Up @@ -134,6 +135,40 @@ public function create()
$this->setSubmitLabel('Continue');
}

/**
* Validate the form and check if the provided database details are correct
*
* @param array $data The submitted details
* @return bool Whether the form and the details are valid
*/
public function isValid($data)
{
$isValid = parent::isValid($data);

if ($isValid) {
$message = $this->checkDatabaseConnection(
new Zend_Config(
array(
'type' => 'db',
'db' => $data['db_provider'],
'dbname' => $data['db_name'],
'host' => $data['db_host'],
'port' => $data['db_port'],
'username' => $data['db_username'],
'password' => $data['db_password']
)
)
);
$isValid = $message === 'OK';

if (!$isValid) {
$this->addErrorNote('Database connection could not be established: ' . $message, 2);
}
}

return $isValid;
}

/**
* Return the provided details
*
Expand Down
82 changes: 81 additions & 1 deletion install/application/forms/WizardForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@

namespace Icinga\Installer\Pages;

require_once 'Zend/Db.php';
require_once 'Zend/Form.php';
require_once 'Zend/Config.php';
require_once 'Zend/Form/Element/Xhtml.php';
require_once 'Zend/Form/Element/Submit.php';
require_once 'Zend/Form/Decorator/Abstract.php';
Expand All @@ -37,10 +39,22 @@
require_once realpath(__DIR__ . '/../../../library/Icinga/Web/Form/Element/Note.php');
require_once realpath(__DIR__ . '/../../../library/Icinga/Web/Form/Decorator/HelpText.php');
require_once realpath(__DIR__ . '/../../../library/Icinga/Web/Form/Decorator/BootstrapForm.php');
require_once realpath(__DIR__ . '/../../../library/Icinga/Util/ConfigAwareFactory.php');
require_once realpath(__DIR__ . '/../../../library/Icinga/Application/DbAdapterFactory.php');
require_once realpath(__DIR__ . '/../../../library/Icinga/Authentication/UserBackend.php');
require_once realpath(__DIR__ . '/../../../library/Icinga/Authentication/Backend/LdapUserBackend.php');
require_once realpath(__DIR__ . '/../../../library/Icinga/Protocol/Ldap/Connection.php');
require_once realpath(__DIR__ . '/../../../library/Icinga/Protocol/Ldap/LdapUtils.php');
require_once realpath(__DIR__ . '/../../../library/Icinga/Protocol/Ldap/Query.php');

use \Exception;
use \Zend_Config;
use \Zend_Session_Namespace;
use \Icinga\Web\Form;
use \Icinga\Web\Form\Element\Note;
use \Icinga\Installer\Report;
use \Zend_Session_Namespace;
use \Icinga\Application\DbAdapterFactory;
use \Icinga\Authentication\Backend\LdapUserBackend;

/**
* Base form for every wizard page
Expand All @@ -61,6 +75,13 @@ class WizardForm extends Form
*/
private $session;

/**
* Last used error note id
*
* @var int
*/
private $lastErrorNoteId = 0;

/**
* Set the system report to use
*
Expand Down Expand Up @@ -201,4 +222,63 @@ public function getResources()
$this->getSession()->databaseDetails['db_resource']
);
}

/**
* Add an error note at a specific location to the form
*
* @param string $message The message to display
* @param int $position Where to display the message
*/
public function addErrorNote($message, $position)
{
$this->addElement(
new Note(
array(
'escape' => true,
'order' => $position + 1, // +1 due to the hidden progress element
'name' => sprintf('error_note_%s', $this->lastErrorNoteId++),
'value' => sprintf('<span style="color:red">%s</span>', $message)
)
)
);
}

/**
* Check whether a database connection can be established
*
* @param Zend_Config $config The database connection details to use
* @return string OK in case a connection has been established, otherwise the error message
*/
public function checkDatabaseConnection(Zend_Config $config)
{
$db = DbAdapterFactory::createDbAdapter($config);

try {
$db->getConnection();
} catch (Exception $error) {
$errorMessage = $error->getMessage();
}

$succeeded = $db->isConnected();
$db->closeConnection();
return $succeeded ? 'OK' : $errorMessage;
}

/**
* Check whether it is possible to authenticate using LDAP with the given connection details
*
* @param Zend_Config $config The LDAP connection details to use
* @return string OK in case the connection was successful, otherwise the error message
*/
public function checkLdapAuthentication(Zend_Config $config)
{
try {
$conn = new LdapUserBackend($config);
$conn->getUserCount();
} catch (Exception $error) {
return $error->getMessage();
}

return 'OK';
}
}
16 changes: 8 additions & 8 deletions library/Icinga/Protocol/Ldap/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
*/
namespace Icinga\Protocol\Ldap;

use Icinga\Application\Platform;
use \Exception;
use \Icinga\Application\Platform;
use \Icinga\Application\Config;
use Icinga\Application\Logger as Log;
use \Icinga\Application\Logger as Log;

/**
* Backend class managing all the LDAP stuff for you.
Expand Down Expand Up @@ -128,7 +129,7 @@ public function fetchDN($query, $fields = array())
{
$rows = $this->fetchAll($query, $fields);
if (count($rows) !== 1) {
throw new \Exception(
throw new Exception(
sprintf(
'Cannot fetch single DN for %s',
$query
Expand Down Expand Up @@ -222,15 +223,14 @@ protected function runQuery($query, $fields)
if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) {
return false;
}
throw new \Exception(
throw new Exception(
sprintf(
'LDAP query "%s" (root %s) failed: %s',
$query,
$this->root_dn,
ldap_error($this->ds)
)
);
die('Query failed');
}
$list = array();
if ($query instanceof Query) {
Expand Down Expand Up @@ -298,15 +298,15 @@ protected function prepareNewConnection()
Log::debug('LDAP STARTTLS succeeded');
} else {
Log::debug('LDAP STARTTLS failed: %s', ldap_error($ds));
throw new \Exception(
throw new Exception(
sprintf(
'LDAP STARTTLS failed: %s',
ldap_error($ds)
)
);
}
} elseif ($force_tls) {
throw new \Exception(
throw new Exception(
sprintf(
'TLS is required but not announced by %s',
$this->host_name
Expand Down Expand Up @@ -448,7 +448,7 @@ public function connect()
$r = @ldap_bind($this->ds, $this->bind_dn, $this->bind_pw);

if (! $r) {
throw new \Exception(
throw new Exception(
sprintf(
'LDAP connection to %s:%s (%s / %s) failed: %s',
$this->hostname,
Expand Down

0 comments on commit 135817f

Please sign in to comment.