72414fb64ee91744881f1c9b6790b930598232b1
[tinc] / test / integration / invite_tinc_up.py
1 #!/usr/bin/env python3
2
3 """Test inviting tinc nodes through tinc-up script."""
4
5 import os
6 import typing as T
7
8 from testlib import check, util
9 from testlib.log import log
10 from testlib.proc import Tinc, Script
11 from testlib.test import Test
12
13 IFCONFIG = "93.184.216.34/24"
14 ROUTES_IPV6 = ("2606:2800:220:1::/64", "2606:2800:220:1:248:1893:25c8:1946")
15 BAD_IPV4 = "1234::"
16 ED_PUBKEY = "Ed25519PublicKey"
17
18
19 def make_inv_created(export_output: str) -> str:
20     """Generate script for invitation-created script."""
21     return f'''
22     node, invite = os.environ['NODE'], os.environ['INVITATION_FILE']
23     log.info('writing to invitation file %s, node %s', invite, node)
24
25     script = f"""
26 Name = {{node}}
27 Ifconfig = {IFCONFIG}
28 Route = {' '.join(ROUTES_IPV6)}
29 Route = 1.2.3.4 {BAD_IPV4}
30
31 {export_output}
32 """.strip()
33
34     with open(invite, 'w', encoding='utf-8') as f:
35         f.write(script)
36     '''
37
38
39 def init(ctx: Test) -> T.Tuple[Tinc, Tinc]:
40     """Initialize new test nodes."""
41     foo, bar = ctx.node(), ctx.node()
42
43     stdin = f"""
44         init {foo}
45         set Port 0
46         set DeviceType dummy
47         set Address localhost
48     """
49     foo.cmd(stdin=stdin)
50     foo.start()
51
52     return foo, bar
53
54
55 def run_tests(ctx: Test) -> None:
56     """Run all tests."""
57     foo, bar = init(ctx)
58
59     log.info("run export")
60     export, _ = foo.cmd("export")
61     assert export
62
63     log.info("adding invitation-created script")
64     code = make_inv_created(export)
65     foo.add_script(Script.INVITATION_CREATED, code)
66
67     log.info("inviting %s", bar)
68     url, _ = foo.cmd("invite", bar.name)
69     url = url.strip()
70     assert url
71
72     log.info('joining %s to %s with "%s"', bar, foo, url)
73     bar.cmd("--batch", "join", url)
74     bar.cmd("set", "Port", "0")
75
76     log.info("comparing host configs")
77     check.files_eq(foo.sub("hosts", foo.name), bar.sub("hosts", foo.name))
78
79     log.info("comparing public keys")
80     foo_key = util.find_line(foo.sub("hosts", bar.name), ED_PUBKEY)
81     bar_key = util.find_line(bar.sub("hosts", bar.name), ED_PUBKEY)
82     check.equals(foo_key, bar_key)
83
84     log.info("bar.tinc-up must not exist")
85     assert not os.path.exists(bar.sub("tinc-up"))
86
87     inv = bar.sub("tinc-up.invitation")
88     log.info("testing %s", inv)
89
90     content = util.read_text(inv)
91     check.is_in(IFCONFIG, content)
92     check.not_in(BAD_IPV4, content)
93
94     for route in ROUTES_IPV6:
95         check.is_in(route, content)
96
97     if os.name != "nt":
98         assert not os.access(inv, os.X_OK)
99
100
101 with Test("invite-tinc-up") as context:
102     run_tests(context)