Skip to content

Commit

Permalink
Adding support to restrict SSL protocols and Cypher Suites
Browse files Browse the repository at this point in the history
  • Loading branch information
atooni committed Mar 6, 2019
1 parent 0cd8137 commit 2c99034
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 42 deletions.
Expand Up @@ -19,6 +19,8 @@ class JolokiaClient(address : JolokiaAddress) {
private[this] implicit val backend = HttpURLConnectionBackend()
private[this] val log = Logger[JolokiaClient]

val url = address.jolokiaUrl

def version : Try[JolokiaVersion] = performGet("version")(JolokiaVersion(_))

def search(searchDef : MBeanSearchDef) : Try[JolokiaSearchResult] = {
Expand Down
Expand Up @@ -16,7 +16,8 @@ import org.osgi.framework.BundleContext
/**
* Note: The fact that this class has the same name as it's trait is required by the MBean spec.
*/
class FrameworkService(bundleContext: BundleContext, ctContext: ContainerContext) extends FrameworkServiceMBean {
class FrameworkService(bundleContext: BundleContext, ctContext: ContainerContext)
extends FrameworkServiceMBean {

private[this] val log = Logger[FrameworkService]
private[this] val restarting : AtomicBoolean = new AtomicBoolean(false)
Expand Down
@@ -0,0 +1,19 @@
package blended.security.ssl

trait SslContextInfo {

val allowedCyphers : List[String]

def getProtocol() : String
def getEnabledProtocols() : Array[String]
def getEnabledCypherSuites() : Array[String]

def getInvalidCypherSuites() : Array[String] = {
getEnabledCypherSuites().filter{ s => !allowedCyphers.contains(s) }
}

override def toString: String = s"SSLContextInfo(protocol=$getProtocol()," +
s"enabledProtocols=${getEnabledProtocols().mkString(",")},\n" +
s"enabledCyphers=${getEnabledCypherSuites().mkString(",\n")}\n" +
s"invalidCyphers=${getInvalidCypherSuites().mkString(",\n")}\n)"
}
Expand Up @@ -2,11 +2,13 @@ package blended.security.ssl.internal

import blended.container.context.api.ContainerIdentifierService
import blended.domino.TypesafeConfigWatching
import blended.security.ssl.{ CertificateManager, CertificateProvider, SelfSignedCertificateProvider, SelfSignedConfig }
import blended.security.ssl.{CertificateManager, CertificateProvider, SelfSignedCertificateProvider, SelfSignedConfig}
import blended.util.config.Implicits._
import blended.util.logging.Logger
import com.typesafe.config.Config
import domino.DominoActivator
import javax.management.{MBeanServer, ObjectName}
import javax.net.ssl.SSLContext

class CertificateActivator extends DominoActivator with TypesafeConfigWatching {

Expand All @@ -25,9 +27,9 @@ class CertificateActivator extends DominoActivator with TypesafeConfigWatching {
}
}

private[this] def setupCertificateManager(cfg: Config, idSvc: ContainerIdentifierService) : Unit = {

val mgrConfig = CertificateManagerConfig.fromConfig(cfg, new PasswordHasher(idSvc.uuid), idSvc)
private[this] def setupCertificateManager(
mgrConfig: CertificateManagerConfig
) : Unit = {

def waitForProvider(providerNames: List[String], provider: Map[String, CertificateProvider]) : Unit = {
providerNames match {
Expand All @@ -49,9 +51,27 @@ class CertificateActivator extends DominoActivator with TypesafeConfigWatching {
}

whenBundleActive {

whenTypesafeConfigAvailable { (cfg, idSvc) =>

val mgrConfig = CertificateManagerConfig.fromConfig(cfg, new PasswordHasher(idSvc.uuid), idSvc)

setupSelfSignedProvider(cfg, idSvc)
setupCertificateManager(cfg, idSvc)
setupCertificateManager(mgrConfig)

whenAdvancedServicePresent[SSLContext]("(type=server)") { ctxt =>
val info = new SslContextInfo(ctxt, mgrConfig.validCypherSuites)
info.providesService[blended.security.ssl.SslContextInfo]

whenServicePresent[MBeanServer] { server =>
val objName: ObjectName = new ObjectName("blended:type=SslContext,name=server")
server.registerMBean(info, objName)

onStop {
server.unregisterMBean(objName)
}
}
}
}
}
}
Expand Up @@ -23,7 +23,8 @@ case class CertificateManagerConfig(
keyPass: String,
certConfigs: List[CertificateConfig],
refresherConfig: Option[RefresherConfig],
skipInitialCheck: Boolean
skipInitialCheck: Boolean,
validCypherSuites : List[String]
)

object CertificateManagerConfig {
Expand All @@ -45,14 +46,17 @@ object CertificateManagerConfig {
val refresherConfig = cfg.getConfigOption("refresher").map(c => RefresherConfig.fromConfig(c).get)

val skipInitialCheck = cfg.getBoolean("skipInitialCheck", false)


val cyphers = cfg.getStringList("validCypherSuites", List.empty)

CertificateManagerConfig(
keyStore = keyStore,
storePass = hasher.password(storePass),
keyPass = hasher.password(keyPass),
certConfigs,
refresherConfig,
skipInitialCheck = skipInitialCheck
skipInitialCheck = skipInitialCheck,
validCypherSuites = cyphers
)
}
}
Expand Down
Expand Up @@ -41,7 +41,7 @@ class CertificateManagerImpl(
// TODO: what should we do with this side-effect, if we unregister the context provider?
// FIXME: should this side-effect be configurable?

log.info(new SSLContextInfo("server", sslCtxtProvider.serverContext).toString())
log.info(s"Server SSLContext : ${new SslContextInfo(sslCtxtProvider.serverContext, cfg.validCypherSuites).toString()}")

SSLContext.setDefault(sslCtxtProvider.serverContext)
val serverReg = sslCtxtProvider.clientContext.providesService[SSLContext](Map("type" -> "client"))
Expand Down

This file was deleted.

@@ -0,0 +1,17 @@
package blended.security.ssl.internal

import blended.security.ssl.{ SslContextInfo => SslContextInfoTrait }
import javax.net.ssl.SSLContext

trait SslContextInfoMBean extends SslContextInfoTrait

class SslContextInfo(
sslContext : SSLContext,
override val allowedCyphers: List[String]
) extends SslContextInfoMBean {

override def getProtocol(): String = sslContext.getProtocol()
override def getEnabledProtocols(): Array[String] = sslContext.getDefaultSSLParameters().getProtocols()
override def getEnabledCypherSuites(): Array[String] = sslContext.getDefaultSSLParameters().getCipherSuites()

}
Expand Up @@ -19,6 +19,23 @@ blended.security.ssl {
}
}

validCypherSuites = [
"TLS_RSA_WITH_AES_256_CBC_SHA256",
"TLS_DH_RSA_WITH_AES_256_CBC_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384",
"TLS_DH_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
]

selfsigned {
validDays=10
keyStrength=2048
Expand Down
@@ -0,0 +1,9 @@
crypto.policy=unlimited

jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224

jdk.tls.disabledAlgorithms=TlSv1, TLSv1.1, SSLv3, DHE_DSS, DHE_RSA, RC4, DES, MD5withRSA, DH keySize < 1024, \
EC keySize < 224, 3DES_EDE_CBC, AES_128_CBC, AES_128_GCM, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, \
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, \
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
Expand Up @@ -5,6 +5,7 @@ import java.io.File
import blended.testsupport.BlendedTestSupport
import blended.testsupport.pojosr.{PojoSrTestHelper, SimplePojoContainerSpec}
import blended.testsupport.scalatest.LoggingFreeSpecLike
import blended.util.logging.Logger
import javax.net.ssl.SSLContext
import org.osgi.framework.BundleActivator
import org.scalatest.Matchers
Expand All @@ -22,14 +23,16 @@ class CertificateActivatorSpec extends SimplePojoContainerSpec
"blended.security.ssl" -> new CertificateActivator()
)

private val log = Logger[CertificateActivatorSpec]

private implicit val timeout : FiniteDuration = 3.seconds

"The Certificate Activator should" - {

"start up and provide a server and a client SSL Context" in {

implicit val timeout : FiniteDuration = 3.seconds

val serverContext : SSLContext = mandatoryService[SSLContext](registry)(Some("(type=server)"))
val clientContext : SSLContext = mandatoryService[SSLContext](registry)(Some("(type=server)"))
val clientContext : SSLContext = mandatoryService[SSLContext](registry)(Some("(type=client)"))

val hasher = new PasswordHasher(pojoUuid)

Expand All @@ -42,6 +45,19 @@ class CertificateActivatorSpec extends SimplePojoContainerSpec
val mks = jks.loadKeyStore().get
mks.certificates.keys.toList.sorted should be (List("default", "logical"))
}

"Only support selected CypherSuites and protocols" in {

val sslInfo : blended.security.ssl.SslContextInfo = mandatoryService[blended.security.ssl.SslContextInfo](registry)(None)
val serverContext : SSLContext = mandatoryService[SSLContext](registry)(Some("(type=server)"))

val enabled : List[String] = sslInfo.getEnabledCypherSuites().toList

val invalid = sslInfo.getInvalidCypherSuites()
log.info(s"Invalid CypherSuites [${invalid.size}] : [\n${invalid.mkString("\n")}\n]")

invalid should be (empty)
}
}

}
3 changes: 3 additions & 0 deletions project/BlendedSecuritySsl.scala
Expand Up @@ -25,6 +25,9 @@ object BlendedSecuritySsl extends ProjectFactory {

override def settings: Seq[sbt.Setting[_]] = defaultSettings ++ Seq(

Test / javaOptions +=
"-Djava.security.properties=" + ((Test / classDirectory).value / "container/security.properties").getAbsolutePath(),

embeddedJars := {
(Compile/externalDependencyClasspath).value
.map(_.data)
Expand Down
26 changes: 13 additions & 13 deletions project/Dependencies.scala.asc
@@ -1,17 +1,17 @@
-----BEGIN PGP SIGNATURE-----
Version: BCPG v1.51

iQIcBAABAgAGBQJceRcXAAoJEEYY0oeTi6qO7YsP/0ky0rdZf02dYuUUSC3fRtfI
zqwOHQ8d443L6uayqeuTIjsl2+vLtJ5PnD5wGUI8s3CQAJK41c2Y5vvqt6oW3qDJ
ppLVAk28zieoRocZhCmJwZTm67Lbi9g8LeGxFHNnRXt8k9+ib6bEx1DCO98aZwCs
+ISNEexQXO2G/ZEtOxfarYayV/MtJQeJ8bjcrqlmzaRuZfmjIYCpm5Me8jh+OsW2
JyWNr539PTYECu8qgY919KdNGga3vAMc9ml8zBe+9pOvsvAdlUPHXXvA9zrOefmu
ghgT4rtLsnpUDny7UYprr51YgTz4rNTaWNNuDXwqko2JbSn6b4/dYk3q+Us3TTyW
6TrmqYiXj7x3qTeS7VX0vQYLHSt40FVKnxa9s1hModI6te5iWHS2qAJN4hKKr8kb
EIqtsxQJYysotedGIMxDjRJK2TqlnvjcEx2qmpkvO9p0ignOeXWQGv9Zm3c0KQZ0
Fr/VqCBnklBPio6hYlq4/jS6NmvolBHek2DYw6JvjYyk96G/8GUGf699aG9NBQOo
2CNyir6QN7vuj1ZopM7wCcYOD+tNyxrZ4rAURHE38lQ/VVveg678Mkq/ejSARUZ6
9TT0Y1IU0hxSVVxGXM2OUhmMN/Wdb1dlohna7s3kQVLi0TqYvGpw0uGumXf0Yxj0
AIz3OlqWqWh+AdJm9zO1
=ijTV
iQIcBAABAgAGBQJcfmcBAAoJEEYY0oeTi6qOOscQAIYL6nNsARfM7tOAOMAB7iO1
pYraogSl6kP2w+0cpwznfY/3XhRr4vk5BFkZoBhNCQUtCWDLmuLAzF2O0fdqnTlA
z5frWG0vv3WsirSSMniwZTRwAW5hVEcHUeMPnvD6Ko8e/sd259OhFE5wmpDbwHQE
bduq45IEmp3X7N2R93kXhdTW9pypqEUTEiNSsKFE1/1zt+LmAwPaPv59KxAXmbNl
siHyJLOkAKF7rIpZRdsJR8Zjmo7dhLQMx9JEuaM6z3Gkm7+dIqTHGaUUx3Rmr1M9
DlfSo2zxcAh+DLfyDFjKvANVn2RLCxDvl3wPjr0uejwNudeCRIavEugRUYH1gCbI
tqeuSzKdxIk6YVgQ15R/x9G4SSk/VKVMsQ/qjHm6Rm4nbSo1MPdX75SuxaGvMruS
izaPBlR0w82XDjYqy54jgTYHlz3UBR+AcWhGW4W7bv9oSd3gzOyjMNfoOura9jUK
xwSGK+kXqHUkJQ+yJmI7L55JfONNUY98LvUa9oXnKA851lDIuTGtigq96dVQfh1Y
OnV00Nd/ZNz4wVjtPAgf+u70GxtOqOzq8mM8NL2jyZLiFWFquHJABCTCCEgZp3zi
CFDe3HXz8BK7sn+aRIdGMdtryd5VNYavwj3zpk090I9MU6QtUGwXHTYvC1bVRNyb
IfyncMan8G45ELDozGXd
=2IMc
-----END PGP SIGNATURE-----
2 changes: 1 addition & 1 deletion version.txt
@@ -1 +1 @@
3.0-M5
3.0-M6-SNAPSHOT

0 comments on commit 2c99034

Please sign in to comment.