Add exclusion reasons, mix task to check enabled keys
Some checks are pending
ci/woodpecker/push/build-amd64 Pipeline is pending
ci/woodpecker/push/build-arm64 Pipeline is pending
ci/woodpecker/push/docs Pipeline is pending
ci/woodpecker/push/lint Pipeline is pending
ci/woodpecker/push/test Pipeline is pending
ci/woodpecker/pr/build-amd64 Pipeline is pending
ci/woodpecker/pr/build-arm64 Pipeline is pending
ci/woodpecker/pr/docs Pipeline is pending
ci/woodpecker/pr/lint Pipeline is pending
ci/woodpecker/pr/test Pipeline is pending

This commit is contained in:
FloatingGhost 2023-08-15 13:59:15 +01:00
parent d63bb3f6b1
commit 6f55ca14f2
4 changed files with 75 additions and 34 deletions

View file

@ -423,6 +423,7 @@
label: "URI Schemes", label: "URI Schemes",
type: :group, type: :group,
description: "URI schemes related settings", description: "URI schemes related settings",
db_exclusion_reasons: "Does not make sense to configure dynamically",
children: [ children: [
%{ %{
key: :valid_schemes, key: :valid_schemes,
@ -1638,6 +1639,7 @@
key: Pleroma.Web.MediaProxy.Invalidation.Script, key: Pleroma.Web.MediaProxy.Invalidation.Script,
type: :group, type: :group,
description: "Invalidation script settings", description: "Invalidation script settings",
db_exclusion_reason: "Provides an arbitrary execution path",
children: [ children: [
%{ %{
key: :script_path, key: :script_path,
@ -1751,6 +1753,7 @@
%{ %{
group: :web_push_encryption, group: :web_push_encryption,
key: :vapid_details, key: :vapid_details,
db_exclusion_reason: "Webserver secret keys",
label: "Vapid Details", label: "Vapid Details",
type: :group, type: :group,
description: description:
@ -1822,19 +1825,13 @@
%{ %{
group: :pleroma, group: :pleroma,
label: "Pleroma Admin Token", label: "Pleroma Admin Token",
type: :group,
description: description:
"Allows setting a token that can be used to authenticate requests with admin privileges without a normal user account token. Append the `admin_token` parameter to requests to utilize it. (Please reconsider using HTTP Basic Auth or OAuth-based authentication if possible)", "Allows setting a token that can be used to authenticate requests with admin privileges without a normal user account token. Append the `admin_token` parameter to requests to utilize it. (Please reconsider using HTTP Basic Auth or OAuth-based authentication if possible)",
children: [
%{
key: :admin_token,
type: :string, type: :string,
description: "Admin token",
suggestions: [ suggestions: [
"Please use a high entropy string or UUID" "Please use a high entropy string or UUID"
] ],
} db_exclusion_reason: "Can provide passwordless admin access"
]
}, },
%{ %{
group: :pleroma, group: :pleroma,
@ -2178,6 +2175,7 @@
label: "Pleroma Authenticator", label: "Pleroma Authenticator",
type: :group, type: :group,
description: "Authenticator", description: "Authenticator",
db_exclusion_reason: "Should be provided at boot-time",
children: [ children: [
%{ %{
key: Pleroma.Web.Auth.Authenticator, key: Pleroma.Web.Auth.Authenticator,
@ -2191,6 +2189,7 @@
key: :ldap, key: :ldap,
label: "LDAP", label: "LDAP",
type: :group, type: :group,
db_exclusion_reason: "Provides access to another service",
description: description:
"Use LDAP for user authentication. When a user logs in to the Pleroma instance, the name and password" <> "Use LDAP for user authentication. When a user logs in to the Pleroma instance, the name and password" <>
" will be verified by trying to authenticate (bind) to a LDAP server." <> " will be verified by trying to authenticate (bind) to a LDAP server." <>
@ -2590,6 +2589,7 @@
label: "Mime Types", label: "Mime Types",
type: :group, type: :group,
description: "Mime Types settings", description: "Mime Types settings",
db_exclusion_reason: "Should be provided at compile-time",
children: [ children: [
%{ %{
key: :types, key: :types,
@ -2796,6 +2796,7 @@
group: :cors_plug, group: :cors_plug,
label: "CORS plug config", label: "CORS plug config",
type: :group, type: :group,
db_exclusion_reason: "Should be provided at compile-time",
children: [ children: [
%{ %{
key: :max_age, key: :max_age,
@ -2953,6 +2954,7 @@
key: :modules, key: :modules,
type: :group, type: :group,
description: "Custom Runtime Modules", description: "Custom Runtime Modules",
db_exclusion_reason: "Allows for custom elixir execution",
children: [ children: [
%{ %{
key: :runtime_dir, key: :runtime_dir,
@ -3089,6 +3091,7 @@
group: :ex_aws, group: :ex_aws,
key: :s3, key: :s3,
type: :group, type: :group,
db_exclusion_reason: "Provides access to another service",
descriptions: "S3 service related settings", descriptions: "S3 service related settings",
children: [ children: [
%{ %{
@ -3468,6 +3471,7 @@
key: :argos_translate, key: :argos_translate,
type: :group, type: :group,
description: "ArgosTranslate Settings.", description: "ArgosTranslate Settings.",
db_exclusion_reason: "Excluded for being able to set arbitrary paths to executables",
children: [ children: [
%{ %{
key: :command_argos_translate, key: :command_argos_translate,

View file

@ -10,6 +10,7 @@ defmodule Mix.Tasks.Pleroma.Config do
alias Pleroma.ConfigDB alias Pleroma.ConfigDB
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.Config.ConfigurableFromDatabase
@shortdoc "Manages the location of the config" @shortdoc "Manages the location of the config"
@moduledoc File.read!("docs/docs/administration/CLI_tasks/config.md") @moduledoc File.read!("docs/docs/administration/CLI_tasks/config.md")
@ -244,6 +245,28 @@ def run(["delete", group]) do
end end
end end
# Primarily a developer tool to check nothing was missed from
# db configwhitelist
def run(["check-allowed"]) do
start_pleroma()
Pleroma.Docs.JSON.compile()
raw = Pleroma.Docs.JSON.compiled_descriptions()
whitelisted = Enum.filter(raw, &ConfigurableFromDatabase.whitelisted_config?/1)
raw_map = MapSet.new(raw)
whitelisted_map = MapSet.new(whitelisted)
IO.puts("Config keys defined in description.exs but not listed as explicitly allowed in the db")
IO.puts(" Please check that standard admins should not need to touch the listed settings whilst the server is live.")
IO.puts(" !! Please remember that admins are not neccesarily sysadmins nor are they immune to oauth/password leakage.")
IO.puts("-------------")
MapSet.difference(raw_map, whitelisted_map)
|> Enum.each(fn map ->
IO.puts("#{map[:group]}, #{map[:key]} (#{map[:label]})")
IO.puts(map[:db_exclusion_reason] || "No exclusion reason set")
IO.puts("++")
end)
end
@spec migrate_to_db(Path.t() | nil) :: any() @spec migrate_to_db(Path.t() | nil) :: any()
def migrate_to_db(file_path \\ nil) do def migrate_to_db(file_path \\ nil) do
with :ok <- Pleroma.Config.DeprecationWarnings.warn() do with :ok <- Pleroma.Config.DeprecationWarnings.warn() do

View file

@ -1,4 +1,6 @@
defmodule Pleroma.Config.ConfigurableFromDatabase do defmodule Pleroma.Config.ConfigurableFromDatabase do
alias Pleroma.Config
# Basically it's silly to let this be configurable # Basically it's silly to let this be configurable
# set a list of things that we can set in the database # set a list of things that we can set in the database
# this is mostly our stuff, with some extra in there # this is mostly our stuff, with some extra in there
@ -9,6 +11,7 @@ defmodule Pleroma.Config.ConfigurableFromDatabase do
{:pleroma, Pleroma.Upload}, {:pleroma, Pleroma.Upload},
{:pleroma, Pleroma.Uploaders.Local}, {:pleroma, Pleroma.Uploaders.Local},
{:pleroma, Pleroma.Uploaders.S3}, {:pleroma, Pleroma.Uploaders.S3},
{:pleroma, :auth},
{:pleroma, :emoji}, {:pleroma, :emoji},
{:pleroma, :http}, {:pleroma, :http},
{:pleroma, :instance}, {:pleroma, :instance},
@ -70,9 +73,34 @@ defmodule Pleroma.Config.ConfigurableFromDatabase do
{:pleroma, Pleroma.Search.Elasticsearch.Cluster}, {:pleroma, Pleroma.Search.Elasticsearch.Cluster},
{:pleroma, :translator}, {:pleroma, :translator},
{:pleroma, :deepl}, {:pleroma, :deepl},
{:pleroma, :libre_translate} {:pleroma, :libre_translate},
# But not argostranslate, because executables! # But not argostranslate, because executables!
{:pleroma, Pleroma.Upload.Filter.AnonymizeFilename},
{:pleroma, Pleroma.Upload.Filter.Mogrify},
{:pleroma, Pleroma.Workers.PurgeExpiredActivity},
{:pleroma, :rate_limit}
] ]
def allowed_groups, do: @allowed_groups def allowed_groups, do: @allowed_groups
def enabled, do: Config.get(:configurable_from_database)
def whitelisted_config?(group, key) do
allowed_groups()
|> Enum.any?(fn
{whitelisted_group} ->
group == inspect(whitelisted_group)
{whitelisted_group, whitelisted_key} ->
group == inspect(whitelisted_group) && key == inspect(whitelisted_key)
end)
end
def whitelisted_config?(%{group: group, key: key}) do
whitelisted_config?(group, key)
end
def whitelisted_config?(%{group: group} = config) do
whitelisted_config?(group, config[:key])
end
end end

View file

@ -8,6 +8,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
alias Pleroma.Config alias Pleroma.Config
alias Pleroma.ConfigDB alias Pleroma.ConfigDB
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Config.ConfigurableFromDatabase
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :update) plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :update)
@ -71,7 +72,11 @@ defp translate_children(item, _path) do
end end
def descriptions(conn, _params) do def descriptions(conn, _params) do
descriptions = Enum.filter(Pleroma.Docs.JSON.compiled_descriptions(), &whitelisted_config?/1) descriptions =
Enum.filter(
Pleroma.Docs.JSON.compiled_descriptions(),
&ConfigurableFromDatabase.whitelisted_config?/1
)
json(conn, translate_descriptions(descriptions)) json(conn, translate_descriptions(descriptions))
end end
@ -132,7 +137,7 @@ def update(%{body_params: %{configs: configs}} = conn, _) do
with :ok <- configurable_from_database() do with :ok <- configurable_from_database() do
results = results =
configs configs
|> Enum.filter(&whitelisted_config?/1) |> Enum.filter(&ConfigurableFromDatabase.whitelisted_config?/1)
|> Enum.map(fn |> Enum.map(fn
%{group: group, key: key, delete: true} = params -> %{group: group, key: key, delete: true} = params ->
ConfigDB.delete(%{group: group, key: key, subkeys: params[:subkeys]}) ConfigDB.delete(%{group: group, key: key, subkeys: params[:subkeys]})
@ -167,29 +172,10 @@ def update(%{body_params: %{configs: configs}} = conn, _) do
end end
defp configurable_from_database do defp configurable_from_database do
if Config.get(:configurable_from_database) do if ConfigurableFromDatabase.enabled() do
:ok :ok
else else
{:error, "You must enable configurable_from_database in your config file."} {:error, "You must enable configurable_from_database in your config file."}
end end
end end
defp whitelisted_config?(group, key) do
Pleroma.Config.ConfigurableFromDatabase.allowed_groups()
|> Enum.any?(fn
{whitelisted_group} ->
group == inspect(whitelisted_group)
{whitelisted_group, whitelisted_key} ->
group == inspect(whitelisted_group) && key == inspect(whitelisted_key)
end)
end
defp whitelisted_config?(%{group: group, key: key}) do
whitelisted_config?(group, key)
end
defp whitelisted_config?(%{group: group} = config) do
whitelisted_config?(group, config[:key])
end
end end