From fe67665e19cc98faff4a8ee53a3f4ca4190ca2ef Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 12 Nov 2018 15:08:02 +0000 Subject: rename CSPPlug to HTTPSecurityPlug. --- config/config.exs | 2 +- config/config.md | 2 +- lib/pleroma/plugs/csp_plug.ex | 57 ------------------------------ lib/pleroma/plugs/http_security_plug.ex | 57 ++++++++++++++++++++++++++++++ lib/pleroma/web/endpoint.ex | 2 +- test/plugs/csp_plug_test.exs | 61 --------------------------------- test/plugs/http_security_plug_test.exs | 61 +++++++++++++++++++++++++++++++++ 7 files changed, 121 insertions(+), 121 deletions(-) delete mode 100644 lib/pleroma/plugs/csp_plug.ex create mode 100644 lib/pleroma/plugs/http_security_plug.ex delete mode 100644 test/plugs/csp_plug_test.exs create mode 100644 test/plugs/http_security_plug_test.exs diff --git a/config/config.exs b/config/config.exs index 1d918919d..be9c03ceb 100644 --- a/config/config.exs +++ b/config/config.exs @@ -176,7 +176,7 @@ config :pleroma, :suggestions, limit: 23, web: "https://vinayaka.distsn.org/?{{host}}+{{user}}" -config :pleroma, :csp, +config :pleroma, :http_security, enabled: true, sts: false, sts_max_age: 31_536_000, diff --git a/config/config.md b/config/config.md index 446b0ce67..48af1c236 100644 --- a/config/config.md +++ b/config/config.md @@ -81,7 +81,7 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i * ``outgoing_blocks``: Whether to federate blocks to other instances * ``deny_follow_blocked``: Whether to disallow following an account that has blocked the user in question -## :csp +## :http_security * ``enabled``: Whether the managed content security policy is enabled * ``sts``: Whether to additionally send a `Strict-Transport-Security` header * ``sts_max_age``: The maximum age for the `Strict-Transport-Security` header if sent diff --git a/lib/pleroma/plugs/csp_plug.ex b/lib/pleroma/plugs/csp_plug.ex deleted file mode 100644 index 8fc21b909..000000000 --- a/lib/pleroma/plugs/csp_plug.ex +++ /dev/null @@ -1,57 +0,0 @@ -defmodule Pleroma.Plugs.CSPPlug do - alias Pleroma.Config - import Plug.Conn - - def init(opts), do: opts - - def call(conn, options) do - if Config.get([:csp, :enabled]) do - conn = - merge_resp_headers(conn, headers()) - |> maybe_send_sts_header(Config.get([:csp, :sts])) - else - conn - end - end - - defp headers do - [ - {"x-xss-protection", "1; mode=block"}, - {"x-permitted-cross-domain-policies", "none"}, - {"x-frame-options", "DENY"}, - {"x-content-type-options", "nosniff"}, - {"referrer-policy", "same-origin"}, - {"x-download-options", "noopen"}, - {"content-security-policy", csp_string() <> ";"} - ] - end - - defp csp_string do - [ - "default-src 'none'", - "base-uri 'self'", - "form-action *", - "frame-ancestors 'none'", - "img-src 'self' data: https:", - "media-src 'self' https:", - "style-src 'self' 'unsafe-inline'", - "font-src 'self'", - "script-src 'self'", - "connect-src 'self' " <> String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws"), - "upgrade-insecure-requests" - ] - |> Enum.join("; ") - end - - defp maybe_send_sts_header(conn, true) do - max_age_sts = Config.get([:csp, :sts_max_age]) - max_age_ct = Config.get([:csp, :ct_max_age]) - - merge_resp_headers(conn, [ - {"strict-transport-security", "max-age=#{max_age_sts}; includeSubDomains"}, - {"expect-ct", "enforce, max-age=#{max_age_ct}"} - ]) - end - - defp maybe_send_sts_header(conn, _), do: conn -end diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex new file mode 100644 index 000000000..8d652a2f3 --- /dev/null +++ b/lib/pleroma/plugs/http_security_plug.ex @@ -0,0 +1,57 @@ +defmodule Pleroma.Plugs.HTTPSecurityPlug do + alias Pleroma.Config + import Plug.Conn + + def init(opts), do: opts + + def call(conn, options) do + if Config.get([:http_security, :enabled]) do + conn = + merge_resp_headers(conn, headers()) + |> maybe_send_sts_header(Config.get([:http_security, :sts])) + else + conn + end + end + + defp headers do + [ + {"x-xss-protection", "1; mode=block"}, + {"x-permitted-cross-domain-policies", "none"}, + {"x-frame-options", "DENY"}, + {"x-content-type-options", "nosniff"}, + {"referrer-policy", "same-origin"}, + {"x-download-options", "noopen"}, + {"content-security-policy", csp_string() <> ";"} + ] + end + + defp csp_string do + [ + "default-src 'none'", + "base-uri 'self'", + "form-action *", + "frame-ancestors 'none'", + "img-src 'self' data: https:", + "media-src 'self' https:", + "style-src 'self' 'unsafe-inline'", + "font-src 'self'", + "script-src 'self'", + "connect-src 'self' " <> String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws"), + "upgrade-insecure-requests" + ] + |> Enum.join("; ") + end + + defp maybe_send_sts_header(conn, true) do + max_age_sts = Config.get([:http_security, :sts_max_age]) + max_age_ct = Config.get([:http_security, :ct_max_age]) + + merge_resp_headers(conn, [ + {"strict-transport-security", "max-age=#{max_age_sts}; includeSubDomains"}, + {"expect-ct", "enforce, max-age=#{max_age_ct}"} + ]) + end + + defp maybe_send_sts_header(conn, _), do: conn +end diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index 370d2d792..7783b8e5c 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -12,7 +12,7 @@ defmodule Pleroma.Web.Endpoint do # You should set gzip to true if you are running phoenix.digest # when deploying your static files in production. plug(CORSPlug) - plug(Pleroma.Plugs.CSPPlug) + plug(Pleroma.Plugs.HTTPSecurityPlug) plug(Plug.Static, at: "/media", from: Pleroma.Uploaders.Local.upload_path(), gzip: false) diff --git a/test/plugs/csp_plug_test.exs b/test/plugs/csp_plug_test.exs deleted file mode 100644 index e27b24db9..000000000 --- a/test/plugs/csp_plug_test.exs +++ /dev/null @@ -1,61 +0,0 @@ -defmodule Pleroma.Web.Plugs.CSPPlugTest do - use Pleroma.Web.ConnCase - alias Pleroma.Config - alias Plug.Conn - - test "it sends CSP headers when enabled", %{conn: conn} do - Config.put([:csp, :enabled], true) - - conn = - conn - |> get("/api/v1/instance") - - refute Conn.get_resp_header(conn, "x-xss-protection") == [] - refute Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == [] - refute Conn.get_resp_header(conn, "x-frame-options") == [] - refute Conn.get_resp_header(conn, "x-content-type-options") == [] - refute Conn.get_resp_header(conn, "x-download-options") == [] - refute Conn.get_resp_header(conn, "referrer-policy") == [] - refute Conn.get_resp_header(conn, "content-security-policy") == [] - end - - test "it does not send CSP headers when disabled", %{conn: conn} do - Config.put([:csp, :enabled], false) - - conn = - conn - |> get("/api/v1/instance") - - assert Conn.get_resp_header(conn, "x-xss-protection") == [] - assert Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == [] - assert Conn.get_resp_header(conn, "x-frame-options") == [] - assert Conn.get_resp_header(conn, "x-content-type-options") == [] - assert Conn.get_resp_header(conn, "x-download-options") == [] - assert Conn.get_resp_header(conn, "referrer-policy") == [] - assert Conn.get_resp_header(conn, "content-security-policy") == [] - end - - test "it sends STS headers when enabled", %{conn: conn} do - Config.put([:csp, :enabled], true) - Config.put([:csp, :sts], true) - - conn = - conn - |> get("/api/v1/instance") - - refute Conn.get_resp_header(conn, "strict-transport-security") == [] - refute Conn.get_resp_header(conn, "expect-ct") == [] - end - - test "it does not send STS headers when disabled", %{conn: conn} do - Config.put([:csp, :enabled], true) - Config.put([:csp, :sts], false) - - conn = - conn - |> get("/api/v1/instance") - - assert Conn.get_resp_header(conn, "strict-transport-security") == [] - assert Conn.get_resp_header(conn, "expect-ct") == [] - end -end diff --git a/test/plugs/http_security_plug_test.exs b/test/plugs/http_security_plug_test.exs new file mode 100644 index 000000000..5268a1972 --- /dev/null +++ b/test/plugs/http_security_plug_test.exs @@ -0,0 +1,61 @@ +defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do + use Pleroma.Web.ConnCase + alias Pleroma.Config + alias Plug.Conn + + test "it sends CSP headers when enabled", %{conn: conn} do + Config.put([:http_security, :enabled], true) + + conn = + conn + |> get("/api/v1/instance") + + refute Conn.get_resp_header(conn, "x-xss-protection") == [] + refute Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == [] + refute Conn.get_resp_header(conn, "x-frame-options") == [] + refute Conn.get_resp_header(conn, "x-content-type-options") == [] + refute Conn.get_resp_header(conn, "x-download-options") == [] + refute Conn.get_resp_header(conn, "referrer-policy") == [] + refute Conn.get_resp_header(conn, "content-security-policy") == [] + end + + test "it does not send CSP headers when disabled", %{conn: conn} do + Config.put([:http_security, :enabled], false) + + conn = + conn + |> get("/api/v1/instance") + + assert Conn.get_resp_header(conn, "x-xss-protection") == [] + assert Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == [] + assert Conn.get_resp_header(conn, "x-frame-options") == [] + assert Conn.get_resp_header(conn, "x-content-type-options") == [] + assert Conn.get_resp_header(conn, "x-download-options") == [] + assert Conn.get_resp_header(conn, "referrer-policy") == [] + assert Conn.get_resp_header(conn, "content-security-policy") == [] + end + + test "it sends STS headers when enabled", %{conn: conn} do + Config.put([:http_security, :enabled], true) + Config.put([:http_security, :sts], true) + + conn = + conn + |> get("/api/v1/instance") + + refute Conn.get_resp_header(conn, "strict-transport-security") == [] + refute Conn.get_resp_header(conn, "expect-ct") == [] + end + + test "it does not send STS headers when disabled", %{conn: conn} do + Config.put([:http_security, :enabled], true) + Config.put([:http_security, :sts], false) + + conn = + conn + |> get("/api/v1/instance") + + assert Conn.get_resp_header(conn, "strict-transport-security") == [] + assert Conn.get_resp_header(conn, "expect-ct") == [] + end +end -- cgit v1.2.3