passing tests

This commit is contained in:
Jamil Bou Kheir
2021-09-02 15:57:42 +00:00
parent 24a49b9468
commit cd3cfd6134
8 changed files with 78 additions and 74 deletions

View File

@@ -28,14 +28,14 @@ defmodule FzHttp.Rules do
def allowlist do
Repo.all(
from r in Rule,
where: r.action == :allow
where: r.action == :accept
)
end
def denylist do
Repo.all(
from r in Rule,
where: r.action == :deny
where: r.action == :drop
)
end

View File

@@ -10,7 +10,7 @@ defmodule FzHttp.Rules.Rule do
schema "rules" do
field :destination, EctoNetwork.INET
field :action, Ecto.Enum, values: [:deny, :allow], default: :deny
field :action, Ecto.Enum, values: [:drop, :accept], default: :drop
timestamps(type: :utc_datetime_usec)
end

View File

@@ -45,10 +45,10 @@ defmodule FzHttpWeb.RuleLive.RuleListComponent do
defp action(id) do
case id do
:allowlist ->
:allow
:accept
:denylist ->
:deny
:drop
end
end

View File

@@ -1,7 +1,7 @@
defmodule FzHttp.Repo.Migrations.CreateRules do
use Ecto.Migration
@create_query "CREATE TYPE action_enum AS ENUM ('deny', 'allow')"
@create_query "CREATE TYPE action_enum AS ENUM ('drop', 'accept')"
@drop_query "DROP TYPE action_enum"
def change do
@@ -9,7 +9,7 @@ defmodule FzHttp.Repo.Migrations.CreateRules do
create table(:rules) do
add :destination, :inet, null: false
add :action, :action_enum, default: "deny", null: false
add :action, :action_enum, default: "drop", null: false
timestamps(type: :utc_datetime_usec)
end

View File

@@ -27,7 +27,7 @@ defmodule FzHttp.RulesTest do
test "creates rule" do
{:ok, rule} = Rules.create_rule(%{destination: "::1"})
assert !is_nil(rule.id)
assert rule.action == :deny
assert rule.action == :drop
end
end
@@ -47,11 +47,11 @@ defmodule FzHttp.RulesTest do
setup [:create_rules]
@iptables_rules [
{"1.1.1.0/24", :deny},
{"2.2.2.0/24", :deny},
{"3.3.3.0/24", :deny},
{"4.4.4.0/24", :deny},
{"5.5.5.0/24", :deny}
{"1.1.1.0/24", :drop},
{"2.2.2.0/24", :drop},
{"3.3.3.0/24", :drop},
{"4.4.4.0/24", :drop},
{"5.5.5.0/24", :drop}
]
test "prints all rules to iptables format", %{rules: _rules} do
@@ -60,7 +60,7 @@ defmodule FzHttp.RulesTest do
end
describe "allowlist/0" do
setup [:create_allow_rule]
setup [:create_accept_rule]
test "returns allow rules", %{rule: rule} do
assert Rules.allowlist() == [rule]
@@ -68,7 +68,7 @@ defmodule FzHttp.RulesTest do
end
describe "denylist/0" do
setup [:create_deny_rule]
setup [:create_drop_rule]
test "returns deny rules", %{rule: rule} do
assert Rules.denylist() == [rule]
@@ -79,7 +79,7 @@ defmodule FzHttp.RulesTest do
# describe "iptables_spec/1 IPv4" do
# setup [:create_rule4]
#
# @ipv4tables_spec {"10.0.0.1", "10.10.10.0/24", :deny}
# @ipv4tables_spec {"10.0.0.1", "10.10.10.0/24", :drop}
#
# test "returns IPv4 tuple", %{rule4: rule} do
# assert @ipv4tables_spec = Rules.iptables_spec(rule)
@@ -89,7 +89,7 @@ defmodule FzHttp.RulesTest do
# describe "iptables_spec/1 IPv6" do
# setup [:create_rule6]
#
# @ipv6tables_spec {"::1", "::/0", :deny}
# @ipv6tables_spec {"::1", "::/0", :drop}
#
# test "returns IPv6 tuple", %{rule6: rule} do
# assert @ipv6tables_spec = Rules.iptables_spec(rule)

View File

@@ -2,10 +2,10 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
use FzHttpWeb.ConnCase, async: true
describe "allowlist" do
setup :create_allow_rule
setup :create_accept_rule
@destination "1.2.3.4"
@allow_params %{"rule" => %{"action" => "allow", "destination" => @destination}}
@allow_params %{"rule" => %{"action" => "accept", "destination" => @destination}}
test "adds to allowlist", %{authed_conn: conn} do
path = Routes.rule_index_path(conn, :index)
@@ -13,7 +13,7 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
test_view =
view
|> form("#allow-form")
|> form("#accept-form")
|> render_submit(@allow_params)
assert test_view =~ @destination
@@ -25,11 +25,11 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
test_view =
view
|> form("#allow-form")
|> form("#accept-form")
|> render_submit(%{
"rule" => %{
"destination" => "not a valid destination",
"action" => "allow"
"action" => "accept"
}
})
@@ -50,10 +50,10 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
end
describe "denylist" do
setup :create_deny_rule
setup :create_drop_rule
@destination "1.2.3.4"
@deny_params %{"rule" => %{"action" => "deny", "destination" => @destination}}
@deny_params %{"rule" => %{"action" => "drop", "destination" => @destination}}
test "adds to denylist", %{authed_conn: conn, rule: _rule} do
path = Routes.rule_index_path(conn, :index)
@@ -61,7 +61,7 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
test_view =
view
|> form("#deny-form")
|> form("#drop-form")
|> render_submit(@deny_params)
assert test_view =~ @destination
@@ -73,11 +73,11 @@ defmodule FzHttpWeb.RuleLive.IndexTest do
test_view =
view
|> form("#deny-form")
|> form("#drop-form")
|> render_submit(%{
"rule" => %{
"destination" => "not a valid destination",
"action" => "deny"
"action" => "drop"
}
})

