Add Artery TCP/TLS transport, #24390
* configurable SSLEngineProvider * ssl configuration * add internal outgoingTlsConnectionWithSSLEngine and bindTlsWithSSLEngine in stream Tcp * TLS tests * update remote security section in reference documentation
This commit is contained in:
parent
162a1f80a0
commit
4dab3252bd
13 changed files with 655 additions and 25 deletions
|
|
@ -49,6 +49,22 @@ object ArterySpecSupport {
|
|||
*/
|
||||
def defaultConfig = newFlightRecorderConfig
|
||||
.withFallback(staticArteryRemotingConfig)
|
||||
.withFallback(tlsConfig) // TLS only used if transport=tls-tcp
|
||||
|
||||
// set the test key-store and trust-store properties
|
||||
// TLS only used if transport=tls-tcp, which can be set from specific tests or
|
||||
// System properties (e.g. jenkins job)
|
||||
lazy val tlsConfig: Config = {
|
||||
val trustStore = getClass.getClassLoader.getResource("truststore").getPath
|
||||
val keyStore = getClass.getClassLoader.getResource("keystore").getPath
|
||||
|
||||
ConfigFactory.parseString(s"""
|
||||
akka.remote.artery.ssl.config-ssl-engine {
|
||||
key-store = "$keyStore"
|
||||
trust-store = "$trustStore"
|
||||
}
|
||||
""")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,20 @@ class ArteryTcpSendConsistencyWithThreeLanesSpec extends AbstractRemoteSendConsi
|
|||
akka.remote.artery.advanced.inbound-lanes = 3
|
||||
""").withFallback(ArterySpecSupport.defaultConfig))
|
||||
|
||||
class ArteryTlsTcpSendConsistencyWithOneLaneSpec extends AbstractRemoteSendConsistencySpec(
|
||||
ConfigFactory.parseString("""
|
||||
akka.remote.artery.transport = tls-tcp
|
||||
akka.remote.artery.advanced.outbound-lanes = 1
|
||||
akka.remote.artery.advanced.inbound-lanes = 1
|
||||
""").withFallback(ArterySpecSupport.defaultConfig))
|
||||
|
||||
class ArteryTlsTcpSendConsistencyWithThreeLanesSpec extends AbstractRemoteSendConsistencySpec(
|
||||
ConfigFactory.parseString("""
|
||||
akka.remote.artery.transport = tls-tcp
|
||||
akka.remote.artery.advanced.outbound-lanes = 1
|
||||
akka.remote.artery.advanced.inbound-lanes = 1
|
||||
""").withFallback(ArterySpecSupport.defaultConfig))
|
||||
|
||||
abstract class AbstractRemoteSendConsistencySpec(config: Config) extends ArteryMultiNodeSpec(config) with ImplicitSender {
|
||||
|
||||
val systemB = newRemoteSystem(name = Some("systemB"))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,167 @@
|
|||
/**
|
||||
* Copyright (C) 2016-2018 Lightbend Inc. <https://www.lightbend.com>
|
||||
*/
|
||||
package akka.remote.artery
|
||||
package tcp
|
||||
|
||||
import java.security.NoSuchAlgorithmException
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.ActorPath
|
||||
import akka.actor.ActorIdentity
|
||||
import akka.actor.ExtendedActorSystem
|
||||
import akka.actor.Identify
|
||||
import akka.actor.RootActorPath
|
||||
import akka.testkit.ImplicitSender
|
||||
import akka.testkit.TestActors
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigFactory
|
||||
|
||||
class TlsTcpWithDefaultConfigSpec extends TlsTcpSpec(ConfigFactory.empty())
|
||||
|
||||
class TlsTcpWithSHA1PRNGSpec extends TlsTcpSpec(ConfigFactory.parseString("""
|
||||
akka.remote.artery.ssl.config-ssl-engine {
|
||||
random-number-generator = "SHA1PRNG"
|
||||
enabled-algorithms = ["TLS_RSA_WITH_AES_128_CBC_SHA"]
|
||||
}
|
||||
"""))
|
||||
|
||||
class TlsTcpWithAES128CounterSecureRNGSpec extends TlsTcpSpec(ConfigFactory.parseString("""
|
||||
akka.remote.artery.ssl.config-ssl-engine {
|
||||
random-number-generator = "AES128CounterSecureRNG"
|
||||
enabled-algorithms = ["TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA"]
|
||||
}
|
||||
"""))
|
||||
|
||||
class TlsTcpWithAES256CounterSecureRNGSpec extends TlsTcpSpec(ConfigFactory.parseString("""
|
||||
akka.remote.artery.ssl.config-ssl-engine {
|
||||
random-number-generator = "AES256CounterSecureRNG"
|
||||
enabled-algorithms = ["TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA"]
|
||||
}
|
||||
"""))
|
||||
|
||||
class TlsTcpWithDefaultRNGSecureSpec extends TlsTcpSpec(ConfigFactory.parseString("""
|
||||
akka.remote.artery.ssl.config-ssl-engine {
|
||||
random-number-generator = ""
|
||||
enabled-algorithms = ["TLS_RSA_WITH_AES_128_CBC_SHA"]
|
||||
}
|
||||
"""))
|
||||
|
||||
class TlsTcpWithCrappyRSAWithMD5OnlyHereToMakeSureThingsWorkSpec extends TlsTcpSpec(ConfigFactory.parseString("""
|
||||
akka.remote.artery.ssl.config-ssl-engine {
|
||||
random-number-generator = ""
|
||||
enabled-algorithms = [""SSL_RSA_WITH_NULL_MD5""]
|
||||
}
|
||||
"""))
|
||||
|
||||
object TlsTcpSpec {
|
||||
|
||||
lazy val config: Config = {
|
||||
ConfigFactory.parseString(s"""
|
||||
akka.loglevel = DEBUG
|
||||
akka.remote.artery {
|
||||
transport = tls-tcp
|
||||
large-message-destinations = [ "/user/large" ]
|
||||
}
|
||||
""")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
abstract class TlsTcpSpec(config: Config)
|
||||
extends ArteryMultiNodeSpec(config.withFallback(TlsTcpSpec.config)) with ImplicitSender {
|
||||
|
||||
val systemB = newRemoteSystem(name = Some("systemB"))
|
||||
val addressB = address(systemB)
|
||||
val rootB = RootActorPath(addressB)
|
||||
|
||||
def isSupported: Boolean = {
|
||||
try {
|
||||
val provider = new ConfigSSLEngineProvider(system)
|
||||
|
||||
val rng = provider.createSecureRandom()
|
||||
rng.nextInt() // Has to work
|
||||
val sRng = provider.SSLRandomNumberGenerator
|
||||
if (rng.getAlgorithm != sRng && sRng != "")
|
||||
throw new NoSuchAlgorithmException(sRng)
|
||||
|
||||
val address = system.asInstanceOf[ExtendedActorSystem].provider.getDefaultAddress
|
||||
val host = address.host.get
|
||||
val port = address.port.get
|
||||
|
||||
val engine = provider.createServerSSLEngine(host, port)
|
||||
val gotAllSupported = provider.SSLEnabledAlgorithms diff engine.getSupportedCipherSuites.toSet
|
||||
val gotAllEnabled = provider.SSLEnabledAlgorithms diff engine.getEnabledCipherSuites.toSet
|
||||
gotAllSupported.isEmpty || (throw new IllegalArgumentException("Cipher Suite not supported: " + gotAllSupported))
|
||||
gotAllEnabled.isEmpty || (throw new IllegalArgumentException("Cipher Suite not enabled: " + gotAllEnabled))
|
||||
engine.getSupportedProtocols.contains(provider.SSLProtocol) ||
|
||||
(throw new IllegalArgumentException("Protocol not supported: " + provider.SSLProtocol))
|
||||
} catch {
|
||||
case e @ ((_: IllegalArgumentException) | (_: NoSuchAlgorithmException)) ⇒
|
||||
info(e.toString)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def identify(path: ActorPath): ActorRef = {
|
||||
system.actorSelection(path) ! Identify(path.name)
|
||||
expectMsgType[ActorIdentity].ref.get
|
||||
}
|
||||
|
||||
def testDelivery(echoRef: ActorRef): Unit = {
|
||||
echoRef ! "ping-1"
|
||||
expectMsg("ping-1")
|
||||
|
||||
// and some more
|
||||
(2 to 10).foreach { n ⇒
|
||||
echoRef ! s"ping-$n"
|
||||
}
|
||||
receiveN(9) should equal((2 to 10).map(n ⇒ s"ping-$n"))
|
||||
}
|
||||
|
||||
"Artery with TLS/TCP" must {
|
||||
|
||||
if (isSupported) {
|
||||
|
||||
"deliver messages" in {
|
||||
systemB.actorOf(TestActors.echoActorProps, "echo")
|
||||
val echoRef = identify(rootB / "user" / "echo")
|
||||
testDelivery(echoRef)
|
||||
}
|
||||
|
||||
"deliver messages over large messages stream" in {
|
||||
systemB.actorOf(TestActors.echoActorProps, "large")
|
||||
val echoRef = identify(rootB / "user" / "large")
|
||||
testDelivery(echoRef)
|
||||
}
|
||||
|
||||
} else {
|
||||
"not be run when the cipher is not supported by the platform this test is currently being executed on" in {
|
||||
pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TlsTcpWithHostnameVerificationSpec extends ArteryMultiNodeSpec(
|
||||
ConfigFactory.parseString("""
|
||||
akka.remote.artery.ssl.config-ssl-engine {
|
||||
hostname-verification = on
|
||||
}
|
||||
""").withFallback(TlsTcpSpec.config)) with ImplicitSender {
|
||||
|
||||
val systemB = newRemoteSystem(name = Some("systemB"))
|
||||
val addressB = address(systemB)
|
||||
val rootB = RootActorPath(addressB)
|
||||
|
||||
"Artery with TLS/TCP and hostname-verification=on" must {
|
||||
"reject invalid" in {
|
||||
systemB.actorOf(TestActors.echoActorProps, "echo")
|
||||
system.actorSelection(rootB / "user" / "echo") ! Identify("echo")
|
||||
expectNoMessage(2.seconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue