Files
IPTables-Management/tests/test_rules_unit.sh

95 lines
4.5 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
# shellcheck source=tests/lib/assert.sh
source "${ROOT_DIR}/tests/lib/assert.sh"
status_of() {
set +e
"$@" >/dev/null 2>&1
local rc=$?
set -e
printf '%s\n' "${rc}"
}
TMP_DIR=$(mktemp -d)
trap 'rm -rf "${TMP_DIR}"' EXIT
export IPF_STORAGE_DIR="${TMP_DIR}/storage"
export IPF_STORAGE_DB="${IPF_STORAGE_DIR}/rules.db"
export IPF_LOCK_FILE="${IPF_STORAGE_DIR}/.lock"
export IPTABLES_MOCK_DIR="${TMP_DIR}/iptables-mock"
export IPTABLES_MOCK_LOG="${TMP_DIR}/iptables.log"
export IPTABLES_BIN="${ROOT_DIR}/tests/mocks/iptables"
export IP6TABLES_BIN="${ROOT_DIR}/tests/mocks/ip6tables"
export IPTABLES_SAVE_BIN="${ROOT_DIR}/tests/mocks/iptables-save"
export IP6TABLES_SAVE_BIN="${ROOT_DIR}/tests/mocks/ip6tables-save"
export NETFILTER_PERSISTENT_BIN="${ROOT_DIR}/tests/mocks/persist-mock.sh"
export PERSIST_MOCK_LOG="${TMP_DIR}/persist.log"
# shellcheck source=lib/common.sh
source "${ROOT_DIR}/lib/common.sh"
# shellcheck source=lib/storage.sh
source "${ROOT_DIR}/lib/storage.sh"
# shellcheck source=lib/persist.sh
source "${ROOT_DIR}/lib/persist.sh"
# shellcheck source=lib/iptables_ops.sh
source "${ROOT_DIR}/lib/iptables_ops.sh"
# shellcheck source=lib/rules_mgr.sh
source "${ROOT_DIR}/lib/rules_mgr.sh"
reset_mock_state() {
rm -rf "${IPTABLES_MOCK_DIR}" "${IPF_STORAGE_DIR}"
mkdir -p "${IPTABLES_MOCK_DIR}" "${IPF_STORAGE_DIR}"
: >"${IPTABLES_MOCK_LOG}"
: >"${PERSIST_MOCK_LOG}"
unset IPTABLES_MOCK_FAIL_ON_N || true
unset PERSIST_MOCK_FAIL || true
storage_init
}
reset_mock_state
uuid_v4=$(cmd_add_batch tcp 8080 127.0.0.1 80 4 'web service')
assert_eq '1' "$(storage_count)" 'cmd_add_batch should persist one rule'
assert_eq '3' "$(grep -Ec '^iptables ' "${IPTABLES_MOCK_LOG}")" 'tcp/ipv4 add should emit three iptables commands'
assert_contains "$(storage_get "${uuid_v4}")" "uuid=${uuid_v4}" 'stored line should contain generated uuid'
assert_eq '1' "$(grep -Ec 'persist-mock\.sh save' "${PERSIST_MOCK_LOG}")" 'successful add should trigger persist_save'
assert_contains "$(ipt_find_by_uuid "${uuid_v4}")" "MGMT:${uuid_v4}" 'ipt_find_by_uuid should locate saved mock rules'
reset_mock_state
uuid_both=$(cmd_add_batch both 5353 '127.0.0.1,::1' 53 both 'dual stack dns')
add_count=$(grep -Ec '^(iptables|ip6tables) ' "${IPTABLES_MOCK_LOG}")
assert_eq '12' "${add_count}" 'both/both add should emit twelve commands'
cmd_delete_uuid "${uuid_both}"
del_count=$(grep -Ec ' -D ' "${IPTABLES_MOCK_LOG}")
assert_eq '12' "${del_count}" 'deleting both/both rule should emit twelve delete commands'
assert_eq '0' "$(storage_count)" 'cmd_delete_uuid should remove rule from storage'
reset_mock_state
export IPTABLES_MOCK_FAIL_ON_N=2
assert_eq '1' "$(status_of cmd_add_batch tcp 9000 127.0.0.1 90 4 'rollback')" 'cmd_add_batch should fail when iptables mock injects an error'
assert_eq '0' "$(storage_count)" 'failed add should not persist storage'
assert_contains "$(cat "${IPTABLES_MOCK_LOG}")" ' -D ' 'failed add should trigger rollback deletes'
assert_eq '0' "$(wc -l < "${PERSIST_MOCK_LOG}")" 'failed add before persistence should not call persist_save'
reset_mock_state
export PERSIST_MOCK_FAIL=1
assert_eq '1' "$(status_of cmd_add_batch tcp 9001 127.0.0.1 91 4 'persist rollback add')" 'cmd_add_batch should fail when persist_save fails'
assert_eq '0' "$(storage_count)" 'persist_save failure on add should roll back storage'
assert_eq '0' "$(wc -l < "${IPTABLES_MOCK_DIR}/state.v4")" 'persist_save failure on add should remove runtime rules'
assert_contains "$(cat "${IPTABLES_MOCK_LOG}")" ' -D ' 'persist_save failure on add should trigger runtime rollback'
assert_eq '1' "$(grep -Ec 'persist-mock\.sh save' "${PERSIST_MOCK_LOG}")" 'persist_save failure on add should still attempt one save'
reset_mock_state
uuid_delete_rollback=$(cmd_add_batch tcp 9100 127.0.0.1 92 4 'persist rollback delete')
export PERSIST_MOCK_FAIL=1
assert_eq '1' "$(status_of cmd_delete_uuid "${uuid_delete_rollback}")" 'cmd_delete_uuid should fail when persist_save fails'
assert_eq '1' "$(storage_count)" 'persist_save failure on delete should restore storage'
assert_contains "$(storage_get "${uuid_delete_rollback}")" "uuid=${uuid_delete_rollback}" 'persist_save failure on delete should restore storage line'
assert_contains "$(ipt_find_by_uuid "${uuid_delete_rollback}")" "MGMT:${uuid_delete_rollback}" 'persist_save failure on delete should restore runtime rules'
assert_eq '2' "$(grep -Ec 'persist-mock\.sh save' "${PERSIST_MOCK_LOG}")" 'persist_save failure on delete should include add and delete save attempts'
pass 'test_rules_unit.sh'