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

Create a new option to trust all non-expired certificates during LDAP authentication #742

Merged
merged 2 commits into from
Jun 20, 2020
Merged
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ LDAP support is through the basic authentication filter.

4. (Optional) Limit access to a specific LDAP Group
- basicAuthentication.ldap.group-filter=< LDAP group filter>
- basicAuthentication.ldap.ssl-trust-all=< Boolean flag to allow non-expired invalid certificates>

#### Example (Online LDAP Test Server):

Expand All @@ -160,6 +161,7 @@ LDAP support is through the basic authentication filter.
- basicAuthentication.ldap.group-filter="cn=allowed-group,ou=groups,dc=example,dc=com"
- basicAuthentication.ldap.connection-pool-size=10
- basicAuthentication.ldap.ssl=false
- basicAuthentication.ldap.ssl-trust-all=false


Deployment
Expand Down
41 changes: 23 additions & 18 deletions app/controllers/BasicAuthenticationFilter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,25 @@ package controllers

import java.nio.charset.StandardCharsets
import java.security.SecureRandom

import com.typesafe.config.ConfigValueType
import java.util.UUID

import com.unboundid.ldap.sdk._
import javax.net.ssl.SSLSocketFactory
import akka.stream.Materializer
import com.typesafe.config.ConfigValueType
import com.unboundid.ldap.sdk._
import com.unboundid.util.ssl.{SSLUtil, TrustAllTrustManager}
import grizzled.slf4j.Logging
import javax.crypto.Mac
import javax.net.ssl
import org.apache.commons.codec.binary.Base64
import play.api.Configuration
import play.api.http.HeaderNames.{AUTHORIZATION, WWW_AUTHENTICATE}
import play.api.libs.Codecs
import play.api.mvc.Results.Unauthorized
import play.api.mvc.{Cookie, Filter, RequestHeader, Result}

import scala.collection.JavaConverters._
import scala.util.{Success, Try}
import grizzled.slf4j.Logging
import javax.crypto.Mac
import play.api.libs.Codecs

import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Success, Try}

class BasicAuthenticationFilter(configuration: BasicAuthenticationFilterConfiguration, authenticator: Authenticator)(implicit val mat: Materializer, ec: ExecutionContext) extends Filter {

Expand All @@ -39,11 +38,8 @@ class BasicAuthenticationFilter(configuration: BasicAuthenticationFilterConfigur

trait Authenticator {

import javax.crypto.Cipher
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.PBEKeySpec
import javax.crypto.spec.SecretKeySpec
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.{IvParameterSpec, PBEKeySpec, SecretKeySpec}
import javax.crypto.{Cipher, SecretKeyFactory}

private lazy val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
private lazy val spec = new PBEKeySpec(secret, salt, 65536, 256)
Expand Down Expand Up @@ -75,7 +71,7 @@ trait Authenticator {
cipher.doFinal(content)
}

def sign(content: String) : String = {
def sign(content: String): String = {
Codecs.toHexString(mac.doFinal(content.getBytes(StandardCharsets.UTF_8)))
}

Expand Down Expand Up @@ -148,7 +144,14 @@ case class LDAPAuthenticator(config: LDAPAuthenticationConfig)(implicit val mat:
private lazy val ldapConnectionPool: LDAPConnectionPool = {
val (address, port) = (config.address, config.port)
val connection = if (config.sslEnabled) {
new LDAPConnection(SSLSocketFactory.getDefault, address, port, config.username, config.password)
if (config.sslTrustAll) {
val sslUtil = new SSLUtil(null, new TrustAllTrustManager(true))
val sslSocketFactory = sslUtil.createSSLSocketFactory
new LDAPConnection(sslSocketFactory, address, port, config.username, config.password)
} else {
val sslSocketFactory = ssl.SSLSocketFactory.getDefault
new LDAPConnection(sslSocketFactory, address, port, config.username, config.password)
}
} else {
new LDAPConnection(address, port, config.username, config.password)
}
Expand Down Expand Up @@ -271,7 +274,8 @@ case class LDAPAuthenticationConfig(salt: Array[Byte]
, searchFilter: String
, groupFilter: String
, connectionPoolSize: Int
, sslEnabled: Boolean) extends AuthenticationConfig
, sslEnabled: Boolean
, sslTrustAll: Boolean) extends AuthenticationConfig

sealed trait AuthType[T <: AuthenticationConfig] {
def getConfig(config: AuthenticationConfig): T
Expand Down Expand Up @@ -352,13 +356,14 @@ object BasicAuthenticationFilterConfiguration {
val groupFilter = string("ldap.group-filter").getOrElse("")
val connectionPoolSize = int("ldap.connection-pool-size").getOrElse(10)
val sslEnabled = boolean("ldap.ssl").getOrElse(false)
val sslTrustAll = boolean("ldap.ssl-trust-all").getOrElse(false)

BasicAuthenticationFilterConfiguration(
enabled,
LDAPAuth,
LDAPAuthenticationConfig(salt, iv, secret,
string("realm").getOrElse(defaultRealm),
server, port, username, password, searchDN, searchFilter, groupFilter, connectionPoolSize, sslEnabled
server, port, username, password, searchDN, searchFilter, groupFilter, connectionPoolSize, sslEnabled, sslTrustAll
),
excluded
)
Expand Down
2 changes: 2 additions & 0 deletions conf/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ basicAuthentication.ldap.connection-pool-size=10
basicAuthentication.ldap.connection-pool-size=${?KAFKA_MANAGER_LDAP_CONNECTION_POOL_SIZE}
basicAuthentication.ldap.ssl=false
basicAuthentication.ldap.ssl=${?KAFKA_MANAGER_LDAP_SSL}
basicAuthentication.ldap.ssl-trust-all=false
basicAuthentication.ldap.ssl-trust-all=${?KAFKA_MANAGER_LDAP_SSL_TRUST_ALL}

basicAuthentication.username="admin"
basicAuthentication.username=${?KAFKA_MANAGER_USERNAME}
Expand Down