Skip to content

Commit

Permalink
Add ldap autodiscovery to installation wizard
Browse files Browse the repository at this point in the history
  • Loading branch information
majentsch committed Oct 8, 2014
1 parent d54bfdd commit 853b00f
Show file tree
Hide file tree
Showing 12 changed files with 564 additions and 8 deletions.
12 changes: 11 additions & 1 deletion application/forms/Config/Authentication/LdapBackendForm.php
Expand Up @@ -70,6 +70,15 @@ public function createElements(array $formData)
: array()
)
);
$this->addElement(
'text',
'base_dn',
array(
'required' => true,
'label' => t('Bind DN'),
'description' => t('The path where users can be found on the ldap server')
)
);
$this->addElement(
'text',
'user_class',
Expand Down Expand Up @@ -127,7 +136,8 @@ public static function isValidAuthenticationBackend(Form $form)
$ldapUserBackend = new LdapUserBackend(
ResourceFactory::createResource($form->getResourceConfig()),
$form->getElement('user_class')->getValue(),
$form->getElement('user_name_attribute')->getValue()
$form->getElement('user_name_attribute')->getValue(),
$form->getElement('base_dn')->getValue()
);
$ldapUserBackend->assertAuthenticationPossible();
} catch (AuthenticationException $e) {
Expand Down
2 changes: 1 addition & 1 deletion application/forms/Config/Resource/LdapResourceForm.php
Expand Up @@ -65,7 +65,7 @@ public function createElements(array $formData)
array(
'required' => true,
'label' => t('Root DN'),
'description' => t('The path where users can be found on the ldap server')
'description' => t('Only the root and its child nodes will be accessible on this resource.')
)
);
$this->addElement(
Expand Down
214 changes: 214 additions & 0 deletions application/forms/LdapDiscoveryForm.php
@@ -0,0 +1,214 @@
<?php

namespace Icinga\Form;

use Icinga\Application\Config;
use Icinga\Logger\Logger;
use Icinga\Protocol\Ldap\Exception as LdapException;
use Icinga\Protocol\Ldap\Connection;
use Icinga\Web\Request;
use Icinga\Protocol\Dns;
use Icinga\Web\Form\Element\Note;
use Icinga\Web\Form;

/**
* Form class for application-wide and logging specific settings
*/
class LdapDiscoveryForm extends Form
{
/**
* The discovered server settings
*
* @var array
*/
private $capabilities = null;

/**
* The discovered root_dn
*
* @var null
*/
private $namingContext = null;

/**
* The working domain name
*
* @var null
*/
private $domain = null;

/**
* The working port name
*
* @var int
*/
private $port = 389;

/**
* Initialize this page
*/
public function init()
{
$this->setName('form_ldap_discovery');
}

/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
$this->addElement(
'text',
'domain',
array(
'required' => true,
'label' => t('Search Domain'),
'description' => t('Search this domain for records of available servers.'),
)
);

if (false) {
$this->addElement(
new Note(
'additional_description',
array(
'value' => t('No Ldap servers found on this domain.'
. ' You can try to specify host and port and try again, or just skip this step and '
. 'configure the server manually.'
)
)
)
);
$this->addElement(
'text',
'hostname',
array(
'required' => false,
'label' => t('Host'),
'description' => t('IP or host name to search.'),
)
);

$this->addElement(
'text',
'port',
array(
'required' => false,
'label' => t('Port'),
'description' => t('Port', 389),
)
);
}
return $this;
}

public function isValid($data)
{
if (false === parent::isValid($data)) {
return false;
}
if ($this->discover($this->getValue('domain'))) {
return true;
}
return true;
}


private function discover($domain)
{
// Attempt 1: Connect to the domain directly
if ($this->discoverCapabilities(array(
'hostname' => $domain,
'port' => 389)
)) {
return true;
}

// Attempt 2: Discover all available ldap dns records and connect to the first one
$cap = false;
$records = Dns::recordsLdap($domain);
if (isset($records[0])) {
$record = $records[0];
if (isset($record['port'])) {
$cap = $this->discoverCapabilities(array(
'hostname' => $record['target'],
'port' => $record['port']
));
} else {
$cap = $this->discoverCapabilities(array(
'hostname' => $record['target'],
'port' => 389
));
}
}
return $cap;
}

private function discoverCapabilities($config)
{
$conn = new Connection(new Config($config));
try {
$conn->connect();
$this->capabilities = $conn->getCapabilities();
$this->namingContext = $conn->getDefaultNamingContext();
$this->port = $config['port'];
$this->domain = $config['hostname'];
return true;
} catch (LdapException $e) {
Logger::info(
'Ldap discovery for ' . $config['hostname'] . ':' . $config['port'] . ' failed: ' . $e->getMessage()
);
return false;
}
}

public function suggestResourceSettings()
{
if (! isset($this->capabilities)) {
return array();
}
if (isset($this->capabilities->msCapabilities->ActiveDirectoryOid)) {
return array(
'hostname' => $this->domain,
'port' => $this->port,
'root_dn' => $this->namingContext
);
} else {
return array(
'hostname' => $this->domain,
'port' => $this->port,
'root_dn' => $this->namingContext
);
}
}

public function hasSuggestion()
{
return isset($this->capabilities);
}

public function suggestBackendSettings()
{
if (! isset($this->capabilities)) {
return array();
}
if (isset($this->capabilities->msCapabilities->ActiveDirectoryOid)) {
return array(
'base_dn' => $this->namingContext,
'user_class' => 'user',
'user_name_attribute' => 'sAMAccountName'
);
} else {
return array(
'base_dn' => $this->namingContext,
'user_class' => 'inetOrgPerson',
'user_name_attribute' => 'uid'
);
}
}

public function isAd()
{
return isset($this->capabilities->msCapabilities->ActiveDirectoryOid);
}
}
3 changes: 2 additions & 1 deletion application/forms/Setup/AdminAccountPage.php
Expand Up @@ -223,7 +223,8 @@ protected function fetchUsers()
$backend = new LdapUserBackend(
ResourceFactory::createResource(new Zend_Config($this->resourceConfig)),
$this->backendConfig['user_class'],
$this->backendConfig['user_name_attribute']
$this->backendConfig['user_name_attribute'],
$this->backendConfig['base_dn']
);
} else {
throw new LogicException(
Expand Down
32 changes: 32 additions & 0 deletions application/forms/Setup/AuthBackendPage.php
Expand Up @@ -16,6 +16,27 @@
*/
class AuthBackendPage extends Form
{
/**
* Suggested configuration settings
*
* @var array
*/
private $suggestion;

/**
* Set the resource configuration to use
*
* @param array $config
*
* @return self
*/
public function setSuggestions(array $config)
{
$this->suggestion = $config;
return $this;
}


/**
* The resource configuration to use
*
Expand Down Expand Up @@ -87,6 +108,17 @@ public function createElements(array $formData)
} elseif ($this->config['type'] === 'ldap') {
$backendForm = new LdapBackendForm();
$backendForm->createElements($formData)->removeElement('resource');
if (isset($this->suggestion)) {
if (!isset($formData['base_dn'])) {
$backendForm->getElement('base_dn')->setValue($this->suggestion['base_dn']);
}
if (!isset($formData['user_class'])) {
$backendForm->getElement('user_class')->setValue($this->suggestion['user_class']);
}
if (!isset($formData['user_name_attribute'])) {
$backendForm->getElement('user_name_attribute')->setValue($this->suggestion['user_name_attribute']);
}
}
} else { // $this->config['type'] === 'autologin'
$backendForm = new AutologinBackendForm();
$backendForm->createElements($formData);
Expand Down

0 comments on commit 853b00f

Please sign in to comment.