forked from AkkomaGang/akkoma
Add ability to obfuscate domains in MRF transparency
This commit is contained in:
parent
f11a6eb8dd
commit
85137f591f
6 changed files with 80 additions and 3 deletions
|
@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- support for fedibird-fe, and non-breaking API parity for it to function
|
- support for fedibird-fe, and non-breaking API parity for it to function
|
||||||
- support for setting instance languages in metadata
|
- support for setting instance languages in metadata
|
||||||
- support for reusing oauth tokens, and not requiring new authorizations
|
- support for reusing oauth tokens, and not requiring new authorizations
|
||||||
|
- the ability to obfuscate domains in your MRF descriptions
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- MFM parsing is now done on the backend by a modified version of ilja's parser -> https://akkoma.dev/AkkomaGang/mfm-parser
|
- MFM parsing is now done on the backend by a modified version of ilja's parser -> https://akkoma.dev/AkkomaGang/mfm-parser
|
||||||
|
|
|
@ -794,7 +794,8 @@
|
||||||
config :pleroma, :mrf,
|
config :pleroma, :mrf,
|
||||||
policies: [Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy, Pleroma.Web.ActivityPub.MRF.TagPolicy],
|
policies: [Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy, Pleroma.Web.ActivityPub.MRF.TagPolicy],
|
||||||
transparency: true,
|
transparency: true,
|
||||||
transparency_exclusions: []
|
transparency_exclusions: [],
|
||||||
|
transparency_obfuscate_domains: []
|
||||||
|
|
||||||
config :ex_aws, http_client: Pleroma.HTTP.ExAws
|
config :ex_aws, http_client: Pleroma.HTTP.ExAws
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@ To add configuration to your config file, you can copy it from the base config.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.KeywordPolicy`: Rejects or removes from the federated timeline or replaces keywords. (See [`:mrf_keyword`](#mrf_keyword)).
|
* `Pleroma.Web.ActivityPub.MRF.KeywordPolicy`: Rejects or removes from the federated timeline or replaces keywords. (See [`:mrf_keyword`](#mrf_keyword)).
|
||||||
* `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
|
* `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
|
||||||
* `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.
|
* `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.
|
||||||
|
* `transparency_obfuscate_domains`: Show domains with `*` in the middle, to censor them if needed. For example, `ridingho.me` will show as `rid*****.me`
|
||||||
|
|
||||||
## Federation
|
## Federation
|
||||||
### MRF policies
|
### MRF policies
|
||||||
|
|
|
@ -41,6 +41,16 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
||||||
suggestions: [
|
suggestions: [
|
||||||
"exclusion.com"
|
"exclusion.com"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :transparency_obfuscate_domains,
|
||||||
|
label: "MRF domain obfuscation",
|
||||||
|
type: {:list, :string},
|
||||||
|
description:
|
||||||
|
"Obfuscate domains in MRF transparency. This is useful if the domain you're blocking contains words you don't want displayed, but still want to disclose the MRF settings.",
|
||||||
|
suggestions: [
|
||||||
|
"badword.com"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,10 +256,35 @@ def filter(object) when is_binary(object) do
|
||||||
|
|
||||||
def filter(object), do: {:ok, object}
|
def filter(object), do: {:ok, object}
|
||||||
|
|
||||||
|
defp obfuscate(string) when is_binary(string) do
|
||||||
|
string
|
||||||
|
|> to_charlist()
|
||||||
|
|> Enum.with_index()
|
||||||
|
|> Enum.map(fn
|
||||||
|
{?., _index} ->
|
||||||
|
?.
|
||||||
|
|
||||||
|
{char, index} ->
|
||||||
|
if 3 <= index && index < String.length(string) - 3, do: ?*, else: char
|
||||||
|
end)
|
||||||
|
|> to_string()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_obfuscate(host, obfuscations) do
|
||||||
|
if MRF.subdomain_match?(obfuscations, host) do
|
||||||
|
obfuscate(host)
|
||||||
|
else
|
||||||
|
host
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def describe do
|
def describe do
|
||||||
exclusions = Config.get([:mrf, :transparency_exclusions]) |> MRF.instance_list_from_tuples()
|
exclusions = Config.get([:mrf, :transparency_exclusions]) |> MRF.instance_list_from_tuples()
|
||||||
|
|
||||||
|
obfuscations =
|
||||||
|
Config.get([:mrf, :transparency_obfuscate_domains], []) |> MRF.subdomains_regex()
|
||||||
|
|
||||||
mrf_simple_excluded =
|
mrf_simple_excluded =
|
||||||
Config.get(:mrf_simple)
|
Config.get(:mrf_simple)
|
||||||
|> Enum.map(fn {rule, instances} ->
|
|> Enum.map(fn {rule, instances} ->
|
||||||
|
@ -269,7 +294,7 @@ def describe do
|
||||||
mrf_simple =
|
mrf_simple =
|
||||||
mrf_simple_excluded
|
mrf_simple_excluded
|
||||||
|> Enum.map(fn {rule, instances} ->
|
|> Enum.map(fn {rule, instances} ->
|
||||||
{rule, Enum.map(instances, fn {host, _} -> host end)}
|
{rule, Enum.map(instances, fn {host, _} -> maybe_obfuscate(host, obfuscations) end)}
|
||||||
end)
|
end)
|
||||||
|> Map.new()
|
|> Map.new()
|
||||||
|
|
||||||
|
@ -286,7 +311,9 @@ def describe do
|
||||||
|> Enum.map(fn {rule, instances} ->
|
|> Enum.map(fn {rule, instances} ->
|
||||||
instances =
|
instances =
|
||||||
instances
|
instances
|
||||||
|> Enum.map(fn {host, reason} -> {host, %{"reason" => reason}} end)
|
|> Enum.map(fn {host, reason} ->
|
||||||
|
{maybe_obfuscate(host, obfuscations), %{"reason" => reason}}
|
||||||
|
end)
|
||||||
|> Map.new()
|
|> Map.new()
|
||||||
|
|
||||||
{rule, instances}
|
{rule, instances}
|
||||||
|
|
|
@ -216,6 +216,43 @@ test "has a matching host but only as:Public in to" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "describe/1" do
|
||||||
|
test "returns a description of the policy" do
|
||||||
|
clear_config([:mrf_simple, :reject], [
|
||||||
|
{"remote.instance", "did not give my catboy a burg"}
|
||||||
|
])
|
||||||
|
|
||||||
|
assert {:ok, %{mrf_simple: %{reject: ["remote.instance"]}}} = SimplePolicy.describe()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "excludes domains listed in :transparency_exclusions" do
|
||||||
|
clear_config([:mrf, :transparency_exclusions], [{"remote.instance", ":("}])
|
||||||
|
|
||||||
|
clear_config([:mrf_simple, :reject], [
|
||||||
|
{"remote.instance", "did not give my catboy a burg"}
|
||||||
|
])
|
||||||
|
|
||||||
|
{:ok, description} = SimplePolicy.describe()
|
||||||
|
assert %{mrf_simple: %{reject: []}} = description
|
||||||
|
assert description[:mrf_simple_info][:reject] == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
test "obfuscates domains listed in :transparency_obfuscate_domains" do
|
||||||
|
clear_config([:mrf, :transparency_obfuscate_domains], ["remote.instance", "a.b"])
|
||||||
|
|
||||||
|
clear_config([:mrf_simple, :reject], [
|
||||||
|
{"remote.instance", "did not give my catboy a burg"},
|
||||||
|
{"a.b", "spam-poked me on facebook in 2006"}
|
||||||
|
])
|
||||||
|
|
||||||
|
assert {:ok,
|
||||||
|
%{
|
||||||
|
mrf_simple: %{reject: ["rem***.*****nce", "a.b"]},
|
||||||
|
mrf_simple_info: %{reject: %{"rem***.*****nce" => %{}}}
|
||||||
|
}} = SimplePolicy.describe()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp build_ftl_actor_and_message do
|
defp build_ftl_actor_and_message do
|
||||||
actor = insert(:user)
|
actor = insert(:user)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue