diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/pleroma/web/plugs/http_signature_plug_test.exs | 219 | ||||
-rw-r--r-- | test/support/data_case.ex | 1 | ||||
-rw-r--r-- | test/support/http_signatures_proxy.ex | 9 | ||||
-rw-r--r-- | test/support/mocks.ex | 1 |
4 files changed, 123 insertions, 107 deletions
diff --git a/test/pleroma/web/plugs/http_signature_plug_test.exs b/test/pleroma/web/plugs/http_signature_plug_test.exs index b871d956e..5f049dc45 100644 --- a/test/pleroma/web/plugs/http_signature_plug_test.exs +++ b/test/pleroma/web/plugs/http_signature_plug_test.exs @@ -3,157 +3,162 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.Plugs.HTTPSignaturePlugTest do - use Pleroma.Web.ConnCase + use Pleroma.Web.ConnCase, async: true alias Pleroma.Web.Plugs.HTTPSignaturePlug + alias Pleroma.StubbedHTTPSignaturesMock, as: HTTPSignaturesMock + alias Pleroma.StaticStubbedConfigMock, as: ConfigMock import Plug.Conn import Phoenix.Controller, only: [put_format: 2] - import Mock + import Mox - test "it call HTTPSignatures to check validity if the actor signed it" do + test "it calls HTTPSignatures to check validity if the actor signed it" do params = %{"actor" => "http://mastodon.example.org/users/admin"} conn = build_conn(:get, "/doesntmattter", params) - with_mock HTTPSignatures, - validate_conn: fn _ -> true end, - signature_for_conn: fn _ -> - %{"keyId" => "http://mastodon.example.org/users/admin#main-key"} - end do - conn = - conn - |> put_req_header( - "signature", - "keyId=\"http://mastodon.example.org/users/admin#main-key" - ) - |> put_format("activity+json") - |> HTTPSignaturePlug.call(%{}) + HTTPSignaturesMock + |> expect(:validate_conn, fn _ -> true end) - assert conn.assigns.valid_signature == true - assert conn.halted == false - assert called(HTTPSignatures.validate_conn(:_)) - end + conn = + conn + |> put_req_header( + "signature", + "keyId=\"http://mastodon.example.org/users/admin#main-key" + ) + |> put_format("activity+json") + |> HTTPSignaturePlug.call(%{}) + + assert conn.assigns.valid_signature == true + assert conn.halted == false end describe "requires a signature when `authorized_fetch_mode` is enabled" do setup do - clear_config([:activitypub, :authorized_fetch_mode], true) - params = %{"actor" => "http://mastodon.example.org/users/admin"} conn = build_conn(:get, "/doesntmattter", params) |> put_format("activity+json") [conn: conn] end - test "when signature header is present", %{conn: conn} do - with_mock HTTPSignatures, - validate_conn: fn _ -> false end, - signature_for_conn: fn _ -> - %{"keyId" => "http://mastodon.example.org/users/admin#main-key"} - end do - conn = - conn - |> put_req_header( - "signature", - "keyId=\"http://mastodon.example.org/users/admin#main-key" - ) - |> HTTPSignaturePlug.call(%{}) - - assert conn.assigns.valid_signature == false - assert conn.halted == true - assert conn.status == 401 - assert conn.state == :sent - assert conn.resp_body == "Request not signed" - assert called(HTTPSignatures.validate_conn(:_)) - end - - with_mock HTTPSignatures, - validate_conn: fn _ -> true end, - signature_for_conn: fn _ -> - %{"keyId" => "http://mastodon.example.org/users/admin#main-key"} - end do - conn = - conn - |> put_req_header( - "signature", - "keyId=\"http://mastodon.example.org/users/admin#main-key" - ) - |> HTTPSignaturePlug.call(%{}) - - assert conn.assigns.valid_signature == true - assert conn.halted == false - assert called(HTTPSignatures.validate_conn(:_)) - end - end + test "when signature header is present", %{conn: orig_conn} do + ConfigMock + |> expect(:get, fn [:activitypub, :authorized_fetch_mode], false -> true end) + |> expect(:get, fn [:activitypub, :authorized_fetch_mode_exceptions], [] -> [] end) - test "halts the connection when `signature` header is not present", %{conn: conn} do - conn = HTTPSignaturePlug.call(conn, %{}) - assert conn.assigns[:valid_signature] == nil + HTTPSignaturesMock + |> expect(:validate_conn, 2, fn _ -> false end) + + conn = + orig_conn + |> put_req_header( + "signature", + "keyId=\"http://mastodon.example.org/users/admin#main-key" + ) + |> HTTPSignaturePlug.call(%{}) + + assert conn.assigns.valid_signature == false assert conn.halted == true assert conn.status == 401 assert conn.state == :sent assert conn.resp_body == "Request not signed" - end - test "exempts specific IPs from `authorized_fetch_mode_exceptions`", %{conn: conn} do - clear_config([:activitypub, :authorized_fetch_mode_exceptions], ["192.168.0.0/24"]) - - with_mock HTTPSignatures, validate_conn: fn _ -> false end do - conn = - conn - |> Map.put(:remote_ip, {192, 168, 0, 1}) - |> put_req_header( - "signature", - "keyId=\"http://mastodon.example.org/users/admin#main-key" - ) - |> HTTPSignaturePlug.call(%{}) - - assert conn.remote_ip == {192, 168, 0, 1} - assert conn.halted == false - assert called(HTTPSignatures.validate_conn(:_)) - end - end - end + ConfigMock + |> expect(:get, fn [:activitypub, :authorized_fetch_mode], false -> true end) + + HTTPSignaturesMock + |> expect(:validate_conn, fn _ -> true end) - test "rejects requests from `rejected_instances` when `authorized_fetch_mode` is enabled" do - clear_config([:activitypub, :authorized_fetch_mode], true) - clear_config([:instance, :rejected_instances], [{"mastodon.example.org", "no reason"}]) - - with_mock HTTPSignatures, - validate_conn: fn _ -> true end, - signature_for_conn: fn _ -> - %{"keyId" => "http://mastodon.example.org/users/admin#main-key"} - end do conn = - build_conn(:get, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"}) + orig_conn |> put_req_header( "signature", "keyId=\"http://mastodon.example.org/users/admin#main-key" ) - |> put_format("activity+json") |> HTTPSignaturePlug.call(%{}) assert conn.assigns.valid_signature == true + assert conn.halted == false + end + + test "halts the connection when `signature` header is not present", %{conn: conn} do + ConfigMock + |> expect(:get, fn [:activitypub, :authorized_fetch_mode], false -> true end) + |> expect(:get, fn [:activitypub, :authorized_fetch_mode_exceptions], [] -> [] end) + + conn = HTTPSignaturePlug.call(conn, %{}) + assert conn.assigns[:valid_signature] == nil assert conn.halted == true - assert called(HTTPSignatures.validate_conn(:_)) + assert conn.status == 401 + assert conn.state == :sent + assert conn.resp_body == "Request not signed" end - with_mock HTTPSignatures, - validate_conn: fn _ -> true end, - signature_for_conn: fn _ -> - %{"keyId" => "http://allowed.example.org/users/admin#main-key"} - end do + test "exempts specific IPs from `authorized_fetch_mode_exceptions`", %{conn: conn} do + ConfigMock + |> expect(:get, fn [:activitypub, :authorized_fetch_mode], false -> true end) + |> expect(:get, fn [:activitypub, :authorized_fetch_mode_exceptions], [] -> + ["192.168.0.0/24"] + end) + |> expect(:get, fn [:activitypub, :authorized_fetch_mode], false -> true end) + + HTTPSignaturesMock + |> expect(:validate_conn, 2, fn _ -> false end) + conn = - build_conn(:get, "/doesntmattter", %{"actor" => "http://allowed.example.org/users/admin"}) + conn + |> Map.put(:remote_ip, {192, 168, 0, 1}) |> put_req_header( "signature", - "keyId=\"http://allowed.example.org/users/admin#main-key" + "keyId=\"http://mastodon.example.org/users/admin#main-key" ) - |> put_format("activity+json") |> HTTPSignaturePlug.call(%{}) - assert conn.assigns.valid_signature == true + assert conn.remote_ip == {192, 168, 0, 1} assert conn.halted == false - assert called(HTTPSignatures.validate_conn(:_)) end end + + test "rejects requests from `rejected_instances` when `authorized_fetch_mode` is enabled" do + ConfigMock + |> expect(:get, fn [:activitypub, :authorized_fetch_mode], false -> true end) + |> expect(:get, fn [:instance, :rejected_instances] -> + [{"mastodon.example.org", "no reason"}] + end) + + HTTPSignaturesMock + |> expect(:validate_conn, fn _ -> true end) + + conn = + build_conn(:get, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"}) + |> put_req_header( + "signature", + "keyId=\"http://mastodon.example.org/users/admin#main-key" + ) + |> put_format("activity+json") + |> HTTPSignaturePlug.call(%{}) + + assert conn.assigns.valid_signature == true + assert conn.halted == true + + ConfigMock + |> expect(:get, fn [:activitypub, :authorized_fetch_mode], false -> true end) + |> expect(:get, fn [:instance, :rejected_instances] -> + [{"mastodon.example.org", "no reason"}] + end) + + HTTPSignaturesMock + |> expect(:validate_conn, fn _ -> true end) + + conn = + build_conn(:get, "/doesntmattter", %{"actor" => "http://allowed.example.org/users/admin"}) + |> put_req_header( + "signature", + "keyId=\"http://allowed.example.org/users/admin#main-key" + ) + |> put_format("activity+json") + |> HTTPSignaturePlug.call(%{}) + + assert conn.assigns.valid_signature == true + assert conn.halted == false + end end diff --git a/test/support/data_case.ex b/test/support/data_case.ex index 14403f0b8..52d4bef1a 100644 --- a/test/support/data_case.ex +++ b/test/support/data_case.ex @@ -116,6 +116,7 @@ defmodule Pleroma.DataCase do Mox.stub_with(Pleroma.Web.FederatorMock, Pleroma.Web.Federator) Mox.stub_with(Pleroma.ConfigMock, Pleroma.Config) Mox.stub_with(Pleroma.StaticStubbedConfigMock, Pleroma.Test.StaticConfig) + Mox.stub_with(Pleroma.StubbedHTTPSignaturesMock, Pleroma.Test.HTTPSignaturesProxy) end def ensure_local_uploader(context) do diff --git a/test/support/http_signatures_proxy.ex b/test/support/http_signatures_proxy.ex new file mode 100644 index 000000000..4c6b39d19 --- /dev/null +++ b/test/support/http_signatures_proxy.ex @@ -0,0 +1,9 @@ +defmodule Pleroma.Test.HTTPSignaturesProxy do + @behaviour Pleroma.HTTPSignaturesAPI + + @impl true + defdelegate validate_conn(conn), to: HTTPSignatures + + @impl true + defdelegate signature_for_conn(conn), to: HTTPSignatures +end diff --git a/test/support/mocks.ex b/test/support/mocks.ex index d906f0e1d..63cbc49ab 100644 --- a/test/support/mocks.ex +++ b/test/support/mocks.ex @@ -28,6 +28,7 @@ Mox.defmock(Pleroma.Web.FederatorMock, for: Pleroma.Web.Federator.Publishing) Mox.defmock(Pleroma.ConfigMock, for: Pleroma.Config.Getting) Mox.defmock(Pleroma.UnstubbedConfigMock, for: Pleroma.Config.Getting) Mox.defmock(Pleroma.StaticStubbedConfigMock, for: Pleroma.Config.Getting) +Mox.defmock(Pleroma.StubbedHTTPSignaturesMock, for: Pleroma.HTTPSignaturesAPI) Mox.defmock(Pleroma.LoggerMock, for: Pleroma.Logging) |