[#1940] Applied rate limit for requests with bad `admin_token`. Added doc warnings...
authorIvan Tashkinov <ivantashkinov@gmail.com>
Tue, 14 Jul 2020 08:58:41 +0000 (11:58 +0300)
committerIvan Tashkinov <ivantashkinov@gmail.com>
Tue, 14 Jul 2020 08:58:41 +0000 (11:58 +0300)
config/description.exs
docs/configuration/cheatsheet.md
lib/pleroma/plugs/admin_secret_authentication_plug.ex
test/plugs/admin_secret_authentication_plug_test.exs

index 84dcdb87e06840699c54931a7b45e6b528fb4af2..8ec4b712f078f9e97283ed29afd4d5abe631950b 100644 (file)
@@ -2008,13 +2008,15 @@ config :pleroma, :config_description, [
     label: "Pleroma Admin Token",
     type: :group,
     description:
-      "Allows to set a token that can be used to authenticate with the admin api without using an actual user by giving it as the `admin_token` parameter",
+      "Allows to set a token that can be used to authenticate with the admin api without using an actual user by giving it as the `admin_token` parameter (risky; use HTTP Basic Auth or OAuth-based authentication if possible)",
     children: [
       %{
         key: :admin_token,
         type: :string,
         description: "Admin token",
-        suggestions: ["We recommend a secure random string or UUID"]
+        suggestions: [
+          "We recommend NOT setting the value do to increased security risk; if set, use a secure random long string or UUID (and change it as often as possible)"
+        ]
       }
     ]
   },
index f796330f1080b10ee80fbaa3c9a9684ab5477ee5..24b162ce797b34535b708b1ca4d2b135fbcddca2 100644 (file)
@@ -815,6 +815,8 @@ or
 curl -H "X-Admin-Token: somerandomtoken" "http://localhost:4000/api/pleroma/admin/users/invites"
 ```
 
+Warning: it's discouraged to use this feature because of the associated security risk: static / rarely changed instance-wide token is much weaker compared to email-password pair of a real admin user; consider using HTTP Basic Auth or OAuth-based authentication instead.
+
 ### :auth
 
 * `Pleroma.Web.Auth.PleromaAuthenticator`: default database authenticator.
index ff0328d4a658cab3819071b913802fbc408e801b..2e54df47a386bb6e02eb402981e09c5567d08cdc 100644 (file)
@@ -5,15 +5,19 @@
 defmodule Pleroma.Plugs.AdminSecretAuthenticationPlug do
   import Plug.Conn
 
-  alias Pleroma.User
   alias Pleroma.Plugs.OAuthScopesPlug
+  alias Pleroma.Plugs.RateLimiter
+  alias Pleroma.User
 
   def init(options) do
     options
   end
 
   def secret_token do
-    Pleroma.Config.get(:admin_token)
+    case Pleroma.Config.get(:admin_token) do
+      blank when blank in [nil, ""] -> nil
+      token -> token
+    end
   end
 
   def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
@@ -30,7 +34,7 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlug do
     if admin_token == secret_token() do
       assign_admin_user(conn)
     else
-      conn
+      handle_bad_token(conn)
     end
   end
 
@@ -38,8 +42,9 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlug do
     token = secret_token()
 
     case get_req_header(conn, "x-admin-token") do
+      blank when blank in [[], [""]] -> conn
       [^token] -> assign_admin_user(conn)
-      _ -> conn
+      _ -> handle_bad_token(conn)
     end
   end
 
@@ -48,4 +53,8 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlug do
     |> assign(:user, %User{is_admin: true})
     |> OAuthScopesPlug.skip_plug()
   end
+
+  defp handle_bad_token(conn) do
+    RateLimiter.call(conn, name: :authentication)
+  end
 end
index b541a7208432df85115c8af55b1b73a1f1c2ad5b..89df03c4b719bd56c33fa11e44dd0060fd91f0e4 100644 (file)
@@ -4,11 +4,14 @@
 
 defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do
   use Pleroma.Web.ConnCase, async: true
+
+  import Mock
   import Pleroma.Factory
 
   alias Pleroma.Plugs.AdminSecretAuthenticationPlug
   alias Pleroma.Plugs.OAuthScopesPlug
   alias Pleroma.Plugs.PlugHelper
+  alias Pleroma.Plugs.RateLimiter
 
   test "does nothing if a user is assigned", %{conn: conn} do
     user = insert(:user)
@@ -27,6 +30,10 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do
   describe "when secret set it assigns an admin user" do
     setup do: clear_config([:admin_token])
 
+    setup_with_mocks([{RateLimiter, [:passthrough], []}]) do
+      :ok
+    end
+
     test "with `admin_token` query parameter", %{conn: conn} do
       Pleroma.Config.put(:admin_token, "password123")
 
@@ -35,6 +42,7 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do
         |> AdminSecretAuthenticationPlug.call(%{})
 
       refute conn.assigns[:user]
+      assert called(RateLimiter.call(conn, name: :authentication))
 
       conn =
         %{conn | params: %{"admin_token" => "password123"}}
@@ -53,6 +61,7 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do
         |> AdminSecretAuthenticationPlug.call(%{})
 
       refute conn.assigns[:user]
+      assert called(RateLimiter.call(conn, name: :authentication))
 
       conn =
         conn