#!/usr/bin/env bash set -eo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" TACHYON_LIB="$ROOT_DIR/tachyon/files/usr/lib" WORK_DIR="$(mktemp -d)" cleanup() { rm -rf "$WORK_DIR" } trap cleanup EXIT fail() { printf 'FAIL: %s\n' "$1" >&2 exit 1 } # 1. Test split-domain-subnet-file with plain IPs, CIDRs, and domains cat >"$WORK_DIR/mixed.txt" <<'EOF' # Sample list with mixed domains, raw IPs, and subnets example.com 1.2.3.4 sub.domain.org 192.168.10.0/24 2001:db8::1 2606:4700::/32 test-site.ru EOF DOMAINS_OUT="$WORK_DIR/domains.txt" SUBNETS_OUT="$WORK_DIR/subnets.txt" ucode -L "$TACHYON_LIB" "$TACHYON_LIB/nft/apply.uc" split-domain-subnet-file \ "$WORK_DIR/mixed.txt" "$DOMAINS_OUT" "$SUBNETS_OUT" grep -q "example.com" "$DOMAINS_OUT" || fail "domains.txt missing example.com" grep -q "sub.domain.org" "$DOMAINS_OUT" || fail "domains.txt missing sub.domain.org" grep -q "test-site.ru" "$DOMAINS_OUT" || fail "domains.txt missing test-site.ru" # Crucial check: plain IPs must NOT be in domains.txt! if grep -q "1.2.3.4" "$DOMAINS_OUT"; then fail "1.2.3.4 was erroneously placed in domains.txt" fi if grep -q "2001:db8::1" "$DOMAINS_OUT"; then fail "2001:db8::1 was erroneously placed in domains.txt" fi grep -q "1.2.3.4" "$SUBNETS_OUT" || fail "subnets.txt missing raw IP 1.2.3.4" grep -q "192.168.10.0/24" "$SUBNETS_OUT" || fail "subnets.txt missing subnet 192.168.10.0/24" grep -q "2001:db8::1" "$SUBNETS_OUT" || fail "subnets.txt missing IPv6 2001:db8::1" grep -q "2606:4700::/32" "$SUBNETS_OUT" || fail "subnets.txt missing IPv6 CIDR" # 2. Test normalize_plain_ruleset_value in routing/rulesets.uc ucode -L "$TACHYON_LIB" -e ' let rulesets = require("routing.rulesets"); let ip = require("core.ip"); // IP addresses must return null for kind == "domains" let dom_res = rulesets.normalize_plain_ruleset_value("1.2.3.4", "domains"); if (dom_res != null) { warn("FAIL: 1.2.3.4 returned non-null domain: ", dom_res, "\n"); exit(1); } let cidr_res = rulesets.normalize_plain_ruleset_value("10.0.0.0/8", "domains"); if (cidr_res != null) { warn("FAIL: 10.0.0.0/8 returned non-null domain: ", cidr_res, "\n"); exit(1); } let sub_res = rulesets.normalize_plain_ruleset_value("1.2.3.4", "subnets"); if (sub_res != "1.2.3.4") { warn("FAIL: 1.2.3.4 was not accepted as subnet\n"); exit(1); } ' || fail "normalize_plain_ruleset_value check failed" # 3. Test validator accepts .txt alongside .lst ucode -L "$TACHYON_LIB" "$TACHYON_LIB/config/validator.uc" plain-domain-ip-list-reference-valid "/etc/tachyon/list.txt" || fail "/etc/tachyon/list.txt was rejected by validator" ucode -L "$TACHYON_LIB" "$TACHYON_LIB/config/validator.uc" plain-domain-ip-list-reference-valid "/etc/tachyon/list.lst" || fail "/etc/tachyon/list.lst was rejected by validator" ucode -L "$TACHYON_LIB" "$TACHYON_LIB/config/validator.uc" plain-domain-ip-list-reference-valid "https://example.com/list.txt" || fail "https://example.com/list.txt was rejected by validator" if ucode -L "$TACHYON_LIB" "$TACHYON_LIB/config/validator.uc" plain-domain-ip-list-reference-valid "/etc/tachyon/list.invalid" >/dev/null 2>&1; then fail "/etc/tachyon/list.invalid was accepted by validator" fi # 4. Test that nft_populate_runtime_set_for_section populates subnets from domain_ip_lists (.txt and .lst) NFT_LOG="$WORK_DIR/nft.log" LOGGER_LOG="$WORK_DIR/logger.log" export NFT_LOG LOGGER_LOG mkdir -p "$WORK_DIR/bin" cat >"$WORK_DIR/bin/nft" <<'NFT' #!/usr/bin/env bash set -eo pipefail { printf 'nft' for arg in "$@"; do printf '\t%s' "$arg" done printf '\n' } >> "${NFT_LOG:?}" if [ "$1" = "-f" ] && [ -f "$2" ]; then while read -r line || [ -n "$line" ]; do if [[ "$line" =~ ^add[[:space:]]+element[[:space:]]+inet[[:space:]]+([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+(.*)$ ]]; then printf 'nft\tadd\telement\tinet\t%s\t%s\t%s\n' "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}" >> "${NFT_LOG:?}" else printf '%s\n' "$line" >> "${NFT_LOG:?}" fi done < "$2" fi exit 0 NFT chmod +x "$WORK_DIR/bin/nft" cat >"$WORK_DIR/bin/logger" <<'LOGGER' #!/usr/bin/env bash exit 0 LOGGER chmod +x "$WORK_DIR/bin/logger" cat >"$WORK_DIR/bin/ip" <<'IP' #!/usr/bin/env bash exit 0 IP chmod +x "$WORK_DIR/bin/ip" OLD_PATH="$PATH" export PATH="$WORK_DIR/bin:$PATH" cat >"$WORK_DIR/subnets1.txt" <<'EOF' # Local subnets in .txt 198.51.100.77 203.0.113.0/24 2001:db8::77 domain-in-subnets.com EOF cat >"$WORK_DIR/subnets2.lst" <<'EOF' # Local subnets in .lst with port 198.51.100.88 EOF cat >"$WORK_DIR/test-populate-fixture.json" < "$NFT_LOG" ucode -L "$TACHYON_LIB" "$TACHYON_LIB/nft/apply.uc" nft-populate-runtime-sets-fixture \ "$WORK_DIR/test-populate-fixture.json" 1 "" TachyonTable tachyon_subnets tachyon_ports tachyon_ip_ports tachyon_interfaces localv4 0x00100000 grep -q "tachyon_rule_sec_txt_subnets.*198.51.100.77" "$NFT_LOG" || fail "sec_txt IPv4 subnets from .txt missing in nft set" grep -q "tachyon_rule_sec_txt_subnets6.*2001:db8::77" "$NFT_LOG" || fail "sec_txt IPv6 subnets from .txt missing in nft set" grep -q "198.51.100.88 . 443" "$NFT_LOG" || fail "sec_lst_ports scoped ip-port missing in nft set" if grep -q "domain-in-subnets.com" "$NFT_LOG"; then fail "domain name unexpectedly placed in nft ip set" fi export PATH="$OLD_PATH" echo "PASS: domain_ip_lists_subnets_nft"