View File

@@ -60,13 +60,13 @@ defmodule FzHttp.TestHelpers do
{:ok, session: session}
end
def create_allow_rule(_) do
rule = Fixtures.rule(%{action: :allow})
def create_accept_rule(_) do
rule = Fixtures.rule(%{action: :accept})
{:ok, rule: rule}
end
def create_deny_rule(_) do
rule = Fixtures.rule(%{action: :deny})
def create_drop_rule(_) do
rule = Fixtures.rule(%{action: :drop})
{:ok, rule: rule}
end

View File

@@ -1,76 +1,80 @@
defmodule FzWall.CLI.Live do
@moduledoc """
A low-level module for interacting with the iptables CLI.
A low-level module for interacting with the nftables CLI.
Rules operate on the iptables forward chain to deny outgoing packets to
Rules operate on the nftables forward chain to deny outgoing packets to
specified IP addresses, ports, and protocols from FireZone device IPs.
Note that iptables chains and rules are mutually exclusive between IPv4 and IPv6.
"""
import FzCommon.CLI
require Logger
@table_name "firezone"
@egress_interface_cmd "route | grep '^default' | grep -o '[^ ]*$'"
@setup_chain_cmd "iptables -N firezone && iptables6 -N firezone"
@teardown_chain_cmd "iptables -F firezone &&\
iptables -X firezone &&\
iptables6 -F firezone &&\
iptables6 -X firezone"
@doc """
Sets up the FireZone iptables chain.
Sets up the FireZone nftables table, base chain, and counts traffic
"forward" is the Netfilter hook we want to tie into.
"""
def setup do
exec!(@setup_chain_cmd)
exec!("#{nft()} add table ip #{@table_name}")
exec!(
"#{nft()} 'add chain ip #{@table_name} forward { type filter hook forward priority 0 ; }'"
)
exec!("#{nft()} 'add rule ip #{@table_name} forward counter accept'")
end
@doc """
Flushes and removes the FireZone iptables chain.
Flushes and removes the FireZone nftables table and base chain.
"""
def teardown do
exec!(@teardown_chain_cmd)
exec!("#{nft()} delete table ip #{@table_name}")
end
@doc """
Adds iptables rule.
Adds nftables rule.
"""
def add_rule({4, s, d, :deny}) do
exec!("iptables -A firezone -s #{s} -d #{d} -j DROP")
end
def add_rule({4, d, :deny}) do
exec!("iptables -A firezone -d #{d} -j DROP")
end
def add_rule({4, s, d, :allow}) do
exec!("iptables -A firezone -s #{s} -d #{d} -j ACCEPT")
end
def add_rule({6, s, d, :deny}) do
exec!("iptables6 -A firezone -s #{s} -d #{d} -j DROP")
end
def add_rule({6, s, d, :allow}) do
exec!("iptables6 -A firezone -s #{s} -d #{d} -j ACCEPT")
def add_rule({dest, action}) do
exec!("#{nft()} 'add rule ip #{@table_name} forward ip daddr #{dest} #{action}'")
end
@doc """
Deletes iptables rule.
Deletes nftables rule.
"""
def delete_rule({4, s, d, :deny}) do
exec!("#{nft()} -D firezone -s #{s} -d #{d} -j DROP")
def delete_rule_spec({dest, action} = rule_spec) do
case get_rule_handle("ip daddr #{dest} #{action}") do
{:ok, handle_num} ->
exec!("#{nft()} delete rule #{@table_name} forward handle #{handle_num}")
{:error, cmd_output} ->
raise("""
######################################################
Could not get handle to delete rule!
Rule spec: #{rule_spec}
Current chain:
#{cmd_output}
######################################################
""")
end
end
def delete_rule({4, s, d, :allow}) do
exec!("iptables -D firezone -s #{s} -d #{d} -j ACCEPT")
def get_rule_handle(rule_str) do
cmd_output = exec!("#{nft()} list table #{@table_name}")
case rule_handle_regex(~r/#{rule_str}.*# handle (?<num>\d+)/, cmd_output) do
[handle] ->
{:ok, handle}
[] ->
{:error, cmd_output}
end
end
def delete_rule({6, s, d, :deny}) do
exec!("iptables6 -D firezone -s #{s} -d #{d} -j DROP")
end
def delete_rule({6, s, d, :allow}) do
exec!("iptables6 -D firezone -s #{s} -d #{d} -j ACCEPT")
defp rule_handle_regex(regex, cmd_output) do
Regex.run(regex, cmd_output, capture: :all_names)
end
def restore(_rules) do