From ad04d12de63d559cc6398c58296afd04321adfbc Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 11 Jun 2019 16:06:03 +0700 Subject: [PATCH] Replace `MastodonAPIController.account_register/2` rate limiter --- config/config.exs | 6 +-- config/test.exs | 2 +- docs/config.md | 8 +-- lib/pleroma/plugs/rate_limit_plug.ex | 36 ------------- .../mastodon_api/mastodon_api_controller.ex | 10 +--- test/plugs/rate_limit_plug_test.exs | 50 ------------------- .../mastodon_api_controller_test.exs | 20 +------- 7 files changed, 7 insertions(+), 125 deletions(-) delete mode 100644 lib/pleroma/plugs/rate_limit_plug.ex delete mode 100644 test/plugs/rate_limit_plug_test.exs diff --git a/config/config.exs b/config/config.exs index d20d4fda9..3d2c6d48e 100644 --- a/config/config.exs +++ b/config/config.exs @@ -247,8 +247,6 @@ config :pleroma, :instance, skip_thread_containment: false, limit_unauthenticated_to_local_content: true -config :pleroma, :app_account_creation, enabled: true, max_requests: 25, interval: 1800 - config :pleroma, :markup, # XXX - unfortunately, inline images must be enabled by default right now, because # of custom emoji. Issue #275 discusses defanging that somehow. @@ -503,7 +501,9 @@ config :pleroma, :database, rum_enabled: false config :http_signatures, adapter: Pleroma.Signature -config :pleroma, :rate_limit, search: [{1000, 10}, {1000, 30}] +config :pleroma, :rate_limit, + search: [{1000, 10}, {1000, 30}], + app_account_creation: {1_800_000, 25} # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. diff --git a/config/test.exs b/config/test.exs index 7861b9598..95129f409 100644 --- a/config/test.exs +++ b/config/test.exs @@ -59,7 +59,7 @@ config :pleroma, Pleroma.ScheduledActivity, total_user_limit: 3, enabled: false -config :pleroma, :app_account_creation, max_requests: 5 +config :pleroma, :rate_limit, app_account_creation: {1000, 5} config :pleroma, :http_security, report_uri: "https://endpoint.com" diff --git a/docs/config.md b/docs/config.md index e31e2b90f..b62b80490 100644 --- a/docs/config.md +++ b/docs/config.md @@ -114,12 +114,6 @@ config :pleroma, Pleroma.Emails.Mailer, * `skip_thread_containment`: Skip filter out broken threads. The default is `false`. * `limit_unauthenticated_to_local_content`: Limit unauthenticated users to search for local statutes and users only. The default is `true`. -## :app_account_creation -REST API for creating an account settings -* `enabled`: Enable/disable registration -* `max_requests`: Number of requests allowed for creating accounts -* `interval`: Interval for restricting requests for one ip (seconds) - ## :logger * `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog, and `Quack.Logger` to log to Slack @@ -568,7 +562,7 @@ config :ueberauth, Ueberauth, providers: [ microsoft: {Ueberauth.Strategy.Microsoft, [callback_params: []]} ] - + # Keycloak # Note: make sure to add `keycloak:ueberauth_keycloak_strategy` entry to `OAUTH_CONSUMER_STRATEGIES` environment variable keycloak_url = "https://publicly-reachable-keycloak-instance.org:8080" diff --git a/lib/pleroma/plugs/rate_limit_plug.ex b/lib/pleroma/plugs/rate_limit_plug.ex deleted file mode 100644 index 466f64a79..000000000 --- a/lib/pleroma/plugs/rate_limit_plug.ex +++ /dev/null @@ -1,36 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Plugs.RateLimitPlug do - import Phoenix.Controller, only: [json: 2] - import Plug.Conn - - def init(opts), do: opts - - def call(conn, opts) do - enabled? = Pleroma.Config.get([:app_account_creation, :enabled]) - - case check_rate(conn, Map.put(opts, :enabled, enabled?)) do - {:ok, _count} -> conn - {:error, _count} -> render_error(conn) - %Plug.Conn{} = conn -> conn - end - end - - defp check_rate(conn, %{enabled: true} = opts) do - max_requests = opts[:max_requests] - bucket_name = conn.remote_ip |> Tuple.to_list() |> Enum.join(".") - - ExRated.check_rate(bucket_name, opts[:interval] * 1000, max_requests) - end - - defp check_rate(conn, _), do: conn - - defp render_error(conn) do - conn - |> put_status(:forbidden) - |> json(%{error: "Rate limit exceeded."}) - |> halt() - end -end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 20b08fda4..46049dd24 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -46,15 +46,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do require Logger - plug( - Pleroma.Plugs.RateLimitPlug, - %{ - max_requests: Config.get([:app_account_creation, :max_requests]), - interval: Config.get([:app_account_creation, :interval]) - } - when action in [:account_register] - ) - + plug(Pleroma.Plugs.RateLimiter, :app_account_creation when action == :account_register) plug(Pleroma.Plugs.RateLimiter, :search when action in [:search, :search2, :account_search]) @local_mastodon_name "Mastodon-Local" diff --git a/test/plugs/rate_limit_plug_test.exs b/test/plugs/rate_limit_plug_test.exs deleted file mode 100644 index 2ec9a8fb7..000000000 --- a/test/plugs/rate_limit_plug_test.exs +++ /dev/null @@ -1,50 +0,0 @@ -defmodule Pleroma.Plugs.RateLimitPlugTest do - use ExUnit.Case, async: true - use Plug.Test - - alias Pleroma.Plugs.RateLimitPlug - - @opts RateLimitPlug.init(%{max_requests: 5, interval: 1}) - - setup do - enabled = Pleroma.Config.get([:app_account_creation, :enabled]) - - Pleroma.Config.put([:app_account_creation, :enabled], true) - - on_exit(fn -> - Pleroma.Config.put([:app_account_creation, :enabled], enabled) - end) - - :ok - end - - test "it restricts by opts" do - conn = conn(:get, "/") - bucket_name = conn.remote_ip |> Tuple.to_list() |> Enum.join(".") - ms = 1000 - - conn = RateLimitPlug.call(conn, @opts) - {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5) - conn = RateLimitPlug.call(conn, @opts) - {2, 3, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5) - conn = RateLimitPlug.call(conn, @opts) - {3, 2, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5) - conn = RateLimitPlug.call(conn, @opts) - {4, 1, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5) - conn = RateLimitPlug.call(conn, @opts) - {5, 0, to_reset, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5) - conn = RateLimitPlug.call(conn, @opts) - assert conn.status == 403 - assert conn.halted - assert conn.resp_body == "{\"error\":\"Rate limit exceeded.\"}" - - Process.sleep(to_reset) - - conn = conn(:get, "/") - conn = RateLimitPlug.call(conn, @opts) - {1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5) - refute conn.status == 403 - refute conn.halted - refute conn.resp_body - end -end diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 33c8e209a..c569ae9dd 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -3501,24 +3501,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do end describe "create account by app" do - setup do - enabled = Pleroma.Config.get([:app_account_creation, :enabled]) - max_requests = Pleroma.Config.get([:app_account_creation, :max_requests]) - interval = Pleroma.Config.get([:app_account_creation, :interval]) - - Pleroma.Config.put([:app_account_creation, :enabled], true) - Pleroma.Config.put([:app_account_creation, :max_requests], 5) - Pleroma.Config.put([:app_account_creation, :interval], 1) - - on_exit(fn -> - Pleroma.Config.put([:app_account_creation, :enabled], enabled) - Pleroma.Config.put([:app_account_creation, :max_requests], max_requests) - Pleroma.Config.put([:app_account_creation, :interval], interval) - end) - - :ok - end - test "Account registration via Application", %{conn: conn} do conn = conn @@ -3621,7 +3603,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do agreement: true }) - assert json_response(conn, 403) == %{"error" => "Rate limit exceeded."} + assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"} end end