Skip to content

Commit

Permalink
#26 Add SSLEngineProvider to request client certificate
Browse files Browse the repository at this point in the history
  • Loading branch information
To-om committed Jun 11, 2018
1 parent b1c8fd7 commit 5471549
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
82 changes: 82 additions & 0 deletions app/org/elastic4play/ClientAuthSSLEngineProvider.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.elastic4play

import java.nio.file.{ Files, Paths }
import java.security.KeyStore

import play.api.Logger
import play.core.ApplicationProvider
import play.core.server.ServerConfig
import play.server.api.SSLEngineProvider

import javax.net.ssl._

class ClientAuthSSLEngineProvider(serverConfig: ServerConfig, appProvider: ApplicationProvider) extends SSLEngineProvider {

lazy val logger = Logger(getClass)
private val config = serverConfig.configuration

def readKeyManagers(): Array[KeyManager] = {
val keyStorePath = Paths.get(config.get[String]("play.server.https.keyStore.path"))
val keyStoreType = config.getOptional[String]("play.server.https.keyStore.type").getOrElse(KeyStore.getDefaultType)
val keyStorePassword = config.getOptional[String]("play.server.https.keyStore.password").getOrElse("").toCharArray
val keyInputStream = Files.newInputStream(keyStorePath)
try {
val keyStore = KeyStore.getInstance(keyStoreType)
keyStore.load(keyInputStream, keyStorePassword)
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm)
kmf.init(keyStore, keyStorePassword)
kmf.getKeyManagers
}
finally {
keyInputStream.close()
}
}

def readTrustManagers(): Array[TrustManager] = {
val trustStorePath = Paths.get(config.get[String]("play.server.https.trustStore.path"))
val keyStoreType = config.getOptional[String]("play.server.https.keyStore.type").getOrElse(KeyStore.getDefaultType)
val trustStorePassword = config.getOptional[String]("play.server.https.trustStore.password").getOrElse("").toCharArray
val trustInputStream = Files.newInputStream(trustStorePath)
try {
val keyStore = KeyStore.getInstance(keyStoreType)
keyStore.load(trustInputStream, trustStorePassword)
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
tmf.init(keyStore)
tmf.getTrustManagers
}
finally {
trustInputStream.close()
}
}

def createSSLContext(applicationProvider: ApplicationProvider): SSLContext = {
val keyManagers = readKeyManagers()
val trustManagers = readTrustManagers()

// Configure the SSL context to use TLS
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(keyManagers, trustManagers, null)
sslContext
}

override def createSSLEngine(): SSLEngine = {
val sslContext = createSSLContext(appProvider)

// Start off with a clone of the default SSL parameters...
val sslParameters = sslContext.getDefaultSSLParameters

// Tells the server to ignore client's cipher suite preference.
// http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#cipher_suite_preference
sslParameters.setUseCipherSuitesOrder(true)

// http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#SSLParameters
val needClientAuth = config.getOptional[Boolean]("play.server.https.needClientAuth").getOrElse(false)
logger.info(s"Client certificate authentication is ${if (needClientAuth) "enable" else "disable"}")
sslParameters.setNeedClientAuth(needClientAuth)

// Clone and modify the default SSL parameters.
val engine = sslContext.createSSLEngine
engine.setSSLParameters(sslParameters)
engine
}
}
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ organizationHomepage := Some(url("https://thehive-project.org/"))
licenses += "AGPL-V3" -> url("https://www.gnu.org/licenses/agpl-3.0.html")

lazy val elastic4play = (project in file("."))
.enablePlugins(PlayScala)
.enablePlugins(PlayScala, PlayAkkaHttp2Support)

scalaVersion := "2.12.4"

Expand Down
5 changes: 4 additions & 1 deletion conf/reference.conf
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# handler for errors (transform exception to related http status code
play.http.errorHandler = org.elastic4play.ErrorHandler
play.http.errorHandler = org.elastic4play.ErrorHandler

# SSL engine used to ask client certificate
play.http.sslengineprovider=org.elastic4play.ClientAuthSSLEngineProvider
2 changes: 1 addition & 1 deletion version.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version := "1.5.0"
version := "1.5.1-SNAPSHOT"

0 comments on commit 5471549

Please sign in to comment.