Merge branch 'fix-losing-relay-private-keys' into 'main'
fix(federation): prevent fetching own relay actor See merge request framasoft/mobilizon!1409
This commit is contained in:
commit
d300f9deea
@ -22,7 +22,9 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
|
|||||||
| {:error,
|
| {:error,
|
||||||
:invalid_url | :http_gone | :http_error | :http_not_found | :content_not_json}
|
:invalid_url | :http_gone | :http_error | :http_not_found | :content_not_json}
|
||||||
def fetch(url, options \\ []) do
|
def fetch(url, options \\ []) do
|
||||||
on_behalf_of = Keyword.get(options, :on_behalf_of, Relay.get_actor())
|
Logger.debug("Fetching #{url} with AP Fetcher")
|
||||||
|
on_behalf_of = Keyword.get(options, :on_behalf_of, actor_relay())
|
||||||
|
Logger.debug("Fetching on behalf of #{inspect(on_behalf_of.url)}")
|
||||||
date = Signature.generate_date_header()
|
date = Signature.generate_date_header()
|
||||||
|
|
||||||
headers =
|
headers =
|
||||||
@ -32,29 +34,8 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
|
|||||||
|
|
||||||
client = ActivityPubClient.client(headers: headers)
|
client = ActivityPubClient.client(headers: headers)
|
||||||
|
|
||||||
if address_valid?(url) do
|
if address_valid?(url) and url != on_behalf_of.url do
|
||||||
case ActivityPubClient.get(client, url) do
|
do_fetch(url, client)
|
||||||
{:ok, %Tesla.Env{body: data, status: code}} when code in 200..299 and is_map(data) ->
|
|
||||||
{:ok, data}
|
|
||||||
|
|
||||||
{:ok, %Tesla.Env{status: 410}} ->
|
|
||||||
Logger.debug("Resource at #{url} is 410 Gone")
|
|
||||||
{:error, :http_gone}
|
|
||||||
|
|
||||||
{:ok, %Tesla.Env{status: 404}} ->
|
|
||||||
Logger.debug("Resource at #{url} is 404 Gone")
|
|
||||||
{:error, :http_not_found}
|
|
||||||
|
|
||||||
{:ok, %Tesla.Env{body: data}} when is_binary(data) ->
|
|
||||||
{:error, :content_not_json}
|
|
||||||
|
|
||||||
{:ok, %Tesla.Env{} = res} ->
|
|
||||||
Logger.debug("Resource returned bad HTTP code #{inspect(res)}")
|
|
||||||
{:error, :http_error}
|
|
||||||
|
|
||||||
{:error, err} ->
|
|
||||||
{:error, err}
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
{:error, :invalid_url}
|
{:error, :invalid_url}
|
||||||
end
|
end
|
||||||
@ -169,4 +150,38 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
|
|||||||
%URI{host: host, scheme: scheme} = URI.parse(address)
|
%URI{host: host, scheme: scheme} = URI.parse(address)
|
||||||
is_valid_string(host) and is_valid_string(scheme)
|
is_valid_string(host) and is_valid_string(scheme)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp actor_relay do
|
||||||
|
Relay.get_actor()
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec do_fetch(String.t(), Tesla.Client.t()) ::
|
||||||
|
{:ok, map()}
|
||||||
|
| {:error,
|
||||||
|
:invalid_url | :http_gone | :http_error | :http_not_found | :content_not_json}
|
||||||
|
defp do_fetch(url, client) do
|
||||||
|
case ActivityPubClient.get(client, url) do
|
||||||
|
{:ok, %Tesla.Env{body: data, status: code}} when code in 200..299 and is_map(data) ->
|
||||||
|
Logger.debug("Found the following from ActivityPubClient fetch: #{inspect(data)}")
|
||||||
|
{:ok, data}
|
||||||
|
|
||||||
|
{:ok, %Tesla.Env{status: 410}} ->
|
||||||
|
Logger.debug("Resource at #{url} is 410 Gone")
|
||||||
|
{:error, :http_gone}
|
||||||
|
|
||||||
|
{:ok, %Tesla.Env{status: 404}} ->
|
||||||
|
Logger.debug("Resource at #{url} is 404 Gone")
|
||||||
|
{:error, :http_not_found}
|
||||||
|
|
||||||
|
{:ok, %Tesla.Env{body: data}} when is_binary(data) ->
|
||||||
|
{:error, :content_not_json}
|
||||||
|
|
||||||
|
{:ok, %Tesla.Env{} = res} ->
|
||||||
|
Logger.debug("Resource returned bad HTTP code #{inspect(res)}")
|
||||||
|
{:error, :http_error}
|
||||||
|
|
||||||
|
{:error, err} ->
|
||||||
|
{:error, err}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -55,7 +55,7 @@ defmodule Mobilizon.Federation.ActivityPub.Refresher do
|
|||||||
@type fetch_actor_errors :: ActivityPubActor.make_actor_errors() | fetch_collection_errors()
|
@type fetch_actor_errors :: ActivityPubActor.make_actor_errors() | fetch_collection_errors()
|
||||||
|
|
||||||
@spec fetch_group(String.t(), Actor.t()) :: :ok | {:error, fetch_actor_errors}
|
@spec fetch_group(String.t(), Actor.t()) :: :ok | {:error, fetch_actor_errors}
|
||||||
def fetch_group(group_url, %Actor{} = on_behalf_of) do
|
def fetch_group(group_url, %Actor{} = on_behalf_of) when is_binary(group_url) do
|
||||||
Logger.debug("Fetching group #{group_url}")
|
Logger.debug("Fetching group #{group_url}")
|
||||||
|
|
||||||
case ActivityPubActor.make_actor_from_url(group_url, on_behalf_of: on_behalf_of) do
|
case ActivityPubActor.make_actor_from_url(group_url, on_behalf_of: on_behalf_of) do
|
||||||
|
@ -12,6 +12,7 @@ defmodule Mobilizon.Federation.HTTPSignatures.Signature do
|
|||||||
|
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor
|
alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor
|
||||||
|
alias Mobilizon.Federation.ActivityPub.Relay
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@ -94,13 +95,19 @@ defmodule Mobilizon.Federation.HTTPSignatures.Signature do
|
|||||||
%{"keyId" => kid} = HTTPSignatures.signature_for_conn(conn)
|
%{"keyId" => kid} = HTTPSignatures.signature_for_conn(conn)
|
||||||
actor_url = key_id_to_actor_url(kid)
|
actor_url = key_id_to_actor_url(kid)
|
||||||
Logger.debug("Refetching public key for #{actor_url}")
|
Logger.debug("Refetching public key for #{actor_url}")
|
||||||
|
relay = Relay.get_actor()
|
||||||
|
|
||||||
# In this specific case we don't sign object fetches because
|
if actor_url == relay.url do
|
||||||
# this would cause infinite recursion when servers both need
|
# Special case if ever it's our own actor fetching ourselves
|
||||||
# to fetch each other's keys
|
get_actor_public_key(relay)
|
||||||
with {:ok, %Actor{} = actor} <-
|
else
|
||||||
ActivityPubActor.make_actor_from_url(actor_url, ignore_sign_object_fetches: true) do
|
# In this specific case we don't sign object fetches because
|
||||||
get_actor_public_key(actor)
|
# this would cause infinite recursion when servers both need
|
||||||
|
# to fetch each other's keys
|
||||||
|
with {:ok, %Actor{} = actor} <-
|
||||||
|
ActivityPubActor.make_actor_from_url(actor_url, ignore_sign_object_fetches: true) do
|
||||||
|
get_actor_public_key(actor)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user