Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #25742: Add LDAP synchronous mode config param #5967

Open
wants to merge 1 commit into
base: branches/rudder/8.1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ ldap.port=389
ldap.authdn=cn=manager,cn=rudder-configuration
ldap.maxPoolSize=2

# By default, Rudder use a synchronous mode for LDAP connection. Before 8.1.8, it used to be async.
# You can revert to async by using 'false'
ldap.useSynchronousMode = true

#
# Password used to connect to the OpenLDAP server.
# On a standard Rudder installation, the password is managed in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,17 @@ object RudderParsedProperties {
2
}
}
val LDAP_USE_SYNC_MODE: Boolean = {
try {
config.getBoolean("ldap.useSynchronousMode")
} catch {
case ex: ConfigException =>
ApplicationLogger.info(
"Property 'ldap.useSynchronousMode' is missing or empty in rudder.configFile. Default to true."
)
true
}
}
val LDAP_CACHE_NODE_INFO_MIN_INTERVAL: Duration = {
val x = {
try {
Expand Down Expand Up @@ -2559,7 +2570,8 @@ object RudderConfigInit {
port = LDAP_PORT,
authDn = LDAP_AUTHDN,
authPw = LDAP_AUTHPW,
poolSize = LDAP_MAX_POOL_SIZE
poolSize = LDAP_MAX_POOL_SIZE,
useSynchronousMode = LDAP_USE_SYNC_MODE
)
}
lazy val roLDAPConnectionProvider = roLdap
Expand All @@ -2569,7 +2581,8 @@ object RudderConfigInit {
port = LDAP_PORT,
authDn = LDAP_AUTHDN,
authPw = LDAP_AUTHPW,
poolSize = LDAP_MAX_POOL_SIZE
poolSize = LDAP_MAX_POOL_SIZE,
useSynchronousMode = LDAP_USE_SYNC_MODE
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.normation.ldap.sdk.syntax.UnboundidLDAPConnection
import com.normation.zio.*
import com.unboundid.ldap.listener.InMemoryDirectoryServer
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig
import com.unboundid.ldap.sdk.LDAPConnectionOptions
import com.unboundid.ldap.sdk.schema.Schema
import zio.*

Expand Down Expand Up @@ -53,9 +54,10 @@ class InMemoryDsConnectionProvider[CON <: RoLDAPConnection](
bootstrapLDIFPaths foreach { path => server.importFromLDIF(false, path) }
server.startListening

override def toConnectionString: String = "in-memory-ldap-connection"
override def semaphore: Semaphore = ZioRuntime.unsafeRun(Semaphore.make(1))
override val connection: Ref[Option[CON]] = ZioRuntime.unsafeRun(Ref.make(Option.empty[CON]))
override def toConnectionString: String = "in-memory-ldap-connection"
override def semaphore: Semaphore = ZioRuntime.unsafeRun(Semaphore.make(1))
override def customizeOption: LDAPConnectionOptions => LDAPConnectionOptions = identity
override val connection: Ref[Option[CON]] = ZioRuntime.unsafeRun(Ref.make(Option.empty[CON]))

override def newUnboundidConnection: UnboundidLDAPConnection = server.getConnection

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,14 @@ trait LDAPConnectionProvider[LDAP <: RoLDAPConnection] {
*
*/
trait UnboundidConnectionProvider {
def customizeOption: LDAPConnectionOptions => LDAPConnectionOptions
// for performance reason, this can't be wrapped in ZIO
def newUnboundidConnection: UnboundidLDAPConnection
def toConnectionString: String
}

object RudderLDAPConnectionOptions {
def apply(useSchemaInfos: Boolean): LDAPConnectionOptions = {
def apply(useSchemaInfos: Boolean, useSynchMode: Boolean): LDAPConnectionOptions = {
val options = new LDAPConnectionOptions
options.setUseSchema(useSchemaInfos)
// In Rudder, some entries can grow quite big, see: https://www.rudder-project.org/redmine/issues/13256
Expand All @@ -145,18 +146,20 @@ object RudderLDAPConnectionOptions {
if (options.getMaxMessageSize() == 20971520) {
options.setMaxMessageSize(Int.MaxValue)
}
options.setUseSynchronousMode(useSynchMode)
options
}
}

trait AnonymousConnection extends UnboundidConnectionProvider {

def host: String
def port: Int
def useSchemaInfos: Boolean
def host: String
def port: Int
def useSchemaInfos: Boolean
def useSynchronousMode: Boolean

override def newUnboundidConnection: LDAPConnection = {
new UnboundidLDAPConnection(RudderLDAPConnectionOptions(useSchemaInfos), host, port)
new UnboundidLDAPConnection(RudderLDAPConnectionOptions(useSchemaInfos, useSynchronousMode), host, port)
}

override def toConnectionString: String = s"anonymous@ldap://${host}:${port}"
Expand All @@ -167,14 +170,16 @@ trait AnonymousConnection extends UnboundidConnectionProvider {
* use a simple login/password authentication to the server.
*/
trait SimpleAuthConnection extends UnboundidConnectionProvider {
def authDn: String
def authPw: String
def host: String
def port: Int
def useSchemaInfos: Boolean
def authDn: String
def authPw: String
def host: String
def port: Int
def useSchemaInfos: Boolean
def useSynchronousMode: Boolean

override def newUnboundidConnection: LDAPConnection = {
new UnboundidLDAPConnection(RudderLDAPConnectionOptions(useSchemaInfos), host, port, authDn, authPw)
val options = customizeOption(RudderLDAPConnectionOptions(useSchemaInfos, useSynchronousMode))
new UnboundidLDAPConnection(options, host, port, authDn, authPw)
}

override def toConnectionString: String = s"$authDn:*****@ldap://${host}:${port}"
Expand Down Expand Up @@ -232,6 +237,14 @@ trait PooledConnectionProvider[LDAP <: RoLDAPConnection] extends LDAPConnectionP
def ldifFileLogger: LDIFFileLogger
def poolname: String

// special option for pooled connection
override def customizeOption: LDAPConnectionOptions => LDAPConnectionOptions = (options: LDAPConnectionOptions) => {
options.setUsePooledSchema(true)
options.setPooledSchemaTimeoutMillis(0) // our schema never change without a Rudder restart
options.setAbandonOnTimeout(true) // better abandoning on timeout to free the connection in the pool
options
}

// for performance reason, operation on pool can't be wrapped into ZIO
protected lazy val pool: LDAPConnectionPool = {
try {
Expand Down Expand Up @@ -263,13 +276,15 @@ trait PooledConnectionProvider[LDAP <: RoLDAPConnection] extends LDAPConnectionP
* with no pool management.
*/
class ROAnonymousConnectionProvider(
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val useSynchronousMode: Boolean = true
) extends AnonymousConnection with OneConnectionProvider[RoLDAPConnection] {
override val semaphore: Semaphore = ZioRuntime.unsafeRun(Semaphore.make(1))
override val connection: Ref[Option[RoLDAPConnection]] = ZioRuntime.unsafeRun(Ref.make(Option.empty[RoLDAPConnection]))
override val semaphore: Semaphore = ZioRuntime.unsafeRun(Semaphore.make(1))
override val connection: Ref[Option[RoLDAPConnection]] = ZioRuntime.unsafeRun(Ref.make(Option.empty[RoLDAPConnection]))
override def customizeOption: LDAPConnectionOptions => LDAPConnectionOptions = identity

def newConnection: IO[LDAPRudderError.BackendException, RoLDAPConnection] = {
LDAPIOResult.attempt(new RoLDAPConnection(newUnboundidConnection, ldifFileLogger))
Expand All @@ -281,13 +296,15 @@ class ROAnonymousConnectionProvider(
* with no pool management.
*/
class RWAnonymousConnectionProvider(
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val useSynchronousMode: Boolean = true
) extends AnonymousConnection with OneConnectionProvider[RwLDAPConnection] {
override def semaphore: Semaphore = ZioRuntime.unsafeRun(Semaphore.make(1))
override val connection: Ref[Option[RwLDAPConnection]] = ZioRuntime.unsafeRun(Ref.make(Option.empty[RwLDAPConnection]))
override def semaphore: Semaphore = ZioRuntime.unsafeRun(Semaphore.make(1))
override val connection: Ref[Option[RwLDAPConnection]] = ZioRuntime.unsafeRun(Ref.make(Option.empty[RwLDAPConnection]))
override def customizeOption: LDAPConnectionOptions => LDAPConnectionOptions = identity

def newConnection: IO[LDAPRudderError.BackendException, RwLDAPConnection] = {
LDAPIOResult.attempt(new RwLDAPConnection(newUnboundidConnection, ldifFileLogger))
Expand All @@ -299,11 +316,12 @@ class RWAnonymousConnectionProvider(
* connection provider
*/
class ROPooledAnonymousConnectionProvider(
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val poolSize: Int = 2
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val poolSize: Int = 2,
override val useSynchronousMode: Boolean = true
) extends AnonymousConnection with PooledConnectionProvider[RoLDAPConnection] {
override def poolname: String = s"rudder-anonymous-ro"
def newConnection: IO[LDAPRudderError.BackendException, RoLDAPConnection] = {
Expand All @@ -316,11 +334,12 @@ class ROPooledAnonymousConnectionProvider(
* connection provider
*/
class RWPooledAnonymousConnectionProvider(
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val poolSize: Int = 2
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val poolSize: Int = 2,
override val useSynchronousMode: Boolean = true
) extends AnonymousConnection with PooledConnectionProvider[RwLDAPConnection] {
override def poolname: String = s"rudder-anonymous-rw"
def newConnection: IO[LDAPRudderError.BackendException, RwLDAPConnection] = {
Expand All @@ -334,15 +353,17 @@ class RWPooledAnonymousConnectionProvider(
* management.
*/
class ROSimpleAuthConnectionProvider(
override val authDn: String,
override val authPw: String,
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false
override val authDn: String,
override val authPw: String,
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val useSynchronousMode: Boolean = true
) extends SimpleAuthConnection with OneConnectionProvider[RoLDAPConnection] {
override val semaphore: Semaphore = ZioRuntime.unsafeRun(Semaphore.make(1))
override val connection: Ref[Option[RoLDAPConnection]] = ZioRuntime.unsafeRun(Ref.make(Option.empty[RoLDAPConnection]))
override val semaphore: Semaphore = ZioRuntime.unsafeRun(Semaphore.make(1))
override val connection: Ref[Option[RoLDAPConnection]] = ZioRuntime.unsafeRun(Ref.make(Option.empty[RoLDAPConnection]))
override def customizeOption: LDAPConnectionOptions => LDAPConnectionOptions = identity

def newConnection: IO[LDAPRudderError.BackendException, RoLDAPConnection] = {
LDAPIOResult.attempt(new RoLDAPConnection(newUnboundidConnection, ldifFileLogger))
Expand All @@ -355,15 +376,17 @@ class ROSimpleAuthConnectionProvider(
* management.
*/
class RWSimpleAuthConnectionProvider(
override val authDn: String,
override val authPw: String,
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false
override val authDn: String,
override val authPw: String,
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val useSynchronousMode: Boolean = true
) extends SimpleAuthConnection with OneConnectionProvider[RwLDAPConnection] {
override val semaphore: Semaphore = ZioRuntime.unsafeRun(Semaphore.make(1))
override val connection: Ref[Option[RwLDAPConnection]] = ZioRuntime.unsafeRun(Ref.make(Option.empty[RwLDAPConnection]))
override val semaphore: Semaphore = ZioRuntime.unsafeRun(Semaphore.make(1))
override val connection: Ref[Option[RwLDAPConnection]] = ZioRuntime.unsafeRun(Ref.make(Option.empty[RwLDAPConnection]))
override def customizeOption: LDAPConnectionOptions => LDAPConnectionOptions = identity

def newConnection: IO[LDAPRudderError.BackendException, RwLDAPConnection] = {
LDAPIOResult.attempt(new RwLDAPConnection(newUnboundidConnection, ldifFileLogger))
Expand All @@ -375,13 +398,14 @@ class RWSimpleAuthConnectionProvider(
* with a simple login/pass connection
*/
class ROPooledSimpleAuthConnectionProvider(
override val authDn: String,
override val authPw: String,
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val poolSize: Int = 2
override val authDn: String,
override val authPw: String,
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val poolSize: Int = 2,
override val useSynchronousMode: Boolean = true
) extends SimpleAuthConnection with PooledConnectionProvider[RoLDAPConnection] {
override def poolname: String = s"rudder-authenticated-ro"
def newConnection: IO[LDAPRudderError.BackendException, RoLDAPConnection] = {
Expand All @@ -394,13 +418,14 @@ class ROPooledSimpleAuthConnectionProvider(
* with a simple login/pass connection
*/
class RWPooledSimpleAuthConnectionProvider(
override val authDn: String,
override val authPw: String,
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val poolSize: Int = 2
override val authDn: String,
override val authPw: String,
override val host: String = "localhost",
override val port: Int = 389,
override val ldifFileLogger: LDIFFileLogger = new DefaultLDIFFileLogger(),
override val useSchemaInfos: Boolean = false,
override val poolSize: Int = 2,
override val useSynchronousMode: Boolean = true
) extends SimpleAuthConnection with PooledConnectionProvider[RwLDAPConnection] {

override def poolname: String = s"rudder-authenticated-rw"
Expand Down