diff --git a/api/funkwhale_api/federation/actors.py b/api/funkwhale_api/federation/actors.py index 187bd8c95..5af1d4012 100644 --- a/api/funkwhale_api/federation/actors.py +++ b/api/funkwhale_api/federation/actors.py @@ -13,6 +13,7 @@ logger = logging.getLogger(__name__) def get_actor_data(actor_url): + logger.debug("Fetching actor %s", actor_url) response = session.get_session().get( actor_url, headers={"Accept": "application/activity+json"}, ) diff --git a/api/funkwhale_api/federation/authentication.py b/api/funkwhale_api/federation/authentication.py index b059b2f81..5f836087c 100644 --- a/api/funkwhale_api/federation/authentication.py +++ b/api/funkwhale_api/federation/authentication.py @@ -46,15 +46,14 @@ class SignatureAuthentication(authentication.BaseAuthentication): domain = urllib.parse.urlparse(actor_url).hostname allowed = models.Domain.objects.filter(name=domain, allowed=True).exists() if not allowed: + logger.debug("Actor domain %s is not on allow-list", domain) raise exceptions.BlockedActorOrDomain() try: actor = actors.get_actor(actor_url) except Exception as e: logger.info( - "Discarding HTTP request from blocked actor/domain %s, %s", - actor_url, - str(e), + "Discarding HTTP request from actor/domain %s, %s", actor_url, str(e), ) raise rest_exceptions.AuthenticationFailed( "Cannot fetch remote actor to authenticate signature" diff --git a/api/funkwhale_api/federation/views.py b/api/funkwhale_api/federation/views.py index 10a6ca972..dfb0b86f0 100644 --- a/api/funkwhale_api/federation/views.py +++ b/api/funkwhale_api/federation/views.py @@ -111,6 +111,13 @@ class ActorViewSet(FederationMixin, mixins.RetrieveModelMixin, viewsets.GenericV queryset = super().get_queryset() return queryset.exclude(channel__attributed_to=actors.get_service_actor()) + def get_permissions(self): + # cf #1999 it must be possible to fetch actors without being authenticated + # otherwise we end up in a loop + if self.action == "retrieve": + return [] + return super().get_permissions() + def retrieve(self, request, *args, **kwargs): instance = self.get_object() if utils.should_redirect_ap_to_html(request.headers.get("accept")): diff --git a/api/tests/federation/test_views.py b/api/tests/federation/test_views.py index 8b3ec8725..0e098465a 100644 --- a/api/tests/federation/test_views.py +++ b/api/tests/federation/test_views.py @@ -12,7 +12,7 @@ from funkwhale_api.federation import ( ) -def test_authenticate_skips_anonymous_fetch_when_allow_list_enabled( +def test_authenticate_allows_anonymous_actor_fetch_when_allow_list_enabled( preferences, api_client ): preferences["moderation__allow_list_enabled"] = True @@ -23,6 +23,17 @@ def test_authenticate_skips_anonymous_fetch_when_allow_list_enabled( ) response = api_client.get(url) + assert response.status_code == 200 + + +def test_authenticate_skips_anonymous_fetch_when_allow_list_enabled( + preferences, api_client, factories +): + preferences["moderation__allow_list_enabled"] = True + library = factories["music.Library"]() + url = reverse("federation:music:libraries-detail", kwargs={"uuid": library.uuid},) + response = api_client.get(url) + assert response.status_code == 403 diff --git a/changes/changelog.d/1999.bugfix b/changes/changelog.d/1999.bugfix new file mode 100644 index 000000000..2f8e73224 --- /dev/null +++ b/changes/changelog.d/1999.bugfix @@ -0,0 +1 @@ +Fixed broken federation with pods using allow-listing (#1999) \ No newline at end of file