1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-08-07 23:03:00 +03:00

multiple ldap server

This commit is contained in:
Khazhinov Vladislav
2022-09-21 15:24:57 +03:00
parent aec772c5eb
commit 4bacc45fb7
2 changed files with 81 additions and 24 deletions

View File

@@ -207,6 +207,7 @@ TWITTER_AUTO_CONFIRM_EMAIL=false
# LDAP authentication configuration # LDAP authentication configuration
# Refer to https://www.bookstackapp.com/docs/admin/ldap-auth/ # Refer to https://www.bookstackapp.com/docs/admin/ldap-auth/
# If you need to use multiple addresses, separate them with a semicolon. Ex: dc1.domain.local:389;dc2.domain.local:389
LDAP_SERVER=false LDAP_SERVER=false
LDAP_BASE_DN=false LDAP_BASE_DN=false
LDAP_DN=false LDAP_DN=false
@@ -368,4 +369,4 @@ LOG_FAILED_LOGIN_CHANNEL=errorlog_plain_webserver
# IP address '146.191.42.4' would result in '146.191.x.x' being logged. # IP address '146.191.42.4' would result in '146.191.x.x' being logged.
# For the IPv6 address '2001:db8:85a3:8d3:1319:8a2e:370:7348' this would result as: # For the IPv6 address '2001:db8:85a3:8d3:1319:8a2e:370:7348' this would result as:
# '2001:db8:85a3:8d3:x:x:x:x' # '2001:db8:85a3:8d3:x:x:x:x'
IP_ADDRESS_PRECISION=4 IP_ADDRESS_PRECISION=4

View File

@@ -217,22 +217,54 @@ class LdapService
} }
$serverDetails = $this->parseServerString($this->config['server']); $serverDetails = $this->parseServerString($this->config['server']);
$ldapConnection = $this->ldap->connect($serverDetails['host'], $serverDetails['port']); if (array_key_exists('hosts', $serverDetails)) {
$fail_counter = 0;
foreach ($serverDetails['hosts'] as $serverDetailsItem) {
try {
$ldapConnection = $this->ldap->connect($serverDetailsItem['host'], $serverDetailsItem['port']);
if ($ldapConnection === false) { if ($ldapConnection === false) {
throw new LdapException(trans('errors.ldap_cannot_connect')); throw new LdapException(trans('errors.ldap_cannot_connect'));
} }
// Set any required options // Set any required options
if ($this->config['version']) { if ($this->config['version']) {
$this->ldap->setVersion($ldapConnection, $this->config['version']); $this->ldap->setVersion($ldapConnection, $this->config['version']);
} }
// Start and verify TLS if it's enabled // Start and verify TLS if it's enabled
if ($this->config['start_tls']) { if ($this->config['start_tls']) {
$started = $this->ldap->startTls($ldapConnection); $started = $this->ldap->startTls($ldapConnection);
if (!$started) { if (!$started) {
throw new LdapException('Could not start TLS connection'); throw new LdapException('Could not start TLS connection');
}
}
} catch (\Throwable $exception) {
$fail_counter++;
}
}
if ($fail_counter == count($serverDetails['hosts'])) {
throw new LdapException(trans('errors.ldap_cannot_connect'));
}
} else {
$ldapConnection = $this->ldap->connect($serverDetails['host'], $serverDetails['port']);
if ($ldapConnection === false) {
throw new LdapException(trans('errors.ldap_cannot_connect'));
}
// Set any required options
if ($this->config['version']) {
$this->ldap->setVersion($ldapConnection, $this->config['version']);
}
// Start and verify TLS if it's enabled
if ($this->config['start_tls']) {
$started = $this->ldap->startTls($ldapConnection);
if (!$started) {
throw new LdapException('Could not start TLS connection');
}
} }
} }
@@ -244,21 +276,45 @@ class LdapService
/** /**
* Parse a LDAP server string and return the host and port for a connection. * Parse a LDAP server string and return the host and port for a connection.
* Is flexible to formats such as 'ldap.example.com:8069' or 'ldaps://ldap.example.com'. * Is flexible to formats such as 'ldap.example.com:8069' or 'ldaps://ldap.example.com'.
* If you need to use multiple addresses, separate them with a semicolon.
* Ex: dc1.domain.local:389;dc2.domain.local:389
*/ */
protected function parseServerString(string $serverString): array protected function parseServerString(string $serverString): array
{ {
$serverNameParts = explode(':', $serverString); $explodedServerString = explode(';', $serverString);
if (count($explodedServerString) > 1) {
$result = ['hosts' => []];
// If we have a protocol just return the full string since PHP will ignore a separate port. foreach ($explodedServerString as $serverString) {
if ($serverNameParts[0] === 'ldaps' || $serverNameParts[0] === 'ldap') { $serverNameParts = explode(':', $serverString);
return ['host' => $serverString, 'port' => 389];
// If we have a protocol just return the full string since PHP will ignore a separate port.
if ($serverNameParts[0] === 'ldaps' || $serverNameParts[0] === 'ldap') {
return ['host' => $serverString, 'port' => 389];
}
// Otherwise, extract the port out
$hostName = $serverNameParts[0];
$ldapPort = (count($serverNameParts) > 1) ? intval($serverNameParts[1]) : 389;
$result['hosts'][] = ['host' => $hostName, 'port' => $ldapPort];
}
return $result;
} else {
$serverNameParts = explode(':', $serverString);
// If we have a protocol just return the full string since PHP will ignore a separate port.
if ($serverNameParts[0] === 'ldaps' || $serverNameParts[0] === 'ldap') {
return ['host' => $serverString, 'port' => 389];
}
// Otherwise, extract the port out
$hostName = $serverNameParts[0];
$ldapPort = (count($serverNameParts) > 1) ? intval($serverNameParts[1]) : 389;
return ['host' => $hostName, 'port' => $ldapPort];
} }
// Otherwise, extract the port out
$hostName = $serverNameParts[0];
$ldapPort = (count($serverNameParts) > 1) ? intval($serverNameParts[1]) : 389;
return ['host' => $hostName, 'port' => $ldapPort];
} }
/** /**