Make FrontEndAnalytics provide CSP configuration

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2022-04-06 16:53:20 +02:00
parent da2254089c
commit e3adc0684f
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
6 changed files with 59 additions and 9 deletions

View File

@ -13,7 +13,12 @@ defmodule Mobilizon.Service.FrontEndAnalytics do
@doc """ @doc """
The configuration for the service The configuration for the service
""" """
@callback configuration() :: map() @callback configuration() :: keyword()
@doc """
The CSP configuration to add for the service to work
"""
@callback csp() :: keyword()
@spec providers :: list(module()) @spec providers :: list(module())
def providers do def providers do
@ -27,7 +32,14 @@ defmodule Mobilizon.Service.FrontEndAnalytics do
Enum.reduce(providers(), [], &load_config/2) Enum.reduce(providers(), [], &load_config/2)
end end
@spec load_config(module(), map()) :: map() @spec csp :: keyword()
def csp do
providers()
|> Enum.map(& &1.csp())
|> Enum.reduce([], &merge_csp_config/2)
end
@spec load_config(module(), list(map())) :: list(map())
defp load_config(provider, acc) do defp load_config(provider, acc) do
acc ++ acc ++
[ [
@ -50,4 +62,10 @@ defmodule Mobilizon.Service.FrontEndAnalytics do
defp type(val) when is_float(val), do: :float defp type(val) when is_float(val), do: :float
defp type(val) when is_boolean(val), do: :boolean defp type(val) when is_boolean(val), do: :boolean
defp type(val) when is_binary(val), do: :string defp type(val) when is_binary(val), do: :string
defp merge_csp_config(config, global_config) do
Keyword.merge(global_config, config, fn _key, global, config ->
"#{global} #{config}"
end)
end
end end

View File

@ -25,6 +25,16 @@ defmodule Mobilizon.Service.FrontEndAnalytics.Matomo do
def configuration do def configuration do
:mobilizon :mobilizon
|> Application.get_env(__MODULE__, []) |> Application.get_env(__MODULE__, [])
|> Keyword.drop([:enabled]) |> Keyword.drop([:enabled, :csp])
end
@doc """
The CSP configuration to add for the service to work
"""
@impl FrontEndAnalytics
def csp do
:mobilizon
|> Application.get_env(__MODULE__, [])
|> Keyword.get(:csp, [])
end end
end end

View File

@ -26,6 +26,16 @@ defmodule Mobilizon.Service.FrontEndAnalytics.Plausible do
def configuration do def configuration do
:mobilizon :mobilizon
|> Application.get_env(__MODULE__, []) |> Application.get_env(__MODULE__, [])
|> Keyword.drop([:enabled]) |> Keyword.drop([:enabled, :csp])
end
@doc """
The CSP configuration to add for the service to work
"""
@impl FrontEndAnalytics
def csp do
:mobilizon
|> Application.get_env(__MODULE__, [])
|> Keyword.get(:csp, [])
end end
end end

View File

@ -26,6 +26,16 @@ defmodule Mobilizon.Service.FrontEndAnalytics.Sentry do
def configuration do def configuration do
:mobilizon :mobilizon
|> Application.get_env(__MODULE__, []) |> Application.get_env(__MODULE__, [])
|> Keyword.drop([:enabled]) |> Keyword.drop([:enabled, :csp])
end
@doc """
The CSP configuration to add for the service to work
"""
@impl FrontEndAnalytics
def csp do
:mobilizon
|> Application.get_env(__MODULE__, [])
|> Keyword.get(:csp, [])
end end
end end

View File

@ -9,6 +9,7 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
""" """
alias Mobilizon.Config alias Mobilizon.Config
alias Mobilizon.Service.FrontEndAnalytics
import Plug.Conn import Plug.Conn
require Logger require Logger
@ -136,8 +137,9 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
@spec get_csp_config(atom(), Keyword.t()) :: iodata() @spec get_csp_config(atom(), Keyword.t()) :: iodata()
defp get_csp_config(type, options) do defp get_csp_config(type, options) do
options config_policy = Keyword.get(options, type, Config.get([:http_security, :csp_policy, type]))
|> Keyword.get(type, Config.get([:http_security, :csp_policy, type])) front_end_analytics_policy = [Keyword.get(FrontEndAnalytics.csp(), type, [])]
|> Enum.join(" ")
Enum.join(config_policy ++ front_end_analytics_policy, " ")
end end
end end

View File

@ -73,7 +73,7 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlugTest do
[csp] = Conn.get_resp_header(conn, "content-security-policy") [csp] = Conn.get_resp_header(conn, "content-security-policy")
assert csp =~ assert csp =~
~r/script-src 'self' 'unsafe-eval' 'sha256-[\w+\/=]*' example.com matomo.example.com;/ ~r/script-src 'self' 'unsafe-eval' 'sha256-[\w+\/=]*' example.com matomo.example.com ;/
end end
end end