diff --git a/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md b/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md index 0bd1df15cf..4ac2d78bfe 100644 --- a/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md +++ b/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md @@ -74,6 +74,10 @@ After being deprecated since 2.5.0, the following have been removed in Akka 2.6. * `akka.stream.actor.ActorSubscriber` and `akka.stream.actor.ActorPublisher` - Use `GraphStage` instead. +After being deprecated since 2.4.0, the following have been removed in Akka 2.6. + +* Secure cookie in Classic Akka Remoting + After being deprecated since 2.2, the following have been removed in Akka 2.6. * `actorFor` diff --git a/akka-remote/src/main/mima-filters/2.5.x.backwards.excludes/_existing.excludes b/akka-remote/src/main/mima-filters/2.5.x.backwards.excludes/_existing.excludes index 9534d2ee74..47ec20f837 100644 --- a/akka-remote/src/main/mima-filters/2.5.x.backwards.excludes/_existing.excludes +++ b/akka-remote/src/main/mima-filters/2.5.x.backwards.excludes/_existing.excludes @@ -74,3 +74,10 @@ ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.artery.ArteryTra ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.artery.ArteryTransport.createFlightRecorderEventSink") ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.artery.ArteryTransport.createFlightRecorderEventSink$default$1") ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.artery.ArteryTransport.flightRecorder") + +# Remove secure-cookie #27809 +ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.transport.AkkaProtocolSettings.RequireCookie") +ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.transport.AkkaProtocolSettings.SecureCookie") +ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.transport.HandshakeInfo.tupled") +ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.transport.HandshakeInfo.curried") +ProblemFilters.exclude[MissingTypesProblem]("akka.remote.transport.HandshakeInfo$") diff --git a/akka-remote/src/main/resources/reference.conf b/akka-remote/src/main/resources/reference.conf index 35a2a621d0..3909b251d0 100644 --- a/akka-remote/src/main/resources/reference.conf +++ b/akka-remote/src/main/resources/reference.conf @@ -341,15 +341,6 @@ akka { # E.g. trusted-selection-paths = ["/user/receptionist", "/user/namingService"] trusted-selection-paths = [] - # Should the remote server require that its peers share the same - # secure-cookie (defined in the 'remote' section)? Secure cookies are passed - # between during the initial handshake. Connections are refused if the initial - # message contains a mismatching cookie or the cookie is missing. - require-cookie = off - - # Deprecated since 2.4-M1 - secure-cookie = "" - ### Logging # If this is "on", Akka will log all inbound messages at DEBUG level, diff --git a/akka-remote/src/main/scala/akka/remote/transport/AkkaPduCodec.scala b/akka-remote/src/main/scala/akka/remote/transport/AkkaPduCodec.scala index 8a640a8b5c..5fb46bfb57 100644 --- a/akka-remote/src/main/scala/akka/remote/transport/AkkaPduCodec.scala +++ b/akka-remote/src/main/scala/akka/remote/transport/AkkaPduCodec.scala @@ -173,7 +173,6 @@ private[remote] object AkkaPduProtobufCodec extends AkkaPduCodec { override def constructAssociate(info: HandshakeInfo): ByteString = { val handshakeInfo = AkkaHandshakeInfo.newBuilder.setOrigin(serializeAddress(info.origin)).setUid(info.uid.toLong) - info.cookie.foreach(handshakeInfo.setCookie) constructControlMessagePdu(WireFormats.CommandType.ASSOCIATE, Some(handshakeInfo)) } @@ -240,12 +239,11 @@ private[remote] object AkkaPduProtobufCodec extends AkkaPduCodec { controlPdu.getCommandType match { case CommandType.ASSOCIATE if controlPdu.hasHandshakeInfo => val handshakeInfo = controlPdu.getHandshakeInfo - val cookie = if (handshakeInfo.hasCookie) Some(handshakeInfo.getCookie) else None Associate( HandshakeInfo( decodeAddress(handshakeInfo.getOrigin), - handshakeInfo.getUid.toInt, // 64 bits are allocated in the wire formats, but we use only 32 for now - cookie)) + handshakeInfo.getUid.toInt // 64 bits are allocated in the wire formats, but we use only 32 for now + )) case CommandType.DISASSOCIATE => Disassociate(AssociationHandle.Unknown) case CommandType.DISASSOCIATE_SHUTTING_DOWN => Disassociate(AssociationHandle.Shutdown) case CommandType.DISASSOCIATE_QUARANTINED => Disassociate(AssociationHandle.Quarantined) diff --git a/akka-remote/src/main/scala/akka/remote/transport/AkkaProtocolTransport.scala b/akka-remote/src/main/scala/akka/remote/transport/AkkaProtocolTransport.scala index ba4145f944..d73fd8a45c 100644 --- a/akka-remote/src/main/scala/akka/remote/transport/AkkaProtocolTransport.scala +++ b/akka-remote/src/main/scala/akka/remote/transport/AkkaProtocolTransport.scala @@ -26,7 +26,6 @@ import scala.concurrent.duration._ import scala.concurrent.{ Future, Promise } import scala.util.control.NonFatal import akka.dispatch.{ RequiresMessageQueue, UnboundedMessageQueueSemantics } -import akka.event.{ LogMarker, Logging } import com.github.ghik.silencer.silent @SerialVersionUID(1L) @@ -46,10 +45,6 @@ private[remote] class AkkaProtocolSettings(config: Config) { TransportFailureDetectorConfig.getMillisDuration("heartbeat-interval") }.requiring(_ > Duration.Zero, "transport-failure-detector.heartbeat-interval must be > 0") - val RequireCookie: Boolean = getBoolean("akka.remote.classic.require-cookie") - - val SecureCookie: Option[String] = if (RequireCookie) Some(getString("akka.remote.classic.secure-cookie")) else None - val HandshakeTimeout: FiniteDuration = { val enabledTransports = config.getStringList("akka.remote.classic.enabled-transports") if (enabledTransports.contains("akka.remote.classic.netty.tcp")) @@ -76,6 +71,12 @@ private[remote] object AkkaProtocolTransport { //Couldn't these go into the Remo extends NoSerializationVerificationNeeded } +object HandshakeInfo { + def apply(origin: Address, uid: Int): HandshakeInfo = + new HandshakeInfo(origin, uid, cookie = None) +} + +// cookie is not used, but keeping field to avoid bin compat (Classic Remoting is deprecated anyway) final case class HandshakeInfo(origin: Address, uid: Int, cookie: Option[String]) /** @@ -83,7 +84,6 @@ final case class HandshakeInfo(origin: Address, uid: Int, cookie: Option[String] * * Features provided by this transport are: * - Soft-state associations via the use of heartbeats and failure detectors - * - Secure-cookie handling * - Transparent origin address handling * - pluggable codecs to encode and decode Akka PDUs * @@ -160,7 +160,7 @@ private[transport] class AkkaProtocolManager( context.actorOf( RARP(context.system).configureDispatcher( ProtocolStateActor.inboundProps( - HandshakeInfo(stateActorLocalAddress, addressUid, stateActorSettings.SecureCookie), + HandshakeInfo(stateActorLocalAddress, addressUid), handle, stateActorAssociationHandler, stateActorSettings, @@ -192,7 +192,7 @@ private[transport] class AkkaProtocolManager( context.actorOf( RARP(context.system).configureDispatcher( ProtocolStateActor.outboundProps( - HandshakeInfo(stateActorLocalAddress, addressUid, stateActorSettings.SecureCookie), + HandshakeInfo(stateActorLocalAddress, addressUid), remoteAddress, statusPromise, stateActorWrappedTransport, @@ -341,8 +341,6 @@ private[remote] class ProtocolStateActor( with FSM[AssociationState, ProtocolStateData] with RequiresMessageQueue[UnboundedMessageQueueSemantics] { - private val markerLog = Logging.withMarker(this) - import ProtocolStateActor._ import context.dispatcher @@ -480,30 +478,15 @@ private[remote] class ProtocolStateActor( // Incoming association -- implicitly ACK by a heartbeat case Associate(info) => - if (!settings.RequireCookie || info.cookie == settings.SecureCookie) { - sendAssociate(wrappedHandle, localHandshakeInfo) - failureDetector.heartbeat() - initHeartbeatTimer() - cancelTimer(handshakeTimerKey) - goto(Open).using( - AssociatedWaitHandler( - notifyInboundHandler(wrappedHandle, info, associationHandler), - wrappedHandle, - immutable.Queue.empty)) - } else { - if (log.isDebugEnabled) - log.warning( - s"Association attempt with mismatching cookie from [{}]. Expected [{}] but received [{}].", - info.origin, - localHandshakeInfo.cookie.getOrElse(""), - info.cookie.getOrElse("")) - else - markerLog.warning( - LogMarker.Security, - s"Association attempt with mismatching cookie from [{}].", - info.origin) - stop() - } + sendAssociate(wrappedHandle, localHandshakeInfo) + failureDetector.heartbeat() + initHeartbeatTimer() + cancelTimer(handshakeTimerKey) + goto(Open).using( + AssociatedWaitHandler( + notifyInboundHandler(wrappedHandle, info, associationHandler), + wrappedHandle, + immutable.Queue.empty)) // Got a stray message -- explicitly reset the association (force remote endpoint to reassociate) case msg => diff --git a/akka-remote/src/test/scala/akka/remote/RemoteConfigSpec.scala b/akka-remote/src/test/scala/akka/remote/RemoteConfigSpec.scala index 4a9ebbfa1c..d8986cbc34 100644 --- a/akka-remote/src/test/scala/akka/remote/RemoteConfigSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/RemoteConfigSpec.scala @@ -70,9 +70,6 @@ class RemoteConfigSpec extends AkkaSpec(""" val settings = new AkkaProtocolSettings(RARP(system).provider.remoteSettings.config) import settings._ - RequireCookie should ===(false) - SecureCookie should ===(None) - TransportFailureDetectorImplementationClass should ===(classOf[DeadlineFailureDetector].getName) TransportHeartBeatInterval should ===(4.seconds) TransportFailureDetectorConfig.getMillisDuration("acceptable-heartbeat-pause") should ===(120.seconds) diff --git a/akka-remote/src/test/scala/akka/remote/classic/RemotingSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/RemotingSpec.scala index 6f2aad571b..2dec011059 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/RemotingSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/RemotingSpec.scala @@ -652,7 +652,7 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D } val handshakePacket = - AkkaPduProtobufCodec.constructAssociate(HandshakeInfo(rawRemoteAddress, uid = 0, cookie = None)) + AkkaPduProtobufCodec.constructAssociate(HandshakeInfo(rawRemoteAddress, uid = 0)) val brokenPacket = AkkaPduProtobufCodec.constructPayload(ByteString(0, 1, 2, 3, 4, 5, 6)) // Finish the inbound handshake so now it is handed up to Remoting @@ -734,7 +734,7 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D } val handshakePacket = - AkkaPduProtobufCodec.constructAssociate(HandshakeInfo(rawRemoteAddress, uid = remoteUID, cookie = None)) + AkkaPduProtobufCodec.constructAssociate(HandshakeInfo(rawRemoteAddress, uid = remoteUID)) // Finish the inbound handshake so now it is handed up to Remoting inboundHandle.write(handshakePacket) diff --git a/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolSpec.scala index 68c5823a16..96d53fa399 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolSpec.scala @@ -53,8 +53,6 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit classic { backoff-interval = 1 s - require-cookie = off - secure-cookie = "abcde" shutdown-timeout = 5 s startup-timeout = 5 s use-passive-connections = on @@ -90,8 +88,8 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit def testPayload = InboundPayload(testMsgPdu) def testDisassociate(info: DisassociateInfo) = InboundPayload(codec.constructDisassociate(info)) - def testAssociate(uid: Int, cookie: Option[String]) = - InboundPayload(codec.constructAssociate(HandshakeInfo(remoteAkkaAddress, uid, cookie))) + def testAssociate(uid: Int) = + InboundPayload(codec.constructAssociate(HandshakeInfo(remoteAkkaAddress, uid))) def collaborators = { val registry = new AssociationRegistry @@ -115,14 +113,14 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit case _ => false } - def lastActivityIsAssociate(registry: AssociationRegistry, uid: Long, cookie: Option[String]) = + def lastActivityIsAssociate(registry: AssociationRegistry, uid: Long) = if (registry.logSnapshot.isEmpty) false else registry.logSnapshot.last match { case WriteAttempt(sender, recipient, payload) if sender == localAddress && recipient == remoteAddress => codec.decodePdu(payload) match { case Associate(info) => - info.cookie == cookie && info.origin == localAddress && info.uid == uid + info.origin == localAddress && info.uid == uid case _ => false } case _ => false @@ -147,7 +145,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit system.actorOf( ProtocolStateActor.inboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = None), + HandshakeInfo(origin = localAddress, uid = 42), handle, ActorAssociationEventListener(testActor), new AkkaProtocolSettings(conf), @@ -162,14 +160,14 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit val reader = system.actorOf( ProtocolStateActor.inboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = None), + HandshakeInfo(origin = localAddress, uid = 42), handle, ActorAssociationEventListener(testActor), new AkkaProtocolSettings(conf), codec, failureDetector)) - reader ! testAssociate(uid = 33, cookie = None) + reader ! testAssociate(uid = 33) awaitCond(failureDetector.called) @@ -198,7 +196,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit val reader = system.actorOf( ProtocolStateActor.inboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = None), + HandshakeInfo(origin = localAddress, uid = 42), handle, ActorAssociationEventListener(testActor), new AkkaProtocolSettings(conf), @@ -209,7 +207,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit reader ! testHeartbeat // this associate will now be ignored - reader ! testAssociate(uid = 33, cookie = None) + reader ! testAssociate(uid = 33) awaitCond(registry.logSnapshot.exists { case DisassociateAttempt(_, _) => true @@ -225,7 +223,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit val reader = system.actorOf( ProtocolStateActor.outboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = None), + HandshakeInfo(origin = localAddress, uid = 42), remoteAddress, statusPromise, transport, @@ -234,7 +232,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit failureDetector, refuseUid = None)) - awaitCond(lastActivityIsAssociate(registry, 42, None)) + awaitCond(lastActivityIsAssociate(registry, 42)) awaitCond(failureDetector.called) // keeps sending heartbeats @@ -243,7 +241,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit statusPromise.isCompleted should ===(false) // finish connection by sending back an associate message - reader ! testAssociate(33, None) + reader ! testAssociate(33) Await.result(statusPromise.future, 3.seconds) match { case h: AkkaProtocolHandle => @@ -256,79 +254,6 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit } - "ignore incoming associations with wrong cookie" in { - val (failureDetector, registry, _, handle) = collaborators - - val reader = system.actorOf( - ProtocolStateActor.inboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = Some("abcde")), - handle, - ActorAssociationEventListener(testActor), - new AkkaProtocolSettings( - ConfigFactory.parseString("akka.remote.classic.require-cookie = on").withFallback(conf)), - codec, - failureDetector)) - - reader ! testAssociate(uid = 33, Some("xyzzy")) - - awaitCond(registry.logSnapshot.exists { - case DisassociateAttempt(_, _) => true - case _ => false - }) - } - - "accept incoming associations with correct cookie" in { - val (failureDetector, registry, _, handle) = collaborators - - val reader = system.actorOf( - ProtocolStateActor.inboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = Some("abcde")), - handle, - ActorAssociationEventListener(testActor), - new AkkaProtocolSettings( - ConfigFactory.parseString("akka.remote.classic.require-cookie = on").withFallback(conf)), - codec, - failureDetector)) - - // Send the correct cookie - reader ! testAssociate(uid = 33, Some("abcde")) - - val wrappedHandle = expectMsgPF() { - case InboundAssociation(h: AkkaProtocolHandle) => - h.handshakeInfo.uid should ===(33) - h.handshakeInfo.cookie should ===(Some("abcde")) - h - } - - wrappedHandle.readHandlerPromise.success(ActorHandleEventListener(testActor)) - - failureDetector.called should ===(true) - - // Heartbeat was sent in response to Associate - awaitCond(lastActivityIsHeartbeat(registry)) - } - - "send cookie in Associate PDU if configured to do so" in { - val (failureDetector, registry, transport, handle) = collaborators - transport.associateBehavior.pushConstant(handle) - - val statusPromise: Promise[AssociationHandle] = Promise() - - system.actorOf( - ProtocolStateActor.outboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = Some("abcde")), - remoteAddress, - statusPromise, - transport, - new AkkaProtocolSettings( - ConfigFactory.parseString("akka.remote.classic.require-cookie = on").withFallback(conf)), - codec, - failureDetector, - refuseUid = None)) - - awaitCond(lastActivityIsAssociate(registry, uid = 42, cookie = Some("abcde"))) - } - "handle explicit disassociate messages" in { val (failureDetector, registry, transport, handle) = collaborators transport.associateBehavior.pushConstant(handle) @@ -337,7 +262,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit val reader = system.actorOf( ProtocolStateActor.outboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = None), + HandshakeInfo(origin = localAddress, uid = 42), remoteAddress, statusPromise, transport, @@ -346,9 +271,9 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit failureDetector, refuseUid = None)) - awaitCond(lastActivityIsAssociate(registry, uid = 42, cookie = None)) + awaitCond(lastActivityIsAssociate(registry, uid = 42)) - reader ! testAssociate(uid = 33, cookie = None) + reader ! testAssociate(uid = 33) val wrappedHandle = Await.result(statusPromise.future, 3.seconds) match { case h: AssociationHandle => @@ -374,7 +299,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit val reader = system.actorOf( ProtocolStateActor.outboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = None), + HandshakeInfo(origin = localAddress, uid = 42), remoteAddress, statusPromise, transport, @@ -383,9 +308,9 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit failureDetector, refuseUid = None)) - awaitCond(lastActivityIsAssociate(registry, uid = 42, cookie = None)) + awaitCond(lastActivityIsAssociate(registry, uid = 42)) - reader ! testAssociate(uid = 33, cookie = None) + reader ! testAssociate(uid = 33) val wrappedHandle = Await.result(statusPromise.future, 3.seconds) match { case h: AssociationHandle => @@ -411,7 +336,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit val stateActor = system.actorOf( ProtocolStateActor.outboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = None), + HandshakeInfo(origin = localAddress, uid = 42), remoteAddress, statusPromise, transport, @@ -420,9 +345,9 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit failureDetector, refuseUid = None)) - awaitCond(lastActivityIsAssociate(registry, uid = 42, cookie = None)) + awaitCond(lastActivityIsAssociate(registry, uid = 42)) - stateActor ! testAssociate(uid = 33, cookie = None) + stateActor ! testAssociate(uid = 33) val wrappedHandle = Await.result(statusPromise.future, 3.seconds) match { case h: AssociationHandle => @@ -451,7 +376,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit val stateActor = system.actorOf( ProtocolStateActor.outboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = None), + HandshakeInfo(origin = localAddress, uid = 42), remoteAddress, statusPromise, transport, @@ -460,9 +385,9 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit failureDetector, refuseUid = None)) - awaitCond(lastActivityIsAssociate(registry, uid = 42, cookie = None)) + awaitCond(lastActivityIsAssociate(registry, uid = 42)) - stateActor ! testAssociate(uid = 33, cookie = None) + stateActor ! testAssociate(uid = 33) val wrappedHandle = Await.result(statusPromise.future, 3.seconds) match { case h: AssociationHandle => @@ -493,7 +418,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit val stateActor = system.actorOf( ProtocolStateActor.outboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = None), + HandshakeInfo(origin = localAddress, uid = 42), remoteAddress, statusPromise, transport, @@ -517,7 +442,7 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit val reader = system.actorOf( ProtocolStateActor.inboundProps( - HandshakeInfo(origin = localAddress, uid = 42, cookie = None), + HandshakeInfo(origin = localAddress, uid = 42), handle, ActorAssociationEventListener(testActor), new AkkaProtocolSettings(conf2),