| 
									
										
										
										
											2021-03-04 21:03:17 -08:00
										 |  |  | import ./make-test-python.nix ({ pkgs, lib, ... }: let | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # We'll need to be able to trade cert files between nodes via scp. | 
					
						
							|  |  |  |   inherit (import ./ssh-keys.nix pkgs) | 
					
						
							|  |  |  |     snakeOilPrivateKey snakeOilPublicKey; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   makeNebulaNode = { config, ... }: name: extraConfig: lib.mkMerge [ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       # Expose nebula for doing cert signing. | 
					
						
							|  |  |  |       environment.systemPackages = [ pkgs.nebula ]; | 
					
						
							|  |  |  |       users.users.root.openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; | 
					
						
							|  |  |  |       services.openssh.enable = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       services.nebula.networks.smoke = { | 
					
						
							|  |  |  |         # Note that these paths won't exist when the machine is first booted. | 
					
						
							|  |  |  |         ca = "/etc/nebula/ca.crt"; | 
					
						
							|  |  |  |         cert = "/etc/nebula/${name}.crt"; | 
					
						
							|  |  |  |         key = "/etc/nebula/${name}.key"; | 
					
						
							|  |  |  |         listen = { host = "0.0.0.0"; port = 4242; }; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     extraConfig | 
					
						
							|  |  |  |   ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | in | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   name = "nebula"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   nodes = { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lighthouse = { ... } @ args: | 
					
						
							|  |  |  |       makeNebulaNode args "lighthouse" { | 
					
						
							|  |  |  |         networking.interfaces.eth1.ipv4.addresses = [{ | 
					
						
							|  |  |  |           address = "192.168.1.1"; | 
					
						
							|  |  |  |           prefixLength = 24; | 
					
						
							|  |  |  |         }]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         services.nebula.networks.smoke = { | 
					
						
							|  |  |  |           isLighthouse = true; | 
					
						
							|  |  |  |           firewall = { | 
					
						
							|  |  |  |             outbound = [ { port = "any"; proto = "any"; host = "any"; } ]; | 
					
						
							|  |  |  |             inbound = [ { port = "any"; proto = "any"; host = "any"; } ]; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     node2 = { ... } @ args: | 
					
						
							|  |  |  |       makeNebulaNode args "node2" { | 
					
						
							|  |  |  |         networking.interfaces.eth1.ipv4.addresses = [{ | 
					
						
							|  |  |  |           address = "192.168.1.2"; | 
					
						
							|  |  |  |           prefixLength = 24; | 
					
						
							|  |  |  |         }]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         services.nebula.networks.smoke = { | 
					
						
							|  |  |  |           staticHostMap = { "10.0.100.1" = [ "192.168.1.1:4242" ]; }; | 
					
						
							|  |  |  |           isLighthouse = false; | 
					
						
							|  |  |  |           lighthouses = [ "10.0.100.1" ]; | 
					
						
							|  |  |  |           firewall = { | 
					
						
							|  |  |  |             outbound = [ { port = "any"; proto = "any"; host = "any"; } ]; | 
					
						
							|  |  |  |             inbound = [ { port = "any"; proto = "any"; host = "any"; } ]; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 21:28:25 -08:00
										 |  |  |     node3 = { ... } @ args: | 
					
						
							|  |  |  |       makeNebulaNode args "node3" { | 
					
						
							|  |  |  |         networking.interfaces.eth1.ipv4.addresses = [{ | 
					
						
							|  |  |  |           address = "192.168.1.3"; | 
					
						
							|  |  |  |           prefixLength = 24; | 
					
						
							|  |  |  |         }]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         services.nebula.networks.smoke = { | 
					
						
							|  |  |  |           staticHostMap = { "10.0.100.1" = [ "192.168.1.1:4242" ]; }; | 
					
						
							|  |  |  |           isLighthouse = false; | 
					
						
							|  |  |  |           lighthouses = [ "10.0.100.1" ]; | 
					
						
							|  |  |  |           firewall = { | 
					
						
							|  |  |  |             outbound = [ { port = "any"; proto = "any"; host = "any"; } ]; | 
					
						
							|  |  |  |             inbound = [ { port = "any"; proto = "any"; host = "lighthouse"; } ]; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     node4 = { ... } @ args: | 
					
						
							|  |  |  |       makeNebulaNode args "node4" { | 
					
						
							|  |  |  |         networking.interfaces.eth1.ipv4.addresses = [{ | 
					
						
							|  |  |  |           address = "192.168.1.4"; | 
					
						
							|  |  |  |           prefixLength = 24; | 
					
						
							|  |  |  |         }]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         services.nebula.networks.smoke = { | 
					
						
							| 
									
										
										
										
											2021-04-10 16:38:44 -06:00
										 |  |  |           enable = true; | 
					
						
							|  |  |  |           staticHostMap = { "10.0.100.1" = [ "192.168.1.1:4242" ]; }; | 
					
						
							|  |  |  |           isLighthouse = false; | 
					
						
							|  |  |  |           lighthouses = [ "10.0.100.1" ]; | 
					
						
							|  |  |  |           firewall = { | 
					
						
							|  |  |  |             outbound = [ { port = "any"; proto = "any"; host = "lighthouse"; } ]; | 
					
						
							|  |  |  |             inbound = [ { port = "any"; proto = "any"; host = "any"; } ]; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     node5 = { ... } @ args: | 
					
						
							|  |  |  |       makeNebulaNode args "node5" { | 
					
						
							|  |  |  |         networking.interfaces.eth1.ipv4.addresses = [{ | 
					
						
							|  |  |  |           address = "192.168.1.5"; | 
					
						
							|  |  |  |           prefixLength = 24; | 
					
						
							|  |  |  |         }]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         services.nebula.networks.smoke = { | 
					
						
							|  |  |  |           enable = false; | 
					
						
							| 
									
										
										
										
											2021-03-04 21:28:25 -08:00
										 |  |  |           staticHostMap = { "10.0.100.1" = [ "192.168.1.1:4242" ]; }; | 
					
						
							|  |  |  |           isLighthouse = false; | 
					
						
							|  |  |  |           lighthouses = [ "10.0.100.1" ]; | 
					
						
							|  |  |  |           firewall = { | 
					
						
							|  |  |  |             outbound = [ { port = "any"; proto = "any"; host = "lighthouse"; } ]; | 
					
						
							|  |  |  |             inbound = [ { port = "any"; proto = "any"; host = "any"; } ]; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 21:03:17 -08:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   testScript = let | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setUpPrivateKey = name: ''
 | 
					
						
							|  |  |  |     ${name}.succeed( | 
					
						
							|  |  |  |         "mkdir -p /root/.ssh", | 
					
						
							|  |  |  |         "chown 700 /root/.ssh", | 
					
						
							|  |  |  |         "cat '${snakeOilPrivateKey}' > /root/.ssh/id_snakeoil", | 
					
						
							|  |  |  |         "chown 600 /root/.ssh/id_snakeoil", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # From what I can tell, StrictHostKeyChecking=no is necessary for ssh to work between machines. | 
					
						
							|  |  |  |     sshOpts = "-oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oIdentityFile=/root/.ssh/id_snakeoil"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     restartAndCheckNebula = name: ip: ''
 | 
					
						
							|  |  |  |       ${name}.systemctl("restart nebula@smoke.service") | 
					
						
							|  |  |  |       ${name}.succeed("ping -c5 ${ip}") | 
					
						
							|  |  |  |     '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Create a keypair on the client node, then use the public key to sign a cert on the lighthouse. | 
					
						
							|  |  |  |     signKeysFor = name: ip: ''
 | 
					
						
							|  |  |  |       lighthouse.wait_for_unit("sshd.service") | 
					
						
							|  |  |  |       ${name}.wait_for_unit("sshd.service") | 
					
						
							|  |  |  |       ${name}.succeed( | 
					
						
							|  |  |  |           "mkdir -p /etc/nebula", | 
					
						
							|  |  |  |           "nebula-cert keygen -out-key /etc/nebula/${name}.key -out-pub /etc/nebula/${name}.pub", | 
					
						
							|  |  |  |           "scp ${sshOpts} /etc/nebula/${name}.pub 192.168.1.1:/tmp/${name}.pub", | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |       lighthouse.succeed( | 
					
						
							|  |  |  |           'nebula-cert sign -ca-crt /etc/nebula/ca.crt -ca-key /etc/nebula/ca.key -name "${name}" -groups "${name}" -ip "${ip}" -in-pub /tmp/${name}.pub -out-crt /tmp/${name}.crt', | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |       ${name}.succeed( | 
					
						
							|  |  |  |           "scp ${sshOpts} 192.168.1.1:/tmp/${name}.crt /etc/nebula/${name}.crt", | 
					
						
							|  |  |  |           "scp ${sshOpts} 192.168.1.1:/etc/nebula/ca.crt /etc/nebula/ca.crt", | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |     '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   in ''
 | 
					
						
							|  |  |  |     start_all() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Create the certificate and sign the lighthouse's keys. | 
					
						
							|  |  |  |     ${setUpPrivateKey "lighthouse"} | 
					
						
							|  |  |  |     lighthouse.succeed( | 
					
						
							|  |  |  |         "mkdir -p /etc/nebula", | 
					
						
							|  |  |  |         'nebula-cert ca -name "Smoke Test" -out-crt /etc/nebula/ca.crt -out-key /etc/nebula/ca.key', | 
					
						
							|  |  |  |         'nebula-cert sign -ca-crt /etc/nebula/ca.crt -ca-key /etc/nebula/ca.key -name "lighthouse" -groups "lighthouse" -ip "10.0.100.1/24" -out-crt /etc/nebula/lighthouse.crt -out-key /etc/nebula/lighthouse.key', | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Reboot the lighthouse and verify that the nebula service comes up on boot. | 
					
						
							|  |  |  |     # Since rebooting takes a while, we'll just restart the service on the other nodes. | 
					
						
							|  |  |  |     lighthouse.shutdown() | 
					
						
							|  |  |  |     lighthouse.start() | 
					
						
							|  |  |  |     lighthouse.wait_for_unit("nebula@smoke.service") | 
					
						
							|  |  |  |     lighthouse.succeed("ping -c5 10.0.100.1") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 21:28:25 -08:00
										 |  |  |     # Create keys for node2's nebula service and test that it comes up. | 
					
						
							| 
									
										
										
										
											2021-03-04 21:03:17 -08:00
										 |  |  |     ${setUpPrivateKey "node2"} | 
					
						
							|  |  |  |     ${signKeysFor "node2" "10.0.100.2/24"} | 
					
						
							|  |  |  |     ${restartAndCheckNebula "node2" "10.0.100.2"} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 21:28:25 -08:00
										 |  |  |     # Create keys for node3's nebula service and test that it comes up. | 
					
						
							|  |  |  |     ${setUpPrivateKey "node3"} | 
					
						
							|  |  |  |     ${signKeysFor "node3" "10.0.100.3/24"} | 
					
						
							|  |  |  |     ${restartAndCheckNebula "node3" "10.0.100.3"} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Create keys for node4's nebula service and test that it comes up. | 
					
						
							|  |  |  |     ${setUpPrivateKey "node4"} | 
					
						
							|  |  |  |     ${signKeysFor "node4" "10.0.100.4/24"} | 
					
						
							|  |  |  |     ${restartAndCheckNebula "node4" "10.0.100.4"} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-10 16:38:44 -06:00
										 |  |  |     # Create keys for node4's nebula service and test that it does not come up. | 
					
						
							|  |  |  |     ${setUpPrivateKey "node5"} | 
					
						
							|  |  |  |     ${signKeysFor "node5" "10.0.100.5/24"} | 
					
						
							|  |  |  |     node5.fail("systemctl status nebula@smoke.service") | 
					
						
							|  |  |  |     node5.fail("ping -c5 10.0.100.5") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # The lighthouse can ping node2 and node3 but not node5 | 
					
						
							| 
									
										
										
										
											2021-03-04 21:28:25 -08:00
										 |  |  |     lighthouse.succeed("ping -c3 10.0.100.2") | 
					
						
							|  |  |  |     lighthouse.succeed("ping -c3 10.0.100.3") | 
					
						
							| 
									
										
										
										
											2021-04-10 16:38:44 -06:00
										 |  |  |     lighthouse.fail("ping -c3 10.0.100.5") | 
					
						
							| 
									
										
										
										
											2021-03-04 21:28:25 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # node2 can ping the lighthouse, but not node3 because of its inbound firewall | 
					
						
							|  |  |  |     node2.succeed("ping -c3 10.0.100.1") | 
					
						
							|  |  |  |     node2.fail("ping -c3 10.0.100.3") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # node3 can ping the lighthouse and node2 | 
					
						
							|  |  |  |     node3.succeed("ping -c3 10.0.100.1") | 
					
						
							|  |  |  |     node3.succeed("ping -c3 10.0.100.2") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # node4 can ping the lighthouse but not node2 or node3 | 
					
						
							|  |  |  |     node4.succeed("ping -c3 10.0.100.1") | 
					
						
							|  |  |  |     node4.fail("ping -c3 10.0.100.2") | 
					
						
							|  |  |  |     node4.fail("ping -c3 10.0.100.3") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # node2 can ping node3 now that node3 pinged it first | 
					
						
							|  |  |  |     node2.succeed("ping -c3 10.0.100.3") | 
					
						
							|  |  |  |     # node4 can ping node2 if node2 pings it first | 
					
						
							|  |  |  |     node2.succeed("ping -c3 10.0.100.4") | 
					
						
							|  |  |  |     node4.succeed("ping -c3 10.0.100.2") | 
					
						
							| 
									
										
										
										
											2021-03-04 21:03:17 -08:00
										 |  |  |   '';
 | 
					
						
							| 
									
										
										
										
											2021-03-04 21:39:04 -08:00
										 |  |  | }) |