Loading README.md +35 −0 Original line number Diff line number Diff line Loading @@ -71,3 +71,38 @@ hosts: [ } ] ``` ### User authentication It is possible to control access to cerebro through authentication. At the moment, there are no roles/permission level, and either an user is able to access or not. There are two methods of authentication: - Basic: username and password on the configuration file - LDAP: connect to an external provider for authentication Example for basic: ```yaml auth { type: basic settings: { username = "admin" password = "1234" } } ``` Example for LDAP: ```yaml auth { type: ldap settings: { url = "ldap://host:port" base-dn = "ou=active,ou=Employee" method = "simple" user-domain = "domain.com" } } ``` app/controllers/AliasesController.scala +14 −8 Original line number Diff line number Diff line package controllers import models.{Aliases, ElasticServer} import javax.inject.Inject import controllers.auth.AuthenticationModule import elastic.ElasticClient import models.{Aliases, CerebroResponse} import play.api.libs.json.JsArray import scala.concurrent.ExecutionContext.Implicits.global class AliasesController extends BaseController { class AliasesController @Inject()(val authentication: AuthenticationModule, client: ElasticClient) extends BaseController { def getAliases = process { (request, client) => client.getAliases(ElasticServer(request.host, request.authentication)).map { aliases => Status(aliases.status)(Aliases(aliases.body)) def getAliases = process { request => client.getAliases(request.target).map { aliases => CerebroResponse(aliases.status, Aliases(aliases.body)) } } def updateAliases = process { (request, client) => def updateAliases = process { request => val changes = request.getOptArray("changes").getOrElse(JsArray()).value client.updateAliases(changes, ElasticServer(request.host, request.authentication)).map { aliases => Status(aliases.status)(aliases.body) client.updateAliases(changes, request.target).map { aliases => CerebroResponse(aliases.status, aliases.body) } } Loading app/controllers/AnalysisController.scala +22 −17 Original line number Diff line number Diff line package controllers import javax.inject.Inject import controllers.auth.AuthenticationModule import elastic.ElasticClient import models.{CerebroResponse, ElasticServer} import models.analysis.{IndexAnalyzers, IndexFields, OpenIndices, Tokens} import models.ElasticServer import scala.concurrent.ExecutionContext.Implicits.global class AnalysisController extends BaseController { class AnalysisController @Inject()(val authentication: AuthenticationModule, client: ElasticClient) extends BaseController { def getIndices = process { (request, client) => client.getIndices(ElasticServer(request.host, request.authentication)).map { response => Status(response.status)(OpenIndices(response.body)) def getIndices = process { request => client.getIndices(request.target).map { response => CerebroResponse(response.status, OpenIndices(response.body)) } } def getIndexAnalyzers = process { (request, client) => def getIndexAnalyzers = process { request => val index = request.get("index") client.getIndexSettings(index, ElasticServer(request.host, request.authentication)).map { response => Status(response.status)(IndexAnalyzers(index, response.body)) client.getIndexSettings(index, request.target).map { response => CerebroResponse(response.status, IndexAnalyzers(index, response.body)) } } def getIndexFields = process { (request, client) => def getIndexFields = process { request => val index = request.get("index") client.getIndexMapping(index, ElasticServer(request.host, request.authentication)).map { response => Status(response.status)(IndexFields(index, response.body)) client.getIndexMapping(index, request.target).map { response => CerebroResponse(response.status, IndexFields(index, response.body)) } } def analyzeByField = process { (request, client) => def analyzeByField = process { request => val index = request.get("index") val field = request.get("field") val text = request.get("text") client.analyzeTextByField(index, field, text, ElasticServer(request.host, request.authentication)).map { response => Status(response.status)(Tokens(response.body)) client.analyzeTextByField(index, field, text, request.target).map { response => CerebroResponse(response.status, Tokens(response.body)) } } def analyzeByAnalyzer = process { (request, client) => def analyzeByAnalyzer = process { request => val index = request.get("index") val analyzer = request.get("analyzer") val text = request.get("text") client.analyzeTextByAnalyzer(index, analyzer, text, ElasticServer(request.host, request.authentication)).map { response => Status(response.status)(Tokens(response.body)) client.analyzeTextByAnalyzer(index, analyzer, text, request.target).map { response => CerebroResponse(response.status, Tokens(response.body)) } } Loading app/controllers/Application.scala +5 −4 Original line number Diff line number Diff line package controllers import play.api.mvc.{Action, Controller} import play.api.http.MimeTypes import com.google.inject.Inject import controllers.auth.AuthenticationModule import play.api.mvc.Controller object Application extends Controller { class Application @Inject()(val authentication: AuthenticationModule) extends Controller with AuthSupport { def index = Action { def index = AuthAction(authentication, true) { request => Ok(views.html.Index()) } Loading app/controllers/AuthController.scala 0 → 100644 +67 −0 Original line number Diff line number Diff line package controllers import javax.inject.{Inject, Singleton} import akka.actor.ActorSystem import controllers.auth.{AuthAction, AuthenticationModule} import forms.LoginForm import play.api.mvc.{Action, Controller} @Singleton class AuthController @Inject()(system: ActorSystem, authentication: AuthenticationModule) extends Controller { import AuthController._ private val badFormMsg = "invalid login form data" def index = Action { implicit request => if (authentication.isEnabled) { request.session.get(AuthAction.SESSION_USER).map { user => request.session.get(AuthAction.REDIRECT_URL) match { case Some(url) => Redirect(url, play.api.http.Status.SEE_OTHER) case None => Redirect(routes.Application.index()) } }.getOrElse { Ok(views.html.auth.login()) } } else { Redirect(routes.Application.index()) } } def login = Action { implicit request => LoginForm.form.bindFromRequest.fold( formWithErrors => { log.error(badFormMsg) BadRequest(badFormMsg) }, creds => { authentication.authentication(creds.user, creds.password) match { case Some(username) => val resp = request.session.get(AuthAction.REDIRECT_URL) match { case Some(url) => Redirect(url, play.api.http.Status.SEE_OTHER) case None => Redirect(routes.Application.index()) } resp.withSession(AuthAction.SESSION_USER -> username) case None => Redirect(routes.AuthController.index).flashing(LOGIN_MSG -> "wrong user and/or password") } } ) } def logout = Action { request => Redirect("/login").withNewSession } } object AuthController { private val log = org.slf4j.LoggerFactory.getLogger(classOf[AuthController]) final val LOGIN_MSG = "login-msg" } Loading
README.md +35 −0 Original line number Diff line number Diff line Loading @@ -71,3 +71,38 @@ hosts: [ } ] ``` ### User authentication It is possible to control access to cerebro through authentication. At the moment, there are no roles/permission level, and either an user is able to access or not. There are two methods of authentication: - Basic: username and password on the configuration file - LDAP: connect to an external provider for authentication Example for basic: ```yaml auth { type: basic settings: { username = "admin" password = "1234" } } ``` Example for LDAP: ```yaml auth { type: ldap settings: { url = "ldap://host:port" base-dn = "ou=active,ou=Employee" method = "simple" user-domain = "domain.com" } } ```
app/controllers/AliasesController.scala +14 −8 Original line number Diff line number Diff line package controllers import models.{Aliases, ElasticServer} import javax.inject.Inject import controllers.auth.AuthenticationModule import elastic.ElasticClient import models.{Aliases, CerebroResponse} import play.api.libs.json.JsArray import scala.concurrent.ExecutionContext.Implicits.global class AliasesController extends BaseController { class AliasesController @Inject()(val authentication: AuthenticationModule, client: ElasticClient) extends BaseController { def getAliases = process { (request, client) => client.getAliases(ElasticServer(request.host, request.authentication)).map { aliases => Status(aliases.status)(Aliases(aliases.body)) def getAliases = process { request => client.getAliases(request.target).map { aliases => CerebroResponse(aliases.status, Aliases(aliases.body)) } } def updateAliases = process { (request, client) => def updateAliases = process { request => val changes = request.getOptArray("changes").getOrElse(JsArray()).value client.updateAliases(changes, ElasticServer(request.host, request.authentication)).map { aliases => Status(aliases.status)(aliases.body) client.updateAliases(changes, request.target).map { aliases => CerebroResponse(aliases.status, aliases.body) } } Loading
app/controllers/AnalysisController.scala +22 −17 Original line number Diff line number Diff line package controllers import javax.inject.Inject import controllers.auth.AuthenticationModule import elastic.ElasticClient import models.{CerebroResponse, ElasticServer} import models.analysis.{IndexAnalyzers, IndexFields, OpenIndices, Tokens} import models.ElasticServer import scala.concurrent.ExecutionContext.Implicits.global class AnalysisController extends BaseController { class AnalysisController @Inject()(val authentication: AuthenticationModule, client: ElasticClient) extends BaseController { def getIndices = process { (request, client) => client.getIndices(ElasticServer(request.host, request.authentication)).map { response => Status(response.status)(OpenIndices(response.body)) def getIndices = process { request => client.getIndices(request.target).map { response => CerebroResponse(response.status, OpenIndices(response.body)) } } def getIndexAnalyzers = process { (request, client) => def getIndexAnalyzers = process { request => val index = request.get("index") client.getIndexSettings(index, ElasticServer(request.host, request.authentication)).map { response => Status(response.status)(IndexAnalyzers(index, response.body)) client.getIndexSettings(index, request.target).map { response => CerebroResponse(response.status, IndexAnalyzers(index, response.body)) } } def getIndexFields = process { (request, client) => def getIndexFields = process { request => val index = request.get("index") client.getIndexMapping(index, ElasticServer(request.host, request.authentication)).map { response => Status(response.status)(IndexFields(index, response.body)) client.getIndexMapping(index, request.target).map { response => CerebroResponse(response.status, IndexFields(index, response.body)) } } def analyzeByField = process { (request, client) => def analyzeByField = process { request => val index = request.get("index") val field = request.get("field") val text = request.get("text") client.analyzeTextByField(index, field, text, ElasticServer(request.host, request.authentication)).map { response => Status(response.status)(Tokens(response.body)) client.analyzeTextByField(index, field, text, request.target).map { response => CerebroResponse(response.status, Tokens(response.body)) } } def analyzeByAnalyzer = process { (request, client) => def analyzeByAnalyzer = process { request => val index = request.get("index") val analyzer = request.get("analyzer") val text = request.get("text") client.analyzeTextByAnalyzer(index, analyzer, text, ElasticServer(request.host, request.authentication)).map { response => Status(response.status)(Tokens(response.body)) client.analyzeTextByAnalyzer(index, analyzer, text, request.target).map { response => CerebroResponse(response.status, Tokens(response.body)) } } Loading
app/controllers/Application.scala +5 −4 Original line number Diff line number Diff line package controllers import play.api.mvc.{Action, Controller} import play.api.http.MimeTypes import com.google.inject.Inject import controllers.auth.AuthenticationModule import play.api.mvc.Controller object Application extends Controller { class Application @Inject()(val authentication: AuthenticationModule) extends Controller with AuthSupport { def index = Action { def index = AuthAction(authentication, true) { request => Ok(views.html.Index()) } Loading
app/controllers/AuthController.scala 0 → 100644 +67 −0 Original line number Diff line number Diff line package controllers import javax.inject.{Inject, Singleton} import akka.actor.ActorSystem import controllers.auth.{AuthAction, AuthenticationModule} import forms.LoginForm import play.api.mvc.{Action, Controller} @Singleton class AuthController @Inject()(system: ActorSystem, authentication: AuthenticationModule) extends Controller { import AuthController._ private val badFormMsg = "invalid login form data" def index = Action { implicit request => if (authentication.isEnabled) { request.session.get(AuthAction.SESSION_USER).map { user => request.session.get(AuthAction.REDIRECT_URL) match { case Some(url) => Redirect(url, play.api.http.Status.SEE_OTHER) case None => Redirect(routes.Application.index()) } }.getOrElse { Ok(views.html.auth.login()) } } else { Redirect(routes.Application.index()) } } def login = Action { implicit request => LoginForm.form.bindFromRequest.fold( formWithErrors => { log.error(badFormMsg) BadRequest(badFormMsg) }, creds => { authentication.authentication(creds.user, creds.password) match { case Some(username) => val resp = request.session.get(AuthAction.REDIRECT_URL) match { case Some(url) => Redirect(url, play.api.http.Status.SEE_OTHER) case None => Redirect(routes.Application.index()) } resp.withSession(AuthAction.SESSION_USER -> username) case None => Redirect(routes.AuthController.index).flashing(LOGIN_MSG -> "wrong user and/or password") } } ) } def logout = Action { request => Redirect("/login").withNewSession } } object AuthController { private val log = org.slf4j.LoggerFactory.getLogger(classOf[AuthController]) final val LOGIN_MSG = "login-msg" }