141 lines
5.4 KiB
Bash
141 lines
5.4 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}"
|
|
}
|
|
|
|
maybe_enter_namespace() {
|
|
if (( EUID == 0 )); then
|
|
return 0
|
|
fi
|
|
|
|
if [[ ${IPF_IN_NAMESPACE:-0} == 1 ]]; then
|
|
return 0
|
|
fi
|
|
|
|
if command -v unshare >/dev/null 2>&1 && unshare -Urn true >/dev/null 2>&1; then
|
|
exec unshare -Urn env IPF_IN_NAMESPACE=1 bash "$0"
|
|
fi
|
|
|
|
printf 'SKIP: root 或 unshare 不可用,跳过集成测试。\n'
|
|
exit 0
|
|
}
|
|
|
|
maybe_enter_namespace
|
|
|
|
if command -v ip >/dev/null 2>&1; then
|
|
ip link set lo up >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
if ! command -v iptables >/dev/null 2>&1; then
|
|
printf 'SKIP: iptables 不可用,跳过集成测试。\n'
|
|
exit 0
|
|
fi
|
|
|
|
if ! command -v iptables-save >/dev/null 2>&1 || ! command -v iptables-restore >/dev/null 2>&1; then
|
|
printf 'SKIP: iptables-save/iptables-restore 不可用,跳过集成测试。\n'
|
|
exit 0
|
|
fi
|
|
|
|
TMP_DIR=$(mktemp -d)
|
|
BACKUP_V4="${TMP_DIR}/iptables.v4.bak"
|
|
BACKUP_V6="${TMP_DIR}/iptables.v6.bak"
|
|
PERSIST_RULES_V4="${TMP_DIR}/rules.v4"
|
|
PERSIST_RULES_V6="${TMP_DIR}/rules.v6"
|
|
PERSIST_FIXTURE_LOG="${TMP_DIR}/persist.log"
|
|
|
|
restore_runtime_from_backup() {
|
|
if [[ -f ${BACKUP_V4} ]]; then
|
|
iptables-restore <"${BACKUP_V4}" >/dev/null 2>&1 || true
|
|
fi
|
|
if [[ -f ${BACKUP_V6} ]] && command -v ip6tables-restore >/dev/null 2>&1; then
|
|
ip6tables-restore <"${BACKUP_V6}" >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
|
|
cleanup() {
|
|
restore_runtime_from_backup
|
|
rm -rf "${TMP_DIR}"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
iptables-save >"${BACKUP_V4}"
|
|
if command -v ip6tables-save >/dev/null 2>&1; then
|
|
ip6tables-save >"${BACKUP_V6}"
|
|
fi
|
|
|
|
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 IPF_SKIP_ENV_CHECK=1
|
|
export IPF_FORCE_PLAIN_UI=1
|
|
export NETFILTER_PERSISTENT_BIN="${ROOT_DIR}/tests/mocks/persist-fixture.sh"
|
|
export PERSIST_RULES_V4
|
|
export PERSIST_RULES_V6
|
|
export PERSIST_FIXTURE_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"
|
|
|
|
uuid_v4=$("${ROOT_DIR}/iptables-forward.sh" --batch add tcp 65432 127.0.0.1 22 4 'integration-v4')
|
|
assert_contains "$(iptables-save)" "MGMT:${uuid_v4}" 'IPv4 rule should appear in iptables-save output'
|
|
assert_contains "$("${ROOT_DIR}/iptables-forward.sh" --batch list)" "uuid=${uuid_v4}" 'batch list should include managed rule'
|
|
assert_file_contains "${PERSIST_RULES_V4}" "MGMT:${uuid_v4}" 'persist save should write IPv4 rules snapshot'
|
|
assert_file_contains "${PERSIST_FIXTURE_LOG}" 'persist-fixture.sh save' 'adding a rule should call persist save'
|
|
|
|
iptables -t nat -D PREROUTING \
|
|
-p tcp --dport 65432 \
|
|
-j DNAT --to-destination 127.0.0.1:22 \
|
|
-m comment --comment "MGMT:${uuid_v4}"
|
|
list_output=$(cmd_list 0)
|
|
[[ ${list_output} =~ [[:space:]]![[:space:]] ]] || fail 'partial runtime loss should show degraded health in cmd_list'
|
|
|
|
persist_reload
|
|
list_output=$(cmd_list 0)
|
|
[[ ${list_output} =~ [[:space:]]✓[[:space:]] ]] || fail 'persist_reload should restore healthy status in cmd_list'
|
|
|
|
ipt_remove_rule "${uuid_v4}" tcp 65432 127.0.0.1 22 4
|
|
assert_status 1 "$(status_of grep -F "MGMT:${uuid_v4}" <(iptables-save))" 'manual runtime removal should clear managed IPv4 rule'
|
|
persist_reload
|
|
assert_file_contains "${PERSIST_FIXTURE_LOG}" 'persist-fixture.sh reload' 'persist_reload should call persistence wrapper'
|
|
assert_contains "$(iptables-save)" "MGMT:${uuid_v4}" 'persist_reload should restore IPv4 rule from snapshot'
|
|
|
|
iptables -A FORWARD -p tcp --dport 65000 -j ACCEPT
|
|
|
|
"${ROOT_DIR}/iptables-forward.sh" --batch delete "${uuid_v4}"
|
|
assert_status 1 "$(status_of grep -F "MGMT:${uuid_v4}" <(iptables-save))" 'deleted IPv4 rule should disappear from iptables-save'
|
|
assert_status 0 "$(status_of grep -F -- '--dport 65000 -j ACCEPT' <(iptables-save))" 'unmanaged rule should remain after deleting managed rule'
|
|
assert_not_contains "$(cat "${PERSIST_RULES_V4}")" "MGMT:${uuid_v4}" 'deleting IPv4 rule should refresh persisted snapshot'
|
|
|
|
if command -v ip6tables >/dev/null 2>&1 && command -v ip6tables-save >/dev/null 2>&1 && command -v ip6tables-restore >/dev/null 2>&1; then
|
|
uuid_v6=$("${ROOT_DIR}/iptables-forward.sh" --batch add tcp 65433 ::1 22 6 'integration-v6')
|
|
assert_contains "$(ip6tables-save)" "MGMT:${uuid_v6}" 'IPv6 rule should appear in ip6tables-save output'
|
|
assert_file_contains "${PERSIST_RULES_V6}" "MGMT:${uuid_v6}" 'persist save should write IPv6 rules snapshot'
|
|
ipt_remove_rule "${uuid_v6}" tcp 65433 ::1 22 6
|
|
assert_status 1 "$(status_of grep -F "MGMT:${uuid_v6}" <(ip6tables-save))" 'manual runtime removal should clear managed IPv6 rule'
|
|
persist_reload
|
|
assert_contains "$(ip6tables-save)" "MGMT:${uuid_v6}" 'persist_reload should restore IPv6 rule from snapshot'
|
|
"${ROOT_DIR}/iptables-forward.sh" --batch delete "${uuid_v6}"
|
|
assert_status 1 "$(status_of grep -F "MGMT:${uuid_v6}" <(ip6tables-save))" 'deleted IPv6 rule should disappear from ip6tables-save'
|
|
assert_not_contains "$(cat "${PERSIST_RULES_V6}")" "MGMT:${uuid_v6}" 'deleting IPv6 rule should refresh persisted snapshot'
|
|
fi
|
|
|
|
pass 'test_integration.sh'
|