Skip to content

Commit

Permalink
tests: add netns to testing framework
Browse files Browse the repository at this point in the history
  • Loading branch information
nixbitcoin committed Jul 17, 2020
1 parent 1274526 commit a3aaff1
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 11 deletions.
91 changes: 80 additions & 11 deletions test/test-script.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ def assert_matches(cmd, regexp):
raise Exception(f"Pattern '{regexp}' not found in '{out}'")


def assert_matches_exactly(cmd, regexp):
out = succeed(cmd)
if not re.fullmatch(regexp, out):
raise Exception(f"Pattern '{regexp}' doesn't match '{out}'")


def log_has_string(unit, str):
return f"journalctl -b --output=cat -u {unit} --grep='{str}'"

Expand Down Expand Up @@ -38,13 +44,15 @@ def assert_running(unit):
assert_matches("su operator -c 'bitcoin-cli getnetworkinfo' | jq", '"version"')

assert_running("electrs")
machine.wait_for_open_port(4224) # prometeus metrics provider
machine.wait_until_succeeds(
"ip netns exec nb-electrs nc -z localhost 4224"
) # prometeus metrics provider
# Check RPC connection to bitcoind
machine.wait_until_succeeds(log_has_string("electrs", "NetworkInfo"))
assert_running("nginx")
# SSL stratum server via nginx. Only check for open port, no content is served here
# as electrs isn't ready.
machine.wait_for_open_port(50003)
machine.wait_until_succeeds("ip netns exec nb-nginx nc -z localhost 50003")
# Stop electrs from spamming the test log with 'wait for bitcoind sync' messages
succeed("systemctl stop electrs")

Expand All @@ -58,31 +66,92 @@ def assert_running(unit):

assert_running("spark-wallet")
spark_auth = re.search("login=(.*)", succeed("cat /secrets/spark-wallet-login"))[1]
machine.wait_for_open_port(9737)
assert_matches(f"curl -s {spark_auth}@localhost:9737", "Spark")
machine.wait_until_succeeds("ip netns exec nb-spark-wallet nc -z 169.254.1.17 9737")
assert_matches(f"ip netns exec nb-spark-wallet curl -s {spark_auth}@169.254.1.17:9737", "Spark")

assert_running("lightning-charge")
charge_auth = re.search("API_TOKEN=(.*)", succeed("cat /secrets/lightning-charge-env"))[1]
machine.wait_for_open_port(9112)
assert_matches(f"curl -s api-token:{charge_auth}@localhost:9112/info | jq", '"id"')
machine.wait_until_succeeds("ip netns exec nb-nanopos nc -z 169.254.1.18 9112")
assert_matches(
f"ip netns exec nb-nanopos curl -s api-token:{charge_auth}@169.254.1.18:9112/info | jq", '"id"',
)

assert_running("nanopos")
machine.wait_for_open_port(9116)
assert_matches("curl localhost:9116", "tshirt")
machine.wait_until_succeeds("ip netns exec nb-lightning-charge nc -z 169.254.1.19 9116")
assert_matches("ip netns exec nb-lightning-charge curl 169.254.1.19:9116", "tshirt")

assert_running("onion-chef")

# FIXME: use 'wait_for_unit' because 'create-web-index' always fails during startup due
# to incomplete unit dependencies.
# 'create-web-index' implicitly tests 'nodeinfo'.
machine.wait_for_unit("create-web-index")
machine.wait_for_open_port(80)
assert_matches("curl localhost", "nix-bitcoin")
assert_matches("curl -L localhost/store", "tshirt")
machine.wait_until_succeeds("ip netns exec nb-nginx nc -z localhost 80")
assert_matches("ip netns exec nb-nginx curl localhost", "nix-bitcoin")
assert_matches("ip netns exec nb-nginx curl -L localhost/store", "tshirt")

machine.wait_until_succeeds(log_has_string("bitcoind-import-banlist", "Importing node banlist"))
assert_no_failure("bitcoind-import-banlist")

### Security tests

# Positive ping tests (non-exhaustive)
machine.succeed(
"bitcoindip='169.254.1.12' && \
clightningip='169.254.1.13' && \
lndip='169.254.1.14' && \
liquiddip='169.254.1.15' && \
electrsip='169.254.1.16' && \
sparkwalletip='169.254.1.17' && \
lightningchargeip='169.254.1.18' && \
nanoposip='169.254.1.19' && \
recurringdonationsip='169.254.1.20' && \
nginxip='169.254.1.21' && \
ip netns exec nb-bitcoind ping -c 1 -w 1 $bitcoindip && \
ip netns exec nb-bitcoind ping -c 1 -w 1 $clightningip && \
ip netns exec nb-bitcoind ping -c 1 -w 1 $liquiddip && \
ip netns exec nb-nanopos ping -c 1 -w 1 $lightningchargeip && \
ip netns exec nb-nanopos ping -c 1 -w 1 $nanoposip && \
ip netns exec nb-nanopos ping -c 1 -w 1 $nginxip"
)

# Negative ping tests (non-exhaustive)
machine.fail(
"bitcoindip='169.254.1.12' && \
clightningip='169.254.1.13' && \
lndip='169.254.1.14' && \
liquiddip='169.254.1.15' && \
electrsip='169.254.1.16' && \
sparkwalletip='169.254.1.17' && \
lightningchargeip='169.254.1.18' && \
nanoposip='169.254.1.19' && \
recurringdonationsip='169.254.1.20' && \
nginxip='169.254.1.21' && \
ip netns exec nb-bitcoind ping -c 1 -w 1 $sparkwalletip || \
ip netns exec nb-bitcoind ping -c 1 -w 1 $lightningchargeip || \
ip netns exec nb-bitcoind ping -c 1 -w 1 $nanoposip || \
ip netns exec nb-bitcoind ping -c 1 -w 1 $recurringdonationsip || \
ip netns exec nb-bitcoind ping -c 1 -w 1 $nginxip || \
ip netns exec nb-nanopos ping -c 1 -w 1 $bitcoindip || \
ip netns exec nb-nanopos ping -c 1 -w 1 $clightningip || \
ip netns exec nb-nanopos ping -c 1 -w 1 $lndip || \
ip netns exec nb-nanopos ping -c 1 -w 1 $liquidip || \
ip netns exec nb-nanopos ping -c 1 -w 1 $electrsip || \
ip netns exec nb-nanopos ping -c 1 -w 1 $sparkwalletip || \
ip netns exec nb-nanopos ping -c 1 -w 1 $recurringdonationsip"
)

# test that netns-exec can't be run for unauthorized namespace
machine.fail("netns-exec nb-electrs ip a")

# test that netns-exec drops capabilities
assert_matches_exactly(
"su operator -c 'netns-exec nb-bitcoind capsh --print | grep Current '", "Current: =\n"
)

# test that netns-exec can not be executed by users that are not operator
machine.fail("sudo -u clightning netns-exec nb-bitcoind ip a")

### Additional tests

# Current time in µs
Expand Down
2 changes: 2 additions & 0 deletions test/test.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import ./make-test.nix rec {
# hardened
];

nix-bitcoin.netns-isolation.enable = mkForce true;

services.bitcoind.extraConfig = mkForce "connect=0";

services.clightning.enable = true;
Expand Down

0 comments on commit a3aaff1

Please sign in to comment.