diff --git a/library/Icinga/Authentication/User/LdapUserBackend.php b/library/Icinga/Authentication/User/LdapUserBackend.php index ecaa08ef4..e8ae9a579 100644 --- a/library/Icinga/Authentication/User/LdapUserBackend.php +++ b/library/Icinga/Authentication/User/LdapUserBackend.php @@ -308,49 +308,14 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In } /** - * Probe the backend to test if authentication is possible - * - * Try to bind to the backend and fetch a single user to check if: - * - * + * @param Inspection $info Optional inspection to fill with diagnostic info * * @throws AuthenticationException When authentication is not possible */ public function assertAuthenticationPossible(Inspection $insp = null) { - if (! isset($insp)) { - $insp = new Inspection(''); - } - try { - $result = $this->select()->fetchRow(); - } catch (LdapException $e) { - throw new AuthenticationException('Connection not possible.', $e); - } - $insp->write('Connection possible.'); - $msg = sprintf( - 'objects with objectClass "%s" in DN "%s" (Filter: %s)', - $this->userClass, - $this->baseDn ?: $this->ds->getDn(), - $this->filter ?: 'None' - ); - if ($result === false) { - throw new AuthenticationException('No ' . $msg . 'found'); - } - $insp->write($msg . ' exist'); - - if (! isset($result->user_name)) { - throw new AuthenticationException( - 'UserNameAttribute "%s" not existing in objectClass "%s"', - $this->userNameAttribute, - $this->userClass - ); - } } /** @@ -389,7 +354,15 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In } /** - * Inspect if this LDAP User Backend is working as expected + * Inspect if this LDAP User Backend is working as expected by probing the backend + * and testing if thea uthentication is possible + * + * Try to bind to the backend and fetch a single user to check if: + * * * @return Inspection Inspection result */ @@ -399,9 +372,31 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In // inspect the used connection to get more diagnostic info in case the connection is not working $result->write($this->ds->inspect()); - try { - $this->assertAuthenticationPossible($result); + try { + $res = $this->select()->fetchRow(); + } catch (LdapException $e) { + throw new AuthenticationException('Connection not possible.', $e); + } + $result->write('Connection possible.'); + $msg = sprintf( + 'objects with objectClass "%s" in DN "%s" (Filter: %s)', + $this->userClass, + $this->baseDn ?: $this->ds->getDn(), + $this->filter ?: 'None' + ); + if ($res === false) { + throw new AuthenticationException('No ' . $msg . 'found'); + } + $result->write($msg . ' exist'); + if (! isset($res->user_name)) { + throw new AuthenticationException( + 'UserNameAttribute "%s" not existing in objectClass "%s"', + $this->userNameAttribute, + $this->userClass + ); + } + $result->write('User count: ' . $this->select()->count()); } catch (AuthenticationException $e) { if (($previous = $e->getPrevious()) !== null) { diff --git a/library/Icinga/Data/Inspection.php b/library/Icinga/Data/Inspection.php new file mode 100644 index 000000000..eea91617e --- /dev/null +++ b/library/Icinga/Data/Inspection.php @@ -0,0 +1,127 @@ +description = $description; + } + + /** + * Get the name of this Inspection + * + * @return mixed + */ + public function getDescription() + { + return $this->description; + } + + /** + * Append the given log entry or nested inspection + * + * @throws ProgrammingError When called after erroring + * + * @param $entry string|Inspection A log entry or nested inspection + */ + public function write($entry) + { + if (isset($this->error)) { + throw new ProgrammingError('Inspection object used after error'); + } + if ($entry instanceof Inspection) { + $this->log[$entry->description] = $entry->toArray(); + } else { + $this->log[] = $entry; + } + } + + /** + * Append the given log entry and fail this inspection with the given error + * + * @param $entry string|Inspection A log entry or nested inspection + * + * @throws ProgrammingError When called multiple times + * + * @return this fluent interface + */ + public function error($entry) + { + if (isset($this->error)) { + throw new ProgrammingError('Inspection object used after error'); + } + $this->write($entry); + $this->error = $entry; + return $this; + } + + /** + * If the inspection resulted in an error + * + * @return bool + */ + public function hasError() + { + return isset($this->error); + } + + /** + * The error that caused the inspection to fail + * + * @return Inspection|string + */ + public function getError() + { + return $this->error; + } + + /** + * Convert the inspection to an array + * + * @return array An array of strings that describe the state in a human-readable form, each array element + * represents one log entry about this object. + */ + public function toArray() + { + return $this->log; + } + + /** + * Return a text representation of the inspection log entries + */ + public function __toString() + { + return sprintf( + 'Inspection: description: "%s" error: "%s"', + $this->description, + $this->error + ); + } +}