Commit 5e81ade3 authored by zhifan huang's avatar zhifan huang

add hmac test

parent 1c601542
...@@ -2,10 +2,12 @@ import subprocess ...@@ -2,10 +2,12 @@ import subprocess
from subprocess import PIPE from subprocess import PIPE
import weakref import weakref
import sys import sys
import os
import logging import logging
import time import time
import ipaddress import ipaddress
class NetManager(object): class NetManager(object):
"""contain all the nemu object created, so they can live more time""" """contain all the nemu object created, so they can live more time"""
def __init__(self): def __init__(self):
...@@ -67,6 +69,7 @@ class Netns(object): ...@@ -67,6 +69,7 @@ class Netns(object):
self.run(['sysctl', '-w', 'net.ipv4.ip_forward=1'], stdout=PIPE) self.run(['sysctl', '-w', 'net.ipv4.ip_forward=1'], stdout=PIPE)
self.run(['sysctl', '-w', 'net.ipv6.conf.default.forwarding=1'], stdout=PIPE) self.run(['sysctl', '-w', 'net.ipv6.conf.default.forwarding=1'], stdout=PIPE)
# self.run(['sysctl', '-q', 'net.ipv4.icmp_echo_ignore_broadcasts=0'], stdout=PIPE)
def Popen(self, cmd, stdout=sys.stdout, stderr=sys.stderr,**kw): def Popen(self, cmd, stdout=sys.stdout, stderr=sys.stderr,**kw):
...@@ -74,7 +77,7 @@ class Netns(object): ...@@ -74,7 +77,7 @@ class Netns(object):
return subprocess.Popen(['nsenter', '-t', str(self.pid), '-n'] + cmd, stdout=stdout, stderr=stderr, **kw) return subprocess.Popen(['nsenter', '-t', str(self.pid), '-n'] + cmd, stdout=stdout, stderr=stderr, **kw)
def run(self, cmd, stdout=sys.stdout, stderr=sys.stderr,**kw): def run(self, cmd, check=True, stdout=sys.stdout, stderr=sys.stderr,**kw):
""" wrapper for subprocess.checkout""" """ wrapper for subprocess.checkout"""
subprocess.check_call(['nsenter', '-t', str(self.pid), '-n'] + cmd, stdout=stdout, stderr=stderr, **kw) subprocess.check_call(['nsenter', '-t', str(self.pid), '-n'] + cmd, stdout=stdout, stderr=stderr, **kw)
...@@ -127,6 +130,11 @@ class Netns(object): ...@@ -127,6 +130,11 @@ class Netns(object):
router.run(['ip', 'link', 'set', dev2.name, 'master', router.bridge.name]) router.run(['ip', 'link', 'set', dev2.name, 'master', router.bridge.name])
return dev1, dev2 return dev1, dev2
def __del__(self):
try:
self.proc.terminate()
except:
pass
def connectible_test(nm): def connectible_test(nm):
"""test each node can ping to their registry """test each node can ping to their registry
...@@ -169,7 +177,7 @@ def net_route(): ...@@ -169,7 +177,7 @@ def net_route():
node1 = Netns() node1 = Netns()
node2 = Netns() node2 = Netns()
veth_r = registry.connect_router(router) veth_r, _ = registry.connect_router(router)
veth_n1, _ = node1.connect_router(router) veth_n1, _ = node1.connect_router(router)
veth_n2, _ = node2.connect_router(router) veth_n2, _ = node2.connect_router(router)
...@@ -247,6 +255,11 @@ def net_demo(): ...@@ -247,6 +255,11 @@ def net_demo():
for node in [node1, node2]: for node in [node1, node2]:
node.add_route("10.0.0.0/8", 'via', "10.1.1.1") node.add_route("10.0.0.0/8", 'via', "10.1.1.1")
gateway1.run(['iptables', '-t', 'nat', '-A', 'POSTROUTING', '-o', veth_g1_1.name, '-j', 'MASQUERADE'])
gateway1.run(['iptables', '-t', 'nat', '-N', 'MINIUPNPD'])
gateway1.run(['iptables', '-t', 'nat', '-A', 'PREROUTING', '-i', veth_g1_1.name, '-j', 'MINIUPNPD'])
gateway1.run(['iptables', '-N', 'MINIUPNPD'])
veth_it3.add_ip4("10.2.0.1", 24) veth_it3.add_ip4("10.2.0.1", 24)
veth_g2_1.add_ip4("10.2.0.2", 24) veth_g2_1.add_ip4("10.2.0.2", 24)
gateway2.add_route("10.0.0.0/8", 'via', "10.2.0.1") gateway2.add_route("10.0.0.0/8", 'via', "10.2.0.1")
...@@ -267,7 +280,7 @@ def net_demo(): ...@@ -267,7 +280,7 @@ def net_demo():
for node in [node6, node7, node8]: for node in [node6, node7, node8]:
node.add_route("10.0.0.0/8", 'via', "10.0.1.1") node.add_route("10.0.0.0/8", 'via', "10.0.1.1")
internet.add_route("10.1.0.0/16", 'via', "10.1.0.2") # internet.add_route("10.1.0.0/16", 'via', "10.1.0.2")
internet.add_route("10.2.0.0/16", 'via', "10.2.0.2") internet.add_route("10.2.0.0/16", 'via', "10.2.0.2")
...@@ -276,6 +289,9 @@ def net_demo(): ...@@ -276,6 +289,9 @@ def net_demo():
nm.registrys[registry] = [node1, node2, node3, node4, node5, node6, node7, node8] nm.registrys[registry] = [node1, node2, node3, node4, node5, node6, node7, node8]
connectible_test(nm) connectible_test(nm)
gateway1.proc = gateway1.Popen(['miniupnpd', '-d', '-f', 'miniupnpd.conf', '-P', 'miniupnpd.pid',
'-a', gateway1.devices[-1].name, '-i', gateway1.devices[-1].name], stdout=PIPE, stderr=PIPE)
return nm return nm
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -9,7 +9,6 @@ time, sequence number, number of non-responding machines, ip of these machines ...@@ -9,7 +9,6 @@ time, sequence number, number of non-responding machines, ip of these machines
import argparse, errno, socket, time, sys import argparse, errno, socket, time, sys
from multiping import MultiPing from multiping import MultiPing
PING_INTERVAL = 10
PING_TIMEOUT = 4 PING_TIMEOUT = 4
class MultiPing(MultiPing): class MultiPing(MultiPing):
......
...@@ -12,12 +12,14 @@ from pathlib2 import Path ...@@ -12,12 +12,14 @@ from pathlib2 import Path
import re6st.tests.tools as tools import re6st.tests.tools as tools
WORK_DIR = Path(__file__).parent.resolve() / "temp_net_test"
WORK_DIR = Path(__file__).parent / "temp_net_test"
DH_FILE = WORK_DIR / "dh2048.pem" DH_FILE = WORK_DIR / "dh2048.pem"
RE6STNET = "re6stnet" RE6STNET = "re6stnet"
#RE6ST_REGISTRY = "re6st-registry" RE6ST_REGISTRY = "re6st-registry"
RE6ST_REGISTRY = "python -m re6st.cli.registry" #RE6ST_REGISTRY = "python -m re6st.cli.registry"
RE6ST_CONF = "re6st-conf" RE6ST_CONF = "re6st-conf"
def initial(): def initial():
...@@ -66,7 +68,14 @@ class Re6stRegistry(object): ...@@ -66,7 +68,14 @@ class Re6stRegistry(object):
text = f.read() text = f.read()
self.ident = hash(text) self.ident = hash(text)
# clear log file
if self.log.exists():
self.log.unlink()
self.clean()
self.run() self.run()
# wait the servcice started # wait the servcice started
self.node.Popen(['python', '-c', """if 1: self.node.Popen(['python', '-c', """if 1:
...@@ -105,8 +114,14 @@ class Re6stRegistry(object): ...@@ -105,8 +114,14 @@ class Re6stRegistry(object):
cmd = cmd.format(script=RE6ST_REGISTRY, ca=self.ca_crt, cmd = cmd.format(script=RE6ST_REGISTRY, ca=self.ca_crt,
key=self.ca_key, dh=DH_FILE, log=self.log, db=self.db, key=self.ca_key, dh=DH_FILE, log=self.log, db=self.db,
run=self.run_path).split() run=self.run_path).split()
logging.info("run registry {} with cmd: {}".format(self.name, " ".join(cmd)))
self.proc = self.node.Popen(cmd, stdout=PIPE, stderr=PIPE) self.proc = self.node.Popen(cmd, stdout=PIPE, stderr=PIPE)
def clean(self):
"""remove the file created last time"""
for f in [self.db, self.log]:
if f.exists():
f.unlink()
def __del__(self): def __del__(self):
try: try:
...@@ -132,13 +147,14 @@ class Re6stNode(object): ...@@ -132,13 +147,14 @@ class Re6stNode(object):
self.email = self.name + "@example.com" self.email = self.name + "@example.com"
self.run_path = tempfile.mkdtemp() self.run_path = tempfile.mkdtemp()
self.log = self.path / "re6stnet.log"
self.crt = self.path / "cert.crt" self.crt = self.path / "cert.crt"
self.key = self.path / 'cert.key' self.key = self.path / 'cert.key'
self.console = self.run_path + "/console.sock" self.console = self.run_path + "/console.sock"
self.data_file = self.path / "data.json" # contain data for restart node self.data_file = self.path / "data.json" # contain data for restart node
# condition node of the registry # condition, node of the registry
if self.name == self.registry.name: if self.name == self.registry.name:
self.ip6 = self.registry.ip6 self.ip6 = self.registry.ip6
if not self.crt.exists(): if not self.crt.exists():
...@@ -159,7 +175,10 @@ class Re6stNode(object): ...@@ -159,7 +175,10 @@ class Re6stNode(object):
if not self.path.exists(): if not self.path.exists():
self.path.mkdir() self.path.mkdir()
self.create_node() self.create_node()
logging.info("{}'s subnet is {}".format(self.name, self.ip6))
logging.debug("{}'s subnet is {}".format(self.name, self.ip6))
self.clean()
@classmethod @classmethod
...@@ -170,12 +189,12 @@ class Re6stNode(object): ...@@ -170,12 +189,12 @@ class Re6stNode(object):
def create_node(self): def create_node(self):
"""create necessary file for node""" """create necessary file for node"""
logging.info("create dir of node {}".format(self.name)) logging.info("create dir of node {}".format(self.name))
cmd = "{script} --registry {registry_url} --email {email}" cmd = "{script} --registry {registry_url} --email {email}"
cmd = cmd.format(script=RE6ST_CONF, registry_url=self.registry.url, cmd = cmd.format(script=RE6ST_CONF, registry_url=self.registry.url,
email=self.email).split() email=self.email).split()
p = self.node.Popen(cmd, stdin=PIPE, stdout=PIPE, cwd=str(self.path)) p = self.node.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=str(self.path))
# read token # read token
db = sqlite3.connect(str(self.registry.db), isolation_level=None) db = sqlite3.connect(str(self.registry.db), isolation_level=None)
count = 0 count = 0
...@@ -190,13 +209,13 @@ class Re6stNode(object): ...@@ -190,13 +209,13 @@ class Re6stNode(object):
raise Exception("can't connect to the Register") raise Exception("can't connect to the Register")
out, _ = p.communicate(str(token[0])) out, _ = p.communicate(str(token[0]))
logging.debug("re6st-conf output: {}".format(out)) # logging.debug("re6st-conf output: {}".format(out))
# find the ipv6 subnet of node # find the ipv6 subnet of node
self.ip6 = re.search('(?<=subnet: )[0-9:a-z]+', out).group(0) self.ip6 = re.search('(?<=subnet: )[0-9:a-z]+', out).group(0)
data = {'ip6': self.ip6, 'hash': self.registry.ident} data = {'ip6': self.ip6, 'hash': self.registry.ident}
with open(str(self.data_file), 'w') as f: with open(str(self.data_file), 'w') as f:
json.dump(data, f) json.dump(data, f)
logging.info("create dir of node {} finish".format(self.name))
def run(self, *args): def run(self, *args):
"""execute re6stnet""" """execute re6stnet"""
...@@ -209,8 +228,16 @@ class Re6stNode(object): ...@@ -209,8 +228,16 @@ class Re6stNode(object):
cert=self.crt, key=self.key, registry=self.registry.url, cert=self.crt, key=self.key, registry=self.registry.url,
console=self.console).split() console=self.console).split()
cmd += args cmd += args
logging.info("run node {} with cmd: {}".format(self.name, " ".join(cmd)))
self.proc = self.node.Popen(cmd, stdout=PIPE, stderr=PIPE) self.proc = self.node.Popen(cmd, stdout=PIPE, stderr=PIPE)
def clean(self):
"""remove the file created last time"""
for name in ["re6stnet.log", "babeld.state", "cache.db"]:
f = self.path / name
if f.exists():
f.unlink()
def __del__(self): def __del__(self):
try: try:
self.proc.terminate() self.proc.terminate()
......
...@@ -5,10 +5,12 @@ import subprocess ...@@ -5,10 +5,12 @@ import subprocess
import sys import sys
import os import os
import logging import logging
import sqlite3
from pathlib2 import Path from pathlib2 import Path
import re6st_wrap import re6st_wrap
import my_net import my_net
import hmac
PING_PATH = str(Path(__file__).parent.resolve() / "ping.py") PING_PATH = str(Path(__file__).parent.resolve() / "ping.py")
...@@ -16,8 +18,10 @@ def deploy_re6st(nm): ...@@ -16,8 +18,10 @@ def deploy_re6st(nm):
net = nm.registrys net = nm.registrys
nodes = [] nodes = []
registrys = [] registrys = []
re6st_wrap.Re6stRegistry.registry_seq = 0
re6st_wrap.Re6stNode.node_seq = 0
for registry in net: for registry in net:
reg = re6st_wrap.Re6stRegistry(registry, "2001:db8:42::", recreate=False) reg = re6st_wrap.Re6stRegistry(registry, "2001:db8:42::", recreate=True)
reg_node = re6st_wrap.Re6stNode(registry, reg, name=reg.name) reg_node = re6st_wrap.Re6stNode(registry, reg, name=reg.name)
registrys.append(reg) registrys.append(reg)
reg_node.run("--gateway", "--disable-proto", "none", "--ip", registry.ip) reg_node.run("--gateway", "--disable-proto", "none", "--ip", registry.ip)
...@@ -28,17 +32,23 @@ def deploy_re6st(nm): ...@@ -28,17 +32,23 @@ def deploy_re6st(nm):
nodes.append(node) nodes.append(node)
return nodes, registrys return nodes, registrys
def wait_stable(nodes, timeout=180): def wait_stable(nodes, timeout=240):
logging.info("wait all node stable") """try use ping6 from each node to the other until ping success to all the other nodes
@timeout: int, the time for wait
@return: True if success
"""
logging.info("wait all node stable, timeout:{}".format(timeout))
now = time.time() now = time.time()
# wait all the nodes can connect to each other
ips = {node.ip6:node.name for node in nodes} ips = {node.ip6:node.name for node in nodes}
# start the ping processs
for node in nodes: for node in nodes:
sub_ips = set(ips) - {node.ip6} sub_ips = set(ips) - {node.ip6}
node.ping_proc = node.node.Popen( node.ping_proc = node.node.Popen(
["python", PING_PATH, '--retry', '-a'] + list(sub_ips)) ["python", PING_PATH, '--retry', '-a'] + list(sub_ips))
# check all the node network can ping each other, in order reverse
unfinished = list(nodes) unfinished = list(nodes)
# check all the node network can ping each other
while len(unfinished): while len(unfinished):
for i in range(len(unfinished)-1,-1,-1): for i in range(len(unfinished)-1,-1,-1):
node = unfinished[i] node = unfinished[i]
...@@ -50,7 +60,7 @@ def wait_stable(nodes, timeout=180): ...@@ -50,7 +60,7 @@ def wait_stable(nodes, timeout=180):
if time.time() - now > timeout: if time.time() - now > timeout:
for node in unfinished: for node in unfinished:
node.ping_proc.terminate() node.ping_proc.terminate()
raise Exception("wait network stable timeout") return False
def ping_test(nodes): def ping_test(nodes):
"""test Re6st node connecty """ """test Re6st node connecty """
...@@ -60,7 +70,7 @@ def ping_test(nodes): ...@@ -60,7 +70,7 @@ def ping_test(nodes):
for node in nodes: for node in nodes:
sub_ips = set(ips) - {node.ip6} sub_ips = set(ips) - {node.ip6}
node.ping_proc = node.node.Popen( node.ping_proc = node.node.Popen(
["python", PING_PATH, '--retry', '-a'] + list(sub_ips), stdout=subprocess.PIPE) ["python", PING_PATH, '-a'] + list(sub_ips), stdout=subprocess.PIPE)
out, _ = node.ping_proc.communicate() out, _ = node.ping_proc.communicate()
unreached = [ ips[addr] for addr in out.split()] unreached = [ ips[addr] for addr in out.split()]
if unreached: if unreached:
...@@ -70,37 +80,35 @@ def ping_test(nodes): ...@@ -70,37 +80,35 @@ def ping_test(nodes):
return failed return failed
@unittest.skipIf(os.geteuid() != 0, "require root") @unittest.skipIf(os.geteuid() != 0, "require root or create user namespace plz")
class TestPing(unittest.TestCase): class TestNet(unittest.TestCase):
"""" ping-test case""" """" ping-test case"""
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
"""create work dir""" """create work dir"""
logging.basicConfig(level=logging.INFO) # logging.basicConfig(level=logging.INFO)
re6st_wrap.initial() re6st_wrap.initial()
def tearDown(self):
# terminate all the sub process
return
def test_sample(self):
"""create a network demo, test the connectivity by ping
wait the network stable then ping 3 times
"""
nm = my_net.net_demo()
nodes, registrys = deploy_re6st(nm)
wait_stable(nodes) @classmethod
for i in range(3): def tearDown(cls):
time.sleep(20) # logging.basicConfig(level=logging.WARNING)
self.assertFalse(ping_test(nodes), "N.{} ping test failed".format(i)) pass
# def test_routeur(self): # def test_ping_demo(self):
# """create a network demo, test the connectivity by ping # """create a network demo, test the connectivity by ping
# wait the network stable then ping 3 times # wait at most 60 seconds, and test each node ping to other by ipv6 addr
# """
# nm = my_net.net_demo()
# nodes, registrys = deploy_re6st(nm)
# # wait 60, if the re6stnet stable quit wait
# wait_stable(nodes, 50)
# time.sleep(10)
# self.assertFalse(wait_stable(nodes, 40), " ping test failed")
# def test_ping_router(self):
# """create a network in a net segment, test the connectivity by ping
# """ # """
# nm = my_net.net_route() # nm = my_net.net_route()
# nodes, registrys = deploy_re6st(nm) # nodes, registrys = deploy_re6st(nm)
...@@ -110,8 +118,57 @@ class TestPing(unittest.TestCase): ...@@ -110,8 +118,57 @@ class TestPing(unittest.TestCase):
# time.sleep(20) # time.sleep(20)
# self.assertFalse(ping_test(nodes), "N.{} ping test failed".format(i)) # self.assertFalse(ping_test(nodes), "N.{} ping test failed".format(i))
def test_hmac(self):
"""create a network demo, and run hmac test, this test check hmac 3 times
"""
nm = my_net.net_demo()
nodes, registrys = deploy_re6st(nm)
updateHMAC = ['python', '-c', "import urllib, sys; sys.exit("
"204 != urllib.urlopen('http://127.0.0.1/updateHMAC').code)"]
registry = registrys[0]
machine1 = nodes[1]
reg1_db = sqlite3.connect(str(registry.db), isolation_level=None, check_same_thread=False)
print reg1_db.text_factory
reg1_db.text_factory = str
m_net1 = [node.name for node in nodes]
# wait net stable
time.sleep(45)
logging.info('Check that the initial HMAC config is deployed on network 1')
self.assertTrue(hmac.checkHMAC(reg1_db, m_net1), "first hmac check failed")
# check the update abillity
logging.info('Test that a HMAC update works with nodes that are up')
registry.node.run(updateHMAC)
logging.info('Updated HMAC (config = hmac0 & hmac1), waiting...')
time.sleep(60)
# Checking HMAC on machines connected to registry 1...
self.assertTrue(hmac.checkHMAC(reg1_db, m_net1), "second hmac check failed: HMAC update don't work")
# check if one machine restarted
logging.info('Test that machines can update upon reboot '
'when they were off during a HMAC update.')
logging.info('Re6st on {} is stopped'.format(machine1.name))
machine1.proc.kill()
time.sleep(5)
registry.node.run(updateHMAC)
logging.info('Updated HMAC on registry (config = hmac1 & hmac2), waiting...')
time.sleep(60)
machine1.run()
logging.info( 'Started re6st on {}, waiting for it to get new conf'.format(machine1.name))
time.sleep(80)
# logging.info( 'Checking HMAC on machines connected to registry 1...')
self.assertTrue(hmac.checkHMAC(reg1_db, m_net1), "third hmac check failed: machine restart failed")
logging.info( 'Testing of HMAC done!')
reg1_db.close()
if __name__ == "__main__": if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG, filename='test.log', filemode='w')
unittest.main(verbosity=3) unittest.main(verbosity=3)
......
...@@ -3,8 +3,14 @@ import os ...@@ -3,8 +3,14 @@ import os
import time import time
import subprocess import subprocess
from OpenSSL import crypto
from re6st import registry with open(os.devnull, "wb") as null:
tmp = sys.stderr
sys.stderr = null
# avoid the python version error
from OpenSSL import crypto
from re6st import registry
sys.stderr = tmp
def generate_csr(): def generate_csr():
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment