Removing, deprecating and replacing usage of black/whitelist (#29254)
This commit is contained in:
parent
25ea7b7f5e
commit
1e9e984727
23 changed files with 168 additions and 144 deletions
|
|
@ -105,14 +105,14 @@ The procedure for changing from Java serialization to Jackson would look like:
|
|||
described in @ref:[Serialization with Jackson](../serialization-jackson.md).
|
||||
* Test the system with the new serialization in a new test cluster (no rolling update).
|
||||
* Remove the binding for the marker interface in `akka.actor.serialization-bindings`, so that Jackson is not used for serialization (toBinary) yet.
|
||||
* Configure `akka.serialization.jackson.whitelist-class-prefix=["com.myapp"]`
|
||||
* Configure `akka.serialization.jackson.allowed-class-prefix=["com.myapp"]`
|
||||
* This is needed for Jackson deserialization when the `serialization-bindings` isn't defined.
|
||||
* Replace `com.myapp` with the name of the root package of your application to trust all classes.
|
||||
* Roll out the change.
|
||||
* Java serialization is still used, but this version is prepared for next roll out.
|
||||
1. Rolling update to enable serialization with Jackson.
|
||||
* Add the binding to the marker interface in `akka.actor.serialization-bindings` to the Jackson serializer.
|
||||
* Remove `akka.serialization.jackson.whitelist-class-prefix`.
|
||||
* Remove `akka.serialization.jackson.allowed-class-prefix`.
|
||||
* Roll out the change.
|
||||
* Old nodes will still send messages with Java serialization, and that can still be deserialized by new nodes.
|
||||
* New nodes will send messages with Jackson serialization, and old node can deserialize those because they were
|
||||
|
|
|
|||
|
|
@ -271,22 +271,22 @@ Scala
|
|||
Java
|
||||
: @@snip [RemoteDeploymentDocTest.java](/akka-docs/src/test/java/jdocs/remoting/RemoteDeploymentDocTest.java) { #deploy }
|
||||
|
||||
### Remote deployment whitelist
|
||||
### Remote deployment allow list
|
||||
|
||||
As remote deployment can potentially be abused by both users and even attackers a whitelist feature
|
||||
As remote deployment can potentially be abused by both users and even attackers an allow list feature
|
||||
is available to guard the ActorSystem from deploying unexpected actors. Please note that remote deployment
|
||||
is *not* remote code loading, the Actors class to be deployed onto a remote system needs to be present on that
|
||||
remote system. This still however may pose a security risk, and one may want to restrict remote deployment to
|
||||
only a specific set of known actors by enabling the whitelist feature.
|
||||
only a specific set of known actors by enabling the allow list feature.
|
||||
|
||||
To enable remote deployment whitelisting set the `akka.remote.deployment.enable-whitelist` value to `on`.
|
||||
To enable remote deployment allow list set the `akka.remote.deployment.enable-allow-list` value to `on`.
|
||||
The list of allowed classes has to be configured on the "remote" system, in other words on the system onto which
|
||||
others will be attempting to remote deploy Actors. That system, locally, knows best which Actors it should or
|
||||
should not allow others to remote deploy onto it. The full settings section may for example look like this:
|
||||
|
||||
@@snip [RemoteDeploymentWhitelistSpec.scala](/akka-remote/src/test/scala/akka/remote/classic/RemoteDeploymentWhitelistSpec.scala) { #whitelist-config }
|
||||
@@snip [RemoteDeploymentAllowListSpec.scala](/akka-remote/src/test/scala/akka/remote/classic/RemoteDeploymentAllowListSpec.scala) { #allow-list-config }
|
||||
|
||||
Actor classes not included in the whitelist will not be allowed to be remote deployed onto this system.
|
||||
Actor classes not included in the allow list will not be allowed to be remote deployed onto this system.
|
||||
|
||||
## Lifecycle and Failure Recovery Model
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ to ensure that a fix can be provided without delay.
|
|||
## Security Related Documentation
|
||||
|
||||
* @ref:[Java Serialization](../serialization.md#java-serialization)
|
||||
* @ref:[Remote deployment whitelist](../remoting.md#remote-deployment-whitelist)
|
||||
* @ref:[Remote deployment allow list](../remoting.md#remote-deployment-allow-list)
|
||||
* @ref:[Remote Security](../remoting-artery.md#remote-security)
|
||||
|
||||
## Fixed Security Vulnerabilities
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ such as:
|
|||
* `java.io.Serializable`
|
||||
* `java.util.Comparable`.
|
||||
|
||||
The blacklist of possible serialization gadget classes defined by Jackson databind are checked
|
||||
The deny list of possible serialization gadget classes defined by Jackson databind are checked
|
||||
and disallowed for deserialization.
|
||||
|
||||
@@@ warning
|
||||
|
|
@ -350,12 +350,12 @@ That type of migration must be configured with the old class name as key. The ac
|
|||
### Remove from serialization-bindings
|
||||
|
||||
When a class is not used for serialization any more it can be removed from `serialization-bindings` but to still
|
||||
allow deserialization it must then be listed in the `whitelist-class-prefix` configuration. This is useful for example
|
||||
allow deserialization it must then be listed in the `allowed-class-prefix` configuration. This is useful for example
|
||||
during rolling update with serialization changes, or when reading old stored data. It can also be used
|
||||
when changing from Jackson serializer to another serializer (e.g. Protobuf) and thereby changing the serialization
|
||||
binding, but it should still be possible to deserialize old data with Jackson.
|
||||
|
||||
@@snip [config](/akka-serialization-jackson/src/test/scala/doc/akka/serialization/jackson/SerializationDocSpec.scala) { #whitelist-class-prefix }
|
||||
@@snip [config](/akka-serialization-jackson/src/test/scala/doc/akka/serialization/jackson/SerializationDocSpec.scala) { #allowed-class-prefix }
|
||||
|
||||
It's a list of class names or prefixes of class names.
|
||||
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@ Java
|
|||
: @@snip [StatefulMapConcat.java](/akka-docs/src/test/java/jdocs/stream/operators/flow/StatefulMapConcat.java) { #zip-with-index }
|
||||
|
||||
In this sample we let the value of the elements have an effect on the following elements, if an element starts
|
||||
with `blacklist:word` we add it to a black list and filter out any subsequent entries of `word`:
|
||||
with `deny:word` we add it to a deny list and filter out any subsequent entries of `word`:
|
||||
|
||||
Scala
|
||||
: @@snip [StatefulMapConcat.scala](/akka-docs/src/test/scala/docs/stream/operators/flow/StatefulMapConcat.scala) { #blacklist }
|
||||
: @@snip [StatefulMapConcat.scala](/akka-docs/src/test/scala/docs/stream/operators/flow/StatefulMapConcat.scala) { #denylist }
|
||||
|
||||
Java
|
||||
: @@snip [StatefulMapConcat.java](/akka-docs/src/test/java/jdocs/stream/operators/flow/StatefulMapConcat.java) { #blacklist }
|
||||
: @@snip [StatefulMapConcat.java](/akka-docs/src/test/java/jdocs/stream/operators/flow/StatefulMapConcat.java) { #denylist }
|
||||
|
||||
For cases where there is a need to emit elements based on the state when the stream ends, it is possible to add an extra
|
||||
element signalling the end of the stream before the `statefulMapConcat` operator.
|
||||
|
|
|
|||
|
|
@ -43,40 +43,39 @@ public class StatefulMapConcat {
|
|||
// #zip-with-index
|
||||
}
|
||||
|
||||
static void blacklist() {
|
||||
// #blacklist
|
||||
Source<String, NotUsed> fruitsAndBlacklistCommands =
|
||||
static void denylist() {
|
||||
// #denylist
|
||||
Source<String, NotUsed> fruitsAndDenyCommands =
|
||||
Source.from(
|
||||
Arrays.asList(
|
||||
"banana", "pear", "orange", "blacklist:banana", "banana", "pear", "banana"));
|
||||
Arrays.asList("banana", "pear", "orange", "deny:banana", "banana", "pear", "banana"));
|
||||
|
||||
Flow<String, String, NotUsed> blacklistingFlow =
|
||||
Flow<String, String, NotUsed> denyFilterFlow =
|
||||
Flow.of(String.class)
|
||||
.statefulMapConcat(
|
||||
() -> {
|
||||
Set<String> blacklist = new HashSet<>();
|
||||
Set<String> denyList = new HashSet<>();
|
||||
|
||||
return (element) -> {
|
||||
if (element.startsWith("blacklist:")) {
|
||||
blacklist.add(element.substring(10));
|
||||
if (element.startsWith("deny:")) {
|
||||
denyList.add(element.substring(10));
|
||||
return Collections
|
||||
.emptyList(); // no element downstream when adding a blacklisted keyword
|
||||
} else if (blacklist.contains(element)) {
|
||||
.emptyList(); // no element downstream when adding a deny listed keyword
|
||||
} else if (denyList.contains(element)) {
|
||||
return Collections
|
||||
.emptyList(); // no element downstream if element is blacklisted
|
||||
.emptyList(); // no element downstream if element is deny listed
|
||||
} else {
|
||||
return Collections.singletonList(element);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
fruitsAndBlacklistCommands.via(blacklistingFlow).runForeach(System.out::println, system);
|
||||
fruitsAndDenyCommands.via(denyFilterFlow).runForeach(System.out::println, system);
|
||||
// prints
|
||||
// banana
|
||||
// pear
|
||||
// orange
|
||||
// pear
|
||||
// #blacklist
|
||||
// #denylist
|
||||
}
|
||||
|
||||
static void reactOnEnd() {
|
||||
|
|
|
|||
|
|
@ -34,33 +34,33 @@ class StatefulMapConcat {
|
|||
// #zip-with-index
|
||||
}
|
||||
|
||||
def blacklist(): Unit = {
|
||||
// #blacklist
|
||||
val fruitsAndBlacklistCommands = Source(
|
||||
"banana" :: "pear" :: "orange" :: "blacklist:banana" :: "banana" :: "pear" :: "banana" :: Nil)
|
||||
def denylist(): Unit = {
|
||||
// #denylist
|
||||
val fruitsAndDeniedCommands = Source(
|
||||
"banana" :: "pear" :: "orange" :: "deny:banana" :: "banana" :: "pear" :: "banana" :: Nil)
|
||||
|
||||
val blacklistingFlow = Flow[String].statefulMapConcat { () =>
|
||||
var blacklist = Set.empty[String]
|
||||
val denyFilterFlow = Flow[String].statefulMapConcat { () =>
|
||||
var denyList = Set.empty[String]
|
||||
|
||||
{ element =>
|
||||
if (element.startsWith("blacklist:")) {
|
||||
blacklist += element.drop(10)
|
||||
Nil // no element downstream when adding a blacklisted keyword
|
||||
} else if (blacklist(element)) {
|
||||
Nil // no element downstream if element is blacklisted
|
||||
if (element.startsWith("deny:")) {
|
||||
denyList += element.drop(10)
|
||||
Nil // no element downstream when adding a deny listed keyword
|
||||
} else if (denyList(element)) {
|
||||
Nil // no element downstream if element is deny listed
|
||||
} else {
|
||||
element :: Nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fruitsAndBlacklistCommands.via(blacklistingFlow).runForeach(println)
|
||||
fruitsAndDeniedCommands.via(denyFilterFlow).runForeach(println)
|
||||
// prints
|
||||
// banana
|
||||
// pear
|
||||
// orange
|
||||
// pear
|
||||
// #blacklist
|
||||
// #denylist
|
||||
}
|
||||
|
||||
def reactOnEnd(): Unit = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue