pekko/akka-remote/src/test/scala/akka/remote/serialization/AllowJavaSerializationOffSpec.scala
Konrad `ktoso` Malawski d306700feb =doc Make it easier to disable Java serialization, #22283 (#22315)
* one single config option to disable it completely
* improve security documentation

Co-authored-by: Patrik Nordwall <patrik.nordwall@gmail.com>
2017-02-16 14:09:04 +01:00

133 lines
5.3 KiB
Scala

/*
* Copyright (C) 2016-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package akka.remote.serialization
import akka.actor.setup.ActorSystemSetup
import akka.actor.{ ActorSystem, BootstrapSetup, ExtendedActorSystem, Terminated }
import akka.serialization._
import akka.testkit.{ AkkaSpec, TestKit, TestProbe }
import com.typesafe.config.ConfigFactory
import scala.concurrent.duration._
import akka.actor.actorRef2Scala
class ConfigurationDummy
class ProgrammaticDummy
case class ProgrammaticJavaDummy()
case class SerializableDummy() // since case classes are serializable
object AllowJavaSerializationOffSpec {
val testSerializer = new TestSerializer
val serializationSettings = SerializationSetup { _
List(
SerializerDetails("test", testSerializer, List(classOf[ProgrammaticDummy])))
}
val bootstrapSettings = BootstrapSetup(None, Some(ConfigFactory.parseString("""
akka {
actor {
serialize-messages = off
serialization-bindings {
"akka.serialization.ConfigurationDummy" = test
}
}
}
""")), None)
val actorSystemSettings = ActorSystemSetup(bootstrapSettings, serializationSettings)
val noJavaSerializationSystem = ActorSystem("AllowJavaSerializationOffSpec" + "NoJavaSerialization", ConfigFactory.parseString(
"""
akka {
actor {
allow-java-serialization = off
}
}
""".stripMargin))
val noJavaSerializer = new DisabledJavaSerializer(noJavaSerializationSystem.asInstanceOf[ExtendedActorSystem])
}
class AllowJavaSerializationOffSpec extends AkkaSpec(
ActorSystem("AllowJavaSerializationOffSpec", AllowJavaSerializationOffSpec.actorSystemSettings)) {
import AllowJavaSerializationOffSpec._
// This is a weird edge case, someone creating a JavaSerializer manually and using it in a system means
// that they'd need a different actor system to be able to create it... someone MAY pick a system with
// allow-java-serialization=on to create the SerializationSetup and use that SerializationSetup
// in another system with allow-java-serialization=off
val addedJavaSerializationSettings = SerializationSetup { _
List(
SerializerDetails("test", testSerializer, List(classOf[ProgrammaticDummy])),
SerializerDetails("java-manual", new JavaSerializer(system.asInstanceOf[ExtendedActorSystem]), List(classOf[ProgrammaticJavaDummy])))
}
val addedJavaSerializationProgramaticallyButDisabledSettings = BootstrapSetup(None, Some(ConfigFactory.parseString("""
akka {
loglevel = debug
actor {
enable-additional-serialization-bindings = off # this should be overriden by the setting below, which should force it to be on
allow-java-serialization = off
}
}
""")), None)
val dontAllowJavaSystem =
ActorSystem("addedJavaSerializationSystem", ActorSystemSetup(addedJavaSerializationProgramaticallyButDisabledSettings, addedJavaSerializationSettings))
"Disabling java serialization" should {
"throw if passed system to JavaSerializer has allow-java-serialization = off" in {
intercept[DisabledJavaSerializer.JavaSerializationException] {
new JavaSerializer(noJavaSerializationSystem.asInstanceOf[ExtendedActorSystem])
}.getMessage should include("akka.actor.allow-java-serialization = off")
intercept[DisabledJavaSerializer.JavaSerializationException] {
SerializationExtension(dontAllowJavaSystem).findSerializerFor(new ProgrammaticJavaDummy).toBinary(new ProgrammaticJavaDummy)
}
}
"enable additional-serialization-bindings" in {
val some = Some("foo")
val ser = SerializationExtension(dontAllowJavaSystem).findSerializerFor(some).asInstanceOf[MiscMessageSerializer]
val bytes = ser.toBinary(some)
ser.fromBinary(bytes, ser.manifest(some)) should ===(Some("foo"))
SerializationExtension(dontAllowJavaSystem).deserialize(bytes, ser.identifier, ser.manifest(some))
.get should ===(Some("foo"))
}
"have replaced java serializer" in {
val p = TestProbe()(dontAllowJavaSystem) // only receiver has the serialization disabled
p.ref ! new ProgrammaticJavaDummy
SerializationExtension(system).findSerializerFor(new ProgrammaticJavaDummy).toBinary(new ProgrammaticJavaDummy)
// should not receive this one, it would have been java serialization!
p.expectNoMsg(100.millis)
p.ref ! new ProgrammaticDummy
p.expectMsgType[ProgrammaticDummy]
}
"disable java serialization also for incoming messages if serializer id usually would have found the serializer" in {
val ser1 = SerializationExtension(system)
val msg = SerializableDummy()
val bytes = ser1.serialize(msg).get
val serId = ser1.findSerializerFor(msg).identifier
ser1.findSerializerFor(msg).includeManifest should ===(false)
val ser2 = SerializationExtension(noJavaSerializationSystem)
ser2.findSerializerFor(new SerializableDummy) should ===(noJavaSerializer)
ser2.serializerByIdentity(serId) should ===(noJavaSerializer)
intercept[DisabledJavaSerializer.JavaSerializationException] {
ser2.deserialize(bytes, serId, "").get
}
}
}
override def afterTermination(): Unit = {
TestKit.shutdownActorSystem(noJavaSerializationSystem)
TestKit.shutdownActorSystem(dontAllowJavaSystem)
}
}