Reject inbound remote deployment when it is not enabled - #1
Draft
claude-code-staging[bot] wants to merge 1 commit into
Draft
claude-code-staging[bot] wants to merge 1 commit into
claude-code-staging[bot] wants to merge 1 commit into
Conversation
Motivation: `pekko.remote.use-unsafe-remote-features-outside-cluster` documents that remote watch and deployment are disabled when Pekko Cluster is not used, but for deployment that was only enforced when a node deploys actors on other nodes. `RemoteSystemDaemon` accepted a `DaemonMsgCreate` from any peer that completed the remoting handshake whenever `untrusted-mode` was off, so a node running `pekko.actor.provider = remote` with default settings would instantiate and start any Actor subclass on its classpath with peer-chosen constructor arguments, supervisor, router configuration and dispatcher. Accepted deployments were only logged at debug level, so there was no audit trail either. Modification: `RemoteSystemDaemon` now evaluates the same condition as `RemoteActorRefProvider.hasClusterOrUseUnsafe` and drops a `DaemonMsgCreate` with a `LogMarker.Security` warning when remote deployment is not enabled, before any actor is created. The requested path comes straight off the wire, so control, format and separator characters are replaced and it is truncated before being logged. Accepted deployments are logged once the actor has been created, also with a `LogMarker.Security`: at info level when deployment was enabled without Cluster, and at debug level with Cluster, where one deployment per remote deployed routee would otherwise flood the default logs. reference.conf and the remoting and remote-security docs now state that the setting applies to inbound deployment as well, that the allow list narrows an already enabled remote deployment rather than enabling it, and that neither gate authenticates the requesting peer. A migration note covers the case where only the deploying node has it enabled. Result: A node that neither uses Cluster nor opts in no longer creates actors that a peer asks it to create, and peer-initiated actor creation is auditable where it is allowed. Tests: - Added remote/src/test/scala/org/apache/pekko/remote/InboundRemoteDeploymentSpec.scala: an end-to-end remote deployment from a node that has the setting enabled onto a node that has it off, plus a variant where the target also has the allow list enabled, asserts that no actor is created and that a security marked warning is logged. With the setting on, the actor is created, replies over remoting, and the security marked info log is emitted. - Not run - no build tooling available in this environment: sbt is not installed and the dependency repositories are unreachable, so `sbt remote/testOnly`, `sbt +mimaReportBinaryIssues`, `scalafmt`, `sbt headerCreateAll` and `sbt docs/paradox` could not be executed. No public API, binary shape or serialization format was changed. References: None - enforce the documented `use-unsafe-remote-features-outside-cluster` deployment gate on the receiving side
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
pekko.remote.use-unsafe-remote-features-outside-clusteris documented inremote/src/main/resources/reference.confas disabling remote watch and deployment when Pekko Cluster isnot used. For deployment, that was only enforced on the sending side:
RemoteActorRefProvider.hasClusterOrUseUnsafeis consulted when this node deploys actors on othernodes, but
RemoteSystemDaemonwas registered under/remoteunconditionally and accepted an inboundDaemonMsgCreatewheneveruntrusted-modewas off.A node running
pekko.actor.provider = remotewith default settings (use-unsafe-remote-features-outside-cluster = off,untrusted-mode = off,enable-allow-list = off) would therefore instantiate and start anyActor/IndirectActorProducersubclass on its classpath for any peer that completed the remoting handshake, withpeer-chosen constructor arguments, supervisor, router configuration (including
nrOfInstances) anddispatcher — while the documentation said remote deployment was disabled in that configuration. Accepted
deployments were only logged at debug level, so an operator had no audit trail of peer-initiated actor
creation.
Modification
RemoteSystemDaemonevaluates the same condition asRemoteActorRefProvider.hasClusterOrUseUnsafeanddrops an inbound
DaemonMsgCreatewith aLogMarker.Securitywarning when remote deployment is notenabled, before
doCreateActoris reached. The check is placed ahead of the allow list, which narrows analready enabled remote deployment rather than enabling it.
characters are replaced and the value is truncated before it is logged.
LogMarker.Security: at infolevel when deployment was enabled without Cluster (the opt-in unsafe configuration worth auditing), and
at debug level with Cluster, where one deployment per remote deployed routee would otherwise flood the
default logs.
reference.conf,remoting.md,remoting-artery.mdandremote-security.mdstate that the settingapplies to inbound deployment as well, that only deployment is symmetric (remote watch is gated on the
watching side only), and that neither gate authenticates the requesting peer — network controls, TLS
with mutual authentication and the allow list still matter. A migration note covers upgrades where only
the deploying node has the setting enabled.
Both logs name the class the peer asked for (
props.clazz, the value that goes on the wire) rather thanprops.actorClass(), so that producing a security log never runs peer-selected code.Deliberately out of scope, and unchanged by this PR:
DaemonMsgCreateSerializer.fromBinarystill resolvesthe peer-named class and deserializes the peer-supplied constructor arguments before the daemon sees the
message. That affects Cluster nodes equally and is not covered by the deployment gate, so it is a separate
change. Inbound deployment is also still accepted from any peer that can associate, including a non-member
of the cluster — the gate decides whether deployment is enabled, not who may request it. The added warning
in the docs says so.
Result
A node that neither uses Cluster nor sets
use-unsafe-remote-features-outside-cluster = onno longercreates actors that a peer asks it to create, which restores the documented contract, and peer-initiated
actor creation is auditable where it is allowed.
This is a behaviour change for non-Cluster setups that enabled the setting only on the deploying node:
the target now drops the request. The migration guide says so and names the symptom.
Tests
Added
remote/src/test/scala/org/apache/pekko/remote/InboundRemoteDeploymentSpec.scala. It drives realend-to-end remote deployment (config-driven
actorOf->useActorOnNode-> wire ->/remotedaemon)from a node that has the setting enabled onto a node under test:
off, no Cluster: no actor is created (IdentifyanswersActorIdentity(_, None)) and aLogMarker.Securitywarning is logged;offplusenable-allow-list = onwith the deployed class allow listed: still rejected, whichpins down that the allow list does not enable remote deployment;
on: the actor is created, replies over remoting, and theLogMarker.Securityinfo log isemitted.
The assertions match on the log event rather than only its text, so the security marker and the level are
both checked. The first two cases fail without the production change.
Not run - no build tooling available in the environment this was prepared in: sbt is not installed and
the dependency repositories are unreachable, so
sbt "remote/testOnly org.apache.pekko.remote.InboundRemoteDeployment*",sbt +mimaReportBinaryIssues,scalafmt --mode diff-ref=origin/main,sbt headerCreateAllandsbt docs/paradoxcould not be executed and need to run in CI. No public API, binary shape orserialization format was changed:
RemoteSystemDaemon's constructor signature is untouched and the newmembers are private.
References
None - enforce the documented
use-unsafe-remote-features-outside-clusterdeployment gate on thereceiving side.
Generated by Claude Code