From 2c5078e63ffca3432ade368ad8b9a3d02bcf3165 Mon Sep 17 00:00:00 2001 From: Jamil Date: Fri, 15 Apr 2022 09:56:56 -0700 Subject: [PATCH] Add WireGuard preshared-keys to devices (#542) * Add PSK support * Add HTTP registered application name * Better kernel check message * Does order matter\? --- .github/workflows/ci.yml | 2 +- .tool-versions | 4 +- apps/fz_common/lib/fz_crypto.ex | 17 +++++-- apps/fz_http/lib/fz_http/devices.ex | 25 ++++++++-- apps/fz_http/lib/fz_http/devices/device.ex | 2 + apps/fz_http/lib/fz_http/events.ex | 4 +- .../device_live/new_form_component.html.heex | 1 + apps/fz_http/lib/fz_http_web/mock_events.ex | 4 +- .../templates/shared/device_details.html.heex | 5 ++ apps/fz_http/mix.exs | 3 +- .../20220412144151_add_psk_to_devices.exs | 9 ++++ apps/fz_http/priv/repo/seeds.exs | 1 + apps/fz_http/test/fz_http/devices_test.exs | 5 ++ apps/fz_http/test/fz_http/events_test.exs | 14 ++++-- apps/fz_vpn/lib/fz_vpn/cli/live.ex | 10 ++-- apps/fz_vpn/lib/fz_vpn/cli/sandbox.ex | 15 +++--- apps/fz_vpn/lib/fz_vpn/config.ex | 48 ++++++++++++++++++- apps/fz_vpn/lib/fz_vpn/server.ex | 18 +++---- apps/fz_vpn/mix.exs | 1 + apps/fz_vpn/test/fz_vpn/config_test.exs | 19 ++++++-- apps/fz_vpn/test/fz_vpn/server_test.exs | 25 +++++----- apps/fz_wall/mix.exs | 1 + config/config.exs | 1 + config/releases.exs | 2 + docs/docs/reference/configuration-file.md | 9 ++++ mix.lock | 6 +-- .../cookbooks/firezone/libraries/config.rb | 1 + omnibus/cookbooks/firezone/recipes/config.rb | 6 +++ scripts/install.sh | 2 +- 29 files changed, 200 insertions(+), 60 deletions(-) create mode 100644 apps/fz_http/priv/repo/migrations/20220412144151_add_psk_to_devices.exs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 067f2dc99..b216a97f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -234,7 +234,7 @@ jobs: - opensuse15-x64 if: startsWith(github.ref, 'refs/tags/') steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 with: name: firezone-${{ matrix.platform }} path: ./ diff --git a/.tool-versions b/.tool-versions index 678c1ae3b..de849c898 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,6 +1,6 @@ # These are used for the dev environment. # This should match the versions used in the built product. nodejs 14.18.3 -elixir 1.13.2-otp-24 -erlang 24.2.1 +elixir ref:v1.13.4 +erlang 25.0-rc3 ruby 2.7.5 diff --git a/apps/fz_common/lib/fz_crypto.ex b/apps/fz_common/lib/fz_crypto.ex index a67da3a31..db9cc362b 100644 --- a/apps/fz_common/lib/fz_crypto.ex +++ b/apps/fz_common/lib/fz_crypto.ex @@ -3,17 +3,28 @@ defmodule FzCommon.FzCrypto do Utilities for working with crypto functions """ + @wg_psk_length 32 + + def psk do + rand_base64(@wg_psk_length) + end + def rand_string(length \\ 16) do - rand_base64(length) + rand_base64(length, :url) |> binary_part(0, length) end def rand_token(length \\ 8) do - rand_base64(length) + rand_base64(length, :url) + end + + defp rand_base64(length, :url) do + :crypto.strong_rand_bytes(length) + |> Base.url_encode64() end defp rand_base64(length) do :crypto.strong_rand_bytes(length) - |> Base.url_encode64() + |> Base.encode64() end end diff --git a/apps/fz_http/lib/fz_http/devices.ex b/apps/fz_http/lib/fz_http/devices.ex index 5322d62c8..2fdf4f663 100644 --- a/apps/fz_http/lib/fz_http/devices.ex +++ b/apps/fz_http/lib/fz_http/devices.ex @@ -4,7 +4,7 @@ defmodule FzHttp.Devices do """ import Ecto.Query, warn: false - alias FzCommon.NameGenerator + alias FzCommon.{FzCrypto, NameGenerator} alias FzHttp.{Devices.Device, Repo, Sites, Telemetry, Users, Users.User} def list_devices do @@ -93,13 +93,23 @@ defmodule FzHttp.Devices do |> Enum.map(fn device -> %{ public_key: device.public_key, - inet: inet(device) + inet: inet(device), + preshared_key: device.preshared_key } end) end def new_device(attrs \\ %{}) do - change_device(%Device{}, Map.merge(%{"name" => NameGenerator.generate()}, attrs)) + change_device( + %Device{}, + Map.merge( + %{ + "name" => NameGenerator.generate(), + "preshared_key" => FzCrypto.psk() + }, + attrs + ) + ) end def allowed_ips(device), do: config(device, :allowed_ips) @@ -142,6 +152,7 @@ defmodule FzHttp.Devices do #{dns_config(device)} [Peer] + #{psk_config(device)} PublicKey = #{server_public_key} #{allowed_ips_config(device)} Endpoint = #{endpoint(device)}:#{wireguard_port} @@ -149,6 +160,14 @@ defmodule FzHttp.Devices do """ end + defp psk_config(device) do + if device.preshared_key do + "PresharedKey = #{device.preshared_key}" + else + "" + end + end + defp mtu_config(device) do m = mtu(device) diff --git a/apps/fz_http/lib/fz_http/devices/device.ex b/apps/fz_http/lib/fz_http/devices/device.ex index 5136f70c8..67f9f2093 100644 --- a/apps/fz_http/lib/fz_http/devices/device.ex +++ b/apps/fz_http/lib/fz_http/devices/device.ex @@ -24,6 +24,7 @@ defmodule FzHttp.Devices.Device do field :uuid, Ecto.UUID, autogenerate: true field :name, :string field :public_key, :string + field :preshared_key, FzHttp.Encrypted.Binary field :use_site_allowed_ips, :boolean, read_after_writes: true, default: true field :use_site_dns, :boolean, read_after_writes: true, default: true field :use_site_endpoint, :boolean, read_after_writes: true, default: true @@ -83,6 +84,7 @@ defmodule FzHttp.Devices.Device do :user_id, :name, :public_key, + :preshared_key, :key_regenerated_at ]) end diff --git a/apps/fz_http/lib/fz_http/events.ex b/apps/fz_http/lib/fz_http/events.ex index 6eecd7a2b..0808b2692 100644 --- a/apps/fz_http/lib/fz_http/events.ex +++ b/apps/fz_http/lib/fz_http/events.ex @@ -11,8 +11,8 @@ defmodule FzHttp.Events do GenServer.call(vpn_pid(), {:set_config, Devices.to_peer_list()}) end - def delete_device(device_pubkey) when is_binary(device_pubkey) do - GenServer.call(vpn_pid(), {:remove_peer, device_pubkey}) + def delete_device(public_key) when is_binary(public_key) do + GenServer.call(vpn_pid(), {:remove_peer, public_key}) end def delete_device(device) when is_struct(device) do diff --git a/apps/fz_http/lib/fz_http_web/live/device_live/new_form_component.html.heex b/apps/fz_http/lib/fz_http_web/live/device_live/new_form_component.html.heex index dba10d274..c113130fc 100644 --- a/apps/fz_http/lib/fz_http_web/live/device_live/new_form_component.html.heex +++ b/apps/fz_http/lib/fz_http_web/live/device_live/new_form_component.html.heex @@ -53,6 +53,7 @@
<.form let={f} for={@changeset} id="create-device" phx-change="change" phx-target={@myself} phx-submit="save"> <%= hidden_input f, :public_key, id: "device-public-key", phx_hook: "GenerateKeyPair" %> + <%= hidden_input f, :preshared_key %> <%= if @changeset.action do %>
diff --git a/apps/fz_http/lib/fz_http_web/mock_events.ex b/apps/fz_http/lib/fz_http_web/mock_events.ex index 3295bebf2..4f5d47ff2 100644 --- a/apps/fz_http/lib/fz_http_web/mock_events.ex +++ b/apps/fz_http/lib/fz_http_web/mock_events.ex @@ -7,8 +7,8 @@ defmodule FzHttpWeb.MockEvents do inside FzHttp and use that for the tests. """ - def delete_device(pubkey) do - {:ok, pubkey} + def delete_device(public_key) do + {:ok, public_key} end def update_device(_device) do diff --git a/apps/fz_http/lib/fz_http_web/templates/shared/device_details.html.heex b/apps/fz_http/lib/fz_http_web/templates/shared/device_details.html.heex index e5610d18f..ab0ae713d 100644 --- a/apps/fz_http/lib/fz_http_web/templates/shared/device_details.html.heex +++ b/apps/fz_http/lib/fz_http_web/templates/shared/device_details.html.heex @@ -62,5 +62,10 @@ Public key <%= @device.public_key %> + + + Preshared Key + <%= @device.preshared_key %> + diff --git a/apps/fz_http/mix.exs b/apps/fz_http/mix.exs index 984b1f630..e7c6b225d 100644 --- a/apps/fz_http/mix.exs +++ b/apps/fz_http/mix.exs @@ -43,7 +43,8 @@ defmodule FzHttp.MixProject do :runtime_tools, :ueberauth_okta, :ueberauth_identity - ] + ], + registered: [:fz_http_server] ] end diff --git a/apps/fz_http/priv/repo/migrations/20220412144151_add_psk_to_devices.exs b/apps/fz_http/priv/repo/migrations/20220412144151_add_psk_to_devices.exs new file mode 100644 index 000000000..eee9fccf1 --- /dev/null +++ b/apps/fz_http/priv/repo/migrations/20220412144151_add_psk_to_devices.exs @@ -0,0 +1,9 @@ +defmodule FzHttp.Repo.Migrations.AddPskToDevices do + use Ecto.Migration + + def change do + alter table(:devices) do + add :preshared_key, :bytea + end + end +end diff --git a/apps/fz_http/priv/repo/seeds.exs b/apps/fz_http/priv/repo/seeds.exs index 8058ae73c..0b2f36538 100644 --- a/apps/fz_http/priv/repo/seeds.exs +++ b/apps/fz_http/priv/repo/seeds.exs @@ -23,6 +23,7 @@ alias FzHttp.{Devices, ConnectivityChecks, Rules, Users} Devices.create_device(%{ user_id: user.id, name: "Factory Device", + preshared_key: "27eCDMVvVFfMVS5Rfnn9n7as4M6MemGY/oghmdrwX2E=", public_key: "3Fo+SNnDJ6hi8qzPt3nWLwgjCVwvpjHL35qJeatKwEc=", remote_ip: %Postgrex.INET{address: {127, 0, 0, 1}} }) diff --git a/apps/fz_http/test/fz_http/devices_test.exs b/apps/fz_http/test/fz_http/devices_test.exs index 2bbee584e..ecdf3fcf1 100644 --- a/apps/fz_http/test/fz_http/devices_test.exs +++ b/apps/fz_http/test/fz_http/devices_test.exs @@ -70,6 +70,10 @@ defmodule FzHttp.DevicesTest do assert device.ipv6 == %Postgrex.INET{address: {64_768, 0, 0, 0, 0, 3, 2, 2}, netmask: 128} end + test "generates preshared_key" do + assert String.length(Devices.new_device().changes.preshared_key) == 44 + end + @tag ipv4_network: "10.3.2.0/30" test "sets error when ipv4 address pool is exhausted", %{user: user} do restore_env(:wireguard_ipv4_network, "10.3.2.0/30", &on_exit/1) @@ -380,6 +384,7 @@ defmodule FzHttp.DevicesTest do test "renders all peers", %{device: device} do assert Devices.to_peer_list() |> List.first() == %{ + preshared_key: nil, public_key: device.public_key, inet: "#{device.ipv4}/32,#{device.ipv6}/128" } diff --git a/apps/fz_http/test/fz_http/events_test.exs b/apps/fz_http/test/fz_http/events_test.exs index a12f38f9e..fb3c17321 100644 --- a/apps/fz_http/test/fz_http/events_test.exs +++ b/apps/fz_http/test/fz_http/events_test.exs @@ -21,7 +21,10 @@ defmodule FzHttp.EventsTest do assert :ok == Events.update_device(device) assert :sys.get_state(Events.vpn_pid()) == %{ - device.public_key => "#{device.ipv4}/32,#{device.ipv6}/128" + device.public_key => %{ + allowed_ips: "#{device.ipv4}/32,#{device.ipv6}/128", + preshared_key: nil + } } end end @@ -33,7 +36,10 @@ defmodule FzHttp.EventsTest do assert :ok = Events.update_device(device) assert :sys.get_state(Events.vpn_pid()) == %{ - device.public_key => "#{device.ipv4}/32,#{device.ipv6}/128" + device.public_key => %{ + allowed_ips: "#{device.ipv4}/32,#{device.ipv6}/128", + preshared_key: nil + } } end end @@ -68,7 +74,9 @@ defmodule FzHttp.EventsTest do :ok = Events.set_config() assert :sys.get_state(Events.vpn_pid()) == - Map.new(Devices.to_peer_list(), fn peer -> {peer.public_key, peer.inet} end) + Map.new(Devices.to_peer_list(), fn peer -> + {peer.public_key, %{allowed_ips: peer.inet, preshared_key: peer.preshared_key}} + end) end end diff --git a/apps/fz_vpn/lib/fz_vpn/cli/live.ex b/apps/fz_vpn/lib/fz_vpn/cli/live.ex index acbd7cd19..b297a4c61 100644 --- a/apps/fz_vpn/lib/fz_vpn/cli/live.ex +++ b/apps/fz_vpn/lib/fz_vpn/cli/live.ex @@ -8,6 +8,7 @@ defmodule FzVpn.CLI.Live do See FzVpn.Server for higher-level functionality. """ + alias FzVpn.Config import FzCommon.CLI require Logger @@ -19,12 +20,9 @@ defmodule FzVpn.CLI.Live do :ok = GenServer.call(:global.whereis_name(:fz_wall_server), :teardown) end - def set_peer(pubkey, inet) do - set("peer #{pubkey} allowed-ips #{inet}") - end - - def remove_peer(pubkey) do - set("peer #{pubkey} remove") + def remove_peer(public_key) do + set("peer #{public_key} remove") + Config.delete_psk(public_key) end def set(config_str) do diff --git a/apps/fz_vpn/lib/fz_vpn/cli/sandbox.ex b/apps/fz_vpn/lib/fz_vpn/cli/sandbox.ex index 17161594e..0c9e9b326 100644 --- a/apps/fz_vpn/lib/fz_vpn/cli/sandbox.ex +++ b/apps/fz_vpn/lib/fz_vpn/cli/sandbox.ex @@ -1,8 +1,10 @@ defmodule FzVpn.CLI.Sandbox do @moduledoc """ - Sandbox CLI environment for WireGuard CLI operations. + Sandbox CLI environment for WireGuard CLI operations used in + dev and test modes. """ + alias FzVpn.Config require Logger @wg_show """ @@ -44,16 +46,13 @@ defmodule FzVpn.CLI.Sandbox do |> Enum.map(fn line -> String.replace_leading(line, "peer: ", "") end) - |> Enum.each(fn pubkey -> - remove_peer(pubkey) + |> Enum.each(fn public_key -> + remove_peer(public_key) end) end - def remove_peer(_pubkey) do - @default_returned - end - - def set_peer(_pubkey, _allowed_ips) do + def remove_peer(public_key) do + Config.delete_psk(public_key) @default_returned end diff --git a/apps/fz_vpn/lib/fz_vpn/config.ex b/apps/fz_vpn/lib/fz_vpn/config.ex index 0b5740918..5106b1bf2 100644 --- a/apps/fz_vpn/lib/fz_vpn/config.ex +++ b/apps/fz_vpn/lib/fz_vpn/config.ex @@ -3,13 +3,57 @@ defmodule FzVpn.Config do Functions for managing the WireGuard configuration. """ + require Logger + # Render peers list into server config def render(config) do Enum.join( - for {public_key, allowed_ips} <- config do - "peer #{public_key} allowed-ips #{allowed_ips}" + for {public_key, %{allowed_ips: allowed_ips, preshared_key: preshared_key}} <- config do + if is_nil(preshared_key) do + "peer #{public_key} allowed-ips #{allowed_ips}" + else + write_psk(public_key, preshared_key) + + "peer #{public_key} allowed-ips #{allowed_ips} preshared-key #{psk_filepath(public_key)}" + end end, " " ) end + + def write_psk(public_key, preshared_key) do + # Sets proper file mode before key is written + File.touch!(psk_filepath(public_key)) + File.chmod!(psk_filepath(public_key), 0o660) + File.write!(psk_filepath(public_key), preshared_key) + end + + def delete_psk(public_key) do + case File.rm(psk_filepath(public_key)) do + :ok -> + :ok + + _ -> + Logger.warn(""" + public_key #{public_key} at path #{psk_filepath(public_key)} \ + seems to have already been removed. + """) + end + end + + def psk_filepath(nil), do: raise("Error! public_key unexpectedly nil") + + def psk_filepath(public_key) do + "#{psk_dir()}/#{psk_filename(public_key)}" + end + + defp psk_dir do + Application.fetch_env!(:fz_vpn, :wireguard_psk_dir) + end + + defp psk_filename(public_key) do + :crypto.hash(:sha256, public_key) + |> Base.encode16() + |> String.downcase() + end end diff --git a/apps/fz_vpn/lib/fz_vpn/server.ex b/apps/fz_vpn/lib/fz_vpn/server.ex index e7fbd09a9..2003c3ee3 100644 --- a/apps/fz_vpn/lib/fz_vpn/server.ex +++ b/apps/fz_vpn/lib/fz_vpn/server.ex @@ -24,10 +24,10 @@ defmodule FzVpn.Server do end @impl GenServer - def handle_call({:remove_peer, pubkey}, _from, config) do - cli().remove_peer(pubkey) - new_config = Map.delete(config, pubkey) - {:reply, {:ok, pubkey}, new_config} + def handle_call({:remove_peer, public_key}, _from, config) do + cli().remove_peer(public_key) + new_config = Map.delete(config, public_key) + {:reply, {:ok, public_key}, new_config} end @impl GenServer @@ -47,14 +47,14 @@ defmodule FzVpn.Server do end defp delete_old_peers(old_config, new_config) do - for pubkey <- Map.keys(old_config) -- Map.keys(new_config) do - cli().remove_peer(pubkey) + for public_key <- Map.keys(old_config) -- Map.keys(new_config) do + cli().remove_peer(public_key) end end defp update_changed_peers(old_config, new_config) do new_config - |> Enum.filter(fn {pubkey, inet} -> Map.get(old_config, pubkey) != inet end) + |> Enum.filter(fn {public_key, settings} -> Map.get(old_config, public_key) != settings end) |> Config.render() |> cli().set() end @@ -64,6 +64,8 @@ defmodule FzVpn.Server do end defp peers_to_config(peers) do - Map.new(peers, fn peer -> {peer.public_key, peer.inet} end) + Map.new(peers, fn peer -> + {peer.public_key, %{allowed_ips: peer.inet, preshared_key: peer.preshared_key}} + end) end end diff --git a/apps/fz_vpn/mix.exs b/apps/fz_vpn/mix.exs index a6c659cfe..d9a5ed03e 100644 --- a/apps/fz_vpn/mix.exs +++ b/apps/fz_vpn/mix.exs @@ -41,6 +41,7 @@ defmodule FzVpn.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ + {:fz_http, in_umbrella: true}, {:fz_common, in_umbrella: true}, {:credo, "~> 1.4", only: [:dev, :test], runtime: false}, {:excoveralls, "~> 0.13", only: :test} diff --git a/apps/fz_vpn/test/fz_vpn/config_test.exs b/apps/fz_vpn/test/fz_vpn/config_test.exs index f1d7d0c3e..2f8375374 100644 --- a/apps/fz_vpn/test/fz_vpn/config_test.exs +++ b/apps/fz_vpn/test/fz_vpn/config_test.exs @@ -2,7 +2,8 @@ defmodule FzVpn.ConfigTest do use ExUnit.Case, async: true alias FzVpn.Config - @populated_config "peer test-pubkey allowed-ips test-ipv4/32,test-ipv6/128" + @psk_config "peer test-pubkey allowed-ips test-ipv4/32,test-ipv6/128 preshared-key /tmp/0abdc3fcda5d110c7ce3626dd2a261d9c0d33f3ee643ef9a46fe2f7aee0ee5e3" + @no_psk_config "peer test-pubkey allowed-ips test-ipv4/32,test-ipv6/128" describe "render" do test "renders default config" do @@ -11,10 +12,20 @@ defmodule FzVpn.ConfigTest do assert Config.render(config) == "" end - test "renders populated config" do - config = %{"test-pubkey" => "test-ipv4/32,test-ipv6/128"} + test "renders psk config" do + config = %{ + "test-pubkey" => %{allowed_ips: "test-ipv4/32,test-ipv6/128", preshared_key: "foobar"} + } - assert Config.render(config) == @populated_config + assert Config.render(config) == @psk_config + end + + test "renders no-psk config" do + config = %{ + "test-pubkey" => %{allowed_ips: "test-ipv4/32,test-ipv6/128", preshared_key: nil} + } + + assert Config.render(config) == @no_psk_config end end end diff --git a/apps/fz_vpn/test/fz_vpn/server_test.exs b/apps/fz_vpn/test/fz_vpn/server_test.exs index b48b23cba..d130cacb0 100644 --- a/apps/fz_vpn/test/fz_vpn/server_test.exs +++ b/apps/fz_vpn/test/fz_vpn/server_test.exs @@ -3,13 +3,13 @@ defmodule FzVpn.ServerTest do import FzVpn.CLI @single_peer [ - %{public_key: "test-pubkey", inet: "127.0.0.1/32,::1/128"} + %{public_key: "test-pubkey", preshared_key: "foobar", inet: "127.0.0.1/32,::1/128"} ] @many_peers [ - %{public_key: "key1", inet: "0.0.0.0/32,::1/128"}, - %{public_key: "key2", inet: "127.0.0.1/32,::1/128"}, - %{public_key: "key3", inet: "127.0.0.1/32,::1/128"}, - %{public_key: "key4", inet: "127.0.0.1/32,::1/128"} + %{public_key: "key1", preshared_key: "foobar", inet: "0.0.0.0/32,::1/128"}, + %{public_key: "key2", preshared_key: "foobar", inet: "127.0.0.1/32,::1/128"}, + %{public_key: "key3", preshared_key: "foobar", inet: "127.0.0.1/32,::1/128"}, + %{public_key: "key4", preshared_key: "foobar", inet: "127.0.0.1/32,::1/128"} ] describe "state" do @@ -31,17 +31,20 @@ defmodule FzVpn.ServerTest do @tag stubbed_config: @many_peers test "calcs diff and sets only the diff", %{test_pid: test_pid} do - new_peers = [%{public_key: "key5", inet: "1.1.1.1/32,::2/128"}] + new_peers = [%{public_key: "key5", inet: "1.1.1.1/32,::2/128", preshared_key: "foobar"}] assert :sys.get_state(test_pid) == %{ - "key1" => "0.0.0.0/32,::1/128", - "key2" => "127.0.0.1/32,::1/128", - "key3" => "127.0.0.1/32,::1/128", - "key4" => "127.0.0.1/32,::1/128" + "key1" => %{allowed_ips: "0.0.0.0/32,::1/128", preshared_key: "foobar"}, + "key2" => %{allowed_ips: "127.0.0.1/32,::1/128", preshared_key: "foobar"}, + "key3" => %{allowed_ips: "127.0.0.1/32,::1/128", preshared_key: "foobar"}, + "key4" => %{allowed_ips: "127.0.0.1/32,::1/128", preshared_key: "foobar"} } GenServer.call(test_pid, {:set_config, new_peers}) - assert :sys.get_state(test_pid) == %{"key5" => "1.1.1.1/32,::2/128"} + + assert :sys.get_state(test_pid) == %{ + "key5" => %{allowed_ips: "1.1.1.1/32,::2/128", preshared_key: "foobar"} + } end end end diff --git a/apps/fz_wall/mix.exs b/apps/fz_wall/mix.exs index 4d67e3cb6..81d2a0eb3 100644 --- a/apps/fz_wall/mix.exs +++ b/apps/fz_wall/mix.exs @@ -41,6 +41,7 @@ defmodule FzWall.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ + {:fz_http, in_umbrella: true}, {:fz_common, in_umbrella: true}, {:credo, "~> 1.4", only: [:dev, :test], runtime: false}, {:excoveralls, "~> 0.13", only: :test} diff --git a/config/config.exs b/config/config.exs index 15541ea58..509d3ac9a 100644 --- a/config/config.exs +++ b/config/config.exs @@ -86,6 +86,7 @@ config :hammer, # This will be changed per-env config :fz_vpn, + wireguard_psk_dir: "/tmp", wireguard_public_key: "cB2yQeCxHO/qCH8APoM2D2Anf4Yd7sRLyfS7su71K3M=", wireguard_interface_name: "wg-firezone", wireguard_port: "51820", diff --git a/config/releases.exs b/config/releases.exs index 1cf0a3244..9f0c5b63d 100644 --- a/config/releases.exs +++ b/config/releases.exs @@ -23,6 +23,7 @@ nft_path = System.fetch_env!("NFT_PATH") wg_path = System.fetch_env!("WG_PATH") egress_interface = System.fetch_env!("EGRESS_INTERFACE") wireguard_public_key = System.fetch_env!("WIREGUARD_PUBLIC_KEY") +wireguard_psk_dir = System.fetch_env!("WIREGUARD_PSK_DIR") wireguard_dns = System.fetch_env!("WIREGUARD_DNS") wireguard_allowed_ips = System.fetch_env!("WIREGUARD_ALLOWED_IPS") wireguard_persistent_keepalive = System.fetch_env!("WIREGUARD_PERSISTENT_KEEPALIVE") @@ -141,6 +142,7 @@ config :fz_wall, cli: FzWall.CLI.Live config :fz_vpn, + wireguard_psk_dir: wireguard_psk_dir, wireguard_public_key: wireguard_public_key, wireguard_interface_name: wireguard_interface_name, wireguard_port: wireguard_port, diff --git a/docs/docs/reference/configuration-file.md b/docs/docs/reference/configuration-file.md index 8d5a313e4..2b835a604 100644 --- a/docs/docs/reference/configuration-file.md +++ b/docs/docs/reference/configuration-file.md @@ -32,6 +32,15 @@ Shown below is a complete listing of the configuration options available in | `default['enterprise']['name']` | Name used by the Chef 'enterprise' cookbook. | `'firezone'` | | `default['firezone']['install_path']` | Install path used by Chef 'enterprise' cookbook. Should be set to the same as the `install_directory` above. | `node['firezone']['install_directory']` | | `default['firezone']['sysvinit_id']` | An identifier used in `/etc/inittab`. Must be a unique sequence of 1-4 characters. | `'SUP'` | +| `default['firezone']['authentication']['local']['enabled'] = true` | Enable or disable local email/password authentication. | `true` | +| `default['firezone']['authentication']['okta']['enabled'] = false` | Enable or disable Okta SSO authentication. | `false` | +| `default['firezone']['authentication']['okta']['client_id'] = nil` | OAuth Client ID for Okta SSO authentication. | `nil` | +| `default['firezone']['authentication']['okta']['client_secret'] = nil` | OAuth Client Secret for Okta SSO authentication. | `nil` | +| `default['firezone']['authentication']['okta']['site'] = 'https://your-domain.okta.com'` | Okta site to redirect to after successful authentication. | `'https://your-domain.okta.com'` | +| `default['firezone']['authentication']['google']['enabled'] = false` | Enable or disable Google SSO authentication. | `false` | +| `default['firezone']['authentication']['google']['client_id'] = nil` | OAuth Client ID for Google SSO authentication. | `nil` | +| `default['firezone']['authentication']['google']['client_secret'] = nil` | OAuth Client Secret for Google SSO authentication. | `nil` | +| `default['firezone']['authentication']['google']['redirect_uri'] = nil` | Google redirect URI for Google SSO authentication. | `nil` | | `default['firezone']['nginx']['enabled']` | Enable or disable the bundled nginx server. | `true` | | `default['firezone']['nginx']['force_ssl']` | Force nginx to SSL mode only. | `true` | | `default['firezone']['nginx']['non_ssl_port']` | HTTP listen port. | `80` | diff --git a/mix.lock b/mix.lock index dfa0f6c8c..788fbf212 100644 --- a/mix.lock +++ b/mix.lock @@ -31,7 +31,7 @@ "hammer": {:hex, :hammer, "6.0.0", "72ec6fff10e9d63856968988a22ee04c4d6d5248071ddccfbda50aa6c455c1d7", [:mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "d8e1ec2e534c4aae508b906759e077c3c1eb3e2b9425235d4b7bbab0b016210a"}, "hammer_plug": {:hex, :hammer_plug, "2.1.1", "eb5390380eff6600e24e93edfe6a34d39f35280cbdd1caa0995b58bb8489f00d", [:make, :mix], [{:hammer, "~> 6.0", [hex: :hammer, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "0fbc3e8b1aacecb7affea65c85c349fdbd00ff28a74bbe6ca30c9f4c76d71e4b"}, "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, - "httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"}, + "httpoison": {:hex, :httpoison, "1.8.1", "df030d96de89dad2e9983f92b0c506a642d4b1f4a819c96ff77d12796189c63e", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "35156a6d678d6d516b9229e208942c405cf21232edd632327ecfaf4fd03e79e0"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm", "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc"}, "inflex": {:hex, :inflex, "2.1.0", "a365cf0821a9dacb65067abd95008ca1b0bb7dcdd85ae59965deef2aa062924c", [:mix], [], "hexpm", "14c17d05db4ee9b6d319b0bff1bdf22aa389a25398d1952c7a0b5f3d93162dd8"}, @@ -51,8 +51,8 @@ "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"}, "phoenix_html": {:hex, :phoenix_html, "3.1.0", "0b499df05aad27160d697a9362f0e89fa0e24d3c7a9065c2bd9d38b4d1416c09", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0c0a98a2cefa63433657983a2a594c7dee5927e4391e0f1bfd3a151d1def33fc"}, "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.3", "3a53772a6118d5679bf50fc1670505a290e32a1d195df9e069d8c53ab040c054", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "766796676e5f558dbae5d1bdb066849673e956005e3730dfd5affd7a6da4abac"}, - "phoenix_live_view": {:hex, :phoenix_live_view, "0.17.7", "05a42377075868a678d446361effba80cefef19ab98941c01a7a4c7560b29121", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.9 or ~> 1.6.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "25eaf41028eb351b90d4f69671874643a09944098fefd0d01d442f40a6091b6f"}, - "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "0.17.9", "36b5aa812bc3ccd64c9630f6b3234d9ea21105493237e927aae19d0ba758f0db", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f7ebc3e0ba0c5f6b6996ed6c901ddbfdaba59a6d09b569e7cb2f2f7d693b4455"}, + "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"}, "phoenix_view": {:hex, :phoenix_view, "1.1.2", "1b82764a065fb41051637872c7bd07ed2fdb6f5c3bd89684d4dca6e10115c95a", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "7ae90ad27b09091266f6adbb61e1d2516a7c3d7062c6789d46a7554ec40f3a56"}, "plug": {:hex, :plug, "1.12.1", "645678c800601d8d9f27ad1aebba1fdb9ce5b2623ddb961a074da0b96c35187d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d57e799a777bc20494b784966dc5fbda91eb4a09f571f76545b72a634ce0d30b"}, "plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"}, diff --git a/omnibus/cookbooks/firezone/libraries/config.rb b/omnibus/cookbooks/firezone/libraries/config.rb index f3f2e3f7e..f866d2914 100644 --- a/omnibus/cookbooks/firezone/libraries/config.rb +++ b/omnibus/cookbooks/firezone/libraries/config.rb @@ -235,6 +235,7 @@ class Firezone 'WIREGUARD_ALLOWED_IPS' => attributes['wireguard']['allowed_ips'].to_s, 'WIREGUARD_PERSISTENT_KEEPALIVE' => attributes['wireguard']['persistent_keepalive'].to_s, 'WIREGUARD_PUBLIC_KEY' => attributes['wireguard_public_key'], + 'WIREGUARD_PSK_DIR' => "#{attributes['var_directory']}/cache/psks", 'WIREGUARD_IPV4_ENABLED' => attributes['wireguard']['ipv4']['enabled'].to_s, 'WIREGUARD_IPV4_NETWORK' => attributes['wireguard']['ipv4']['network'], 'WIREGUARD_IPV4_ADDRESS' => attributes['wireguard']['ipv4']['address'], diff --git a/omnibus/cookbooks/firezone/recipes/config.rb b/omnibus/cookbooks/firezone/recipes/config.rb index 4fd738ed7..3e99f2c97 100644 --- a/omnibus/cookbooks/firezone/recipes/config.rb +++ b/omnibus/cookbooks/firezone/recipes/config.rb @@ -109,3 +109,9 @@ file "#{node['firezone']['var_directory']}/cache/wg_private_key" do content node['firezone']['wireguard_private_key'] action :create_if_missing end + +directory "#{node['firezone']['var_directory']}/cache/psks" do + owner 'root' + group node['firezone']['group'] + mode '0770' +end diff --git a/scripts/install.sh b/scripts/install.sh index a6cbd0c8f..5bda967e1 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -68,7 +68,7 @@ wireguardCheck() { kernelCheck() { major=`uname -r | cut -d'.' -f1` if [ "$major" -lt "5" ]; then - echo "Kernel is not supported `uname -r`" + echo "Kernel version `uname -r ` is not supported. Please upgrade to 5.0 or higher." exit fi }