vuls: init at 0.27.0 (#348530)
[NixPkgs.git] / nixos / tests / yggdrasil.nix
blob70d148380bf754321ee7c0f39993662803184573
1 let
2   aliceIp6 = "202:b70:9b0b:cf34:f93c:8f18:bbfd:7034";
3   aliceKeys = {
4     PublicKey = "3e91ec9e861960d86e1ce88051f97c435bdf2859640ab681dfa906eb45ad5182";
5     PrivateKey = "a867f9e078e4ce58d310cf5acd4622d759e2a21df07e1d6fc380a2a26489480d3e91ec9e861960d86e1ce88051f97c435bdf2859640ab681dfa906eb45ad5182";
6   };
7   bobIp6 = "202:a483:73a4:9f2d:a559:4a19:bc9:8458";
8   bobPrefix = "302:a483:73a4:9f2d";
9   bobConfig = {
10     InterfacePeers = {
11       eth1 = [ "tcp://192.168.1.200:12345" ];
12     };
13     MulticastInterfaces = [ {
14       Regex = ".*";
15       Beacon = true;
16       Listen = true;
17       Port = 54321;
18       Priority = 0;
19     } ];
20     PublicKey = "2b6f918b6c1a4b54d6bcde86cf74e074fb32ead4ee439b7930df2aa60c825186";
21     PrivateKey = "0c4a24acd3402722ce9277ed179f4a04b895b49586493c25fbaed60653d857d62b6f918b6c1a4b54d6bcde86cf74e074fb32ead4ee439b7930df2aa60c825186";
22   };
23   danIp6 = bobPrefix + "::2";
25 in import ./make-test-python.nix ({ pkgs, ...} : {
26   name = "yggdrasil";
27   meta = with pkgs.lib.maintainers; {
28     maintainers = [ gazally ];
29   };
31   nodes = rec {
32     # Alice is listening for peerings on a specified port,
33     # but has multicast peering disabled.  Alice has part of her
34     # yggdrasil config in Nix and part of it in a file.
35     alice =
36       { ... }:
37       {
38         networking = {
39           interfaces.eth1.ipv4.addresses = [{
40             address = "192.168.1.200";
41             prefixLength = 24;
42           }];
43           firewall.allowedTCPPorts = [ 80 12345 ];
44         };
45         services.httpd.enable = true;
46         services.httpd.adminAddr = "foo@example.org";
48         services.yggdrasil = {
49           enable = true;
50           settings = {
51             Listen = ["tcp://0.0.0.0:12345"];
52             MulticastInterfaces = [ ];
53           };
54           configFile = toString (pkgs.writeTextFile {
55                          name = "yggdrasil-alice-conf";
56                          text = builtins.toJSON aliceKeys;
57                        });
58         };
59       };
61     # Bob is set up to peer with Alice, and also to do local multicast
62     # peering.  Bob's yggdrasil config is in a file.
63     bob =
64       { ... }:
65       {
66         networking.firewall.allowedTCPPorts = [ 54321 ];
67         services.yggdrasil = {
68           enable = true;
69           openMulticastPort = true;
70           configFile = toString (pkgs.writeTextFile {
71                          name = "yggdrasil-bob-conf";
72                          text = builtins.toJSON bobConfig;
73                        });
74         };
76         boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
78         networking = {
79           bridges.br0.interfaces = [ ];
80           interfaces.br0 = {
81             ipv6.addresses = [{
82               address = bobPrefix + "::1";
83               prefixLength = 64;
84             }];
85           };
86         };
88         # dan is a node inside a container running on bob's host.
89         containers.dan = {
90           autoStart = true;
91           privateNetwork = true;
92           hostBridge = "br0";
93           config = { config, pkgs, ... }: {
94             networking.interfaces.eth0.ipv6 = {
95               addresses = [{
96                 address = bobPrefix + "::2";
97                 prefixLength = 64;
98               }];
99               routes = [{
100                 address = "200::";
101                 prefixLength = 7;
102                 via = bobPrefix + "::1";
103               }];
104             };
105             services.httpd.enable = true;
106             services.httpd.adminAddr = "foo@example.org";
107             networking.firewall.allowedTCPPorts = [ 80 ];
108           };
109         };
110       };
112     # Carol only does local peering.  Carol's yggdrasil config is all Nix.
113     carol =
114       { ... }:
115       {
116         networking.firewall.allowedTCPPorts = [ 43210 ];
117         services.yggdrasil = {
118           enable = true;
119           extraArgs = [ "-loglevel" "error" ];
120           denyDhcpcdInterfaces = [ "ygg0" ];
121           settings = {
122             IfTAPMode = true;
123             IfName = "ygg0";
124             MulticastInterfaces = [
125               {
126                 Port = 43210;
127               }
128             ];
129             openMulticastPort = true;
130           };
131           persistentKeys = true;
132         };
133       };
134     };
136   testScript =
137     ''
138       import re
140       # Give Alice a head start so she is ready when Bob calls.
141       alice.start()
142       alice.wait_for_unit("yggdrasil.service")
144       bob.start()
145       carol.start()
146       bob.wait_for_unit("default.target")
147       carol.wait_for_unit("yggdrasil.service")
149       ip_addr_show = "ip -o -6 addr show dev ygg0 scope global"
150       carol.wait_until_succeeds(f"[ `{ip_addr_show} | grep -v tentative | wc -l` -ge 1 ]")
151       carol_ip6 = re.split(" +|/", carol.succeed(ip_addr_show))[3]
153       # If Alice can talk to Carol, then Bob's outbound peering and Carol's
154       # local peering have succeeded and everybody is connected.
155       alice.wait_until_succeeds(f"ping -c 1 {carol_ip6}")
156       alice.succeed("ping -c 1 ${bobIp6}")
158       bob.succeed("ping -c 1 ${aliceIp6}")
159       bob.succeed(f"ping -c 1 {carol_ip6}")
161       carol.succeed("ping -c 1 ${aliceIp6}")
162       carol.succeed("ping -c 1 ${bobIp6}")
163       carol.succeed("ping -c 1 ${bobPrefix}::1")
164       carol.succeed("ping -c 8 ${danIp6}")
166       carol.fail("journalctl -u dhcpcd | grep ygg0")
168       alice.wait_for_unit("httpd.service")
169       carol.succeed("curl --fail -g http://[${aliceIp6}]")
170       carol.succeed("curl --fail -g http://[${danIp6}]")
171     '';