zerotier: migrate from facts to vars

This commit is contained in:
Jörg Thalheim
2025-04-22 14:36:13 +02:00
parent 3dd6c33200
commit cbde58e1d8
12 changed files with 148 additions and 112 deletions

View File

@@ -13,10 +13,10 @@ let
defaultBootstrapNodes = builtins.foldl' ( defaultBootstrapNodes = builtins.foldl' (
urls: name: urls: name:
if if
builtins.pathExists "${config.clan.core.settings.directory}/machines/${name}/facts/zerotier-ip" builtins.pathExists "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value"
then then
let let
ip = builtins.readFile "${config.clan.core.settings.directory}/machines/${name}/facts/zerotier-ip"; ip = builtins.readFile "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value";
in in
urls ++ "${ip}:${cfg.network.port}" urls ++ "${ip}:${cfg.network.port}"
else else

View File

@@ -26,8 +26,8 @@
config.networking.hosts = config.networking.hosts =
let let
dir = config.clan.core.settings.directory; dir = config.clan.core.settings.directory;
machineDir = dir + "/machines/"; machineDir = "${dir}/vars/per-machine";
zerotierIpMachinePath = machines: machineDir + machines + "/facts/zerotier-ip"; zerotierIpMachinePath = machine: "${machineDir}/${machine}/zerotier/zerotier-ip/value";
machinesFileSet = builtins.readDir machineDir; machinesFileSet = builtins.readDir machineDir;
machines = lib.mapAttrsToList (name: _: name) machinesFileSet; machines = lib.mapAttrsToList (name: _: name) machinesFileSet;
networkIpsUnchecked = builtins.map ( networkIpsUnchecked = builtins.map (

View File

@@ -6,10 +6,9 @@
}: }:
let let
dir = config.clan.core.settings.directory; dir = config.clan.core.settings.directory;
machineDir = dir + "/machines/"; machineVarDir = "${dir}/vars/per-machine/";
machineVarDir = dir + "/vars/per-machine/"; syncthingPublicKeyPath = machine: "${machineVarDir}/${machine}/syncthing/id/value";
syncthingPublicKeyPath = machines: machineVarDir + machines + "/syncthing/id/value"; machinesFileSet = builtins.readDir machineVarDir;
machinesFileSet = builtins.readDir machineDir;
machines = lib.mapAttrsToList (name: _: name) machinesFileSet; machines = lib.mapAttrsToList (name: _: name) machinesFileSet;
syncthingPublicKeysUnchecked = builtins.map ( syncthingPublicKeysUnchecked = builtins.map (
machine: machine:
@@ -19,7 +18,7 @@ let
if builtins.pathExists fullPath then machine else null if builtins.pathExists fullPath then machine else null
) machines; ) machines;
syncthingPublicKeyMachines = lib.filter (machine: machine != null) syncthingPublicKeysUnchecked; syncthingPublicKeyMachines = lib.filter (machine: machine != null) syncthingPublicKeysUnchecked;
zerotierIpMachinePath = machines: machineDir + machines + "/facts/zerotier-ip"; zerotierIpMachinePath = machine: "${machineVarDir}/${machine}/zerotier/zerotier-ip/value";
networkIpsUnchecked = builtins.map ( networkIpsUnchecked = builtins.map (
machine: machine:
let let

View File

@@ -6,15 +6,16 @@
}: }:
let let
dir = config.clan.core.settings.directory; dir = config.clan.core.settings.directory;
machineDir = dir + "/machines/"; machineDir = "${dir}/vars/per-machine";
# TODO: This should use the inventory
# However we are probably going to replace this with the network module.
machinesFileSet = builtins.readDir machineDir; machinesFileSet = builtins.readDir machineDir;
machines = lib.mapAttrsToList (name: _: name) machinesFileSet; machines = lib.mapAttrsToList (name: _: name) machinesFileSet;
zerotierNetworkIdPath = machines: machineDir + machines + "/facts/zerotier-network-id";
networkIdsUnchecked = builtins.map ( networkIdsUnchecked = builtins.map (
machine: machine:
let let
fullPath = zerotierNetworkIdPath machine; fullPath = "${machineDir}/vars/per-machine/${machine}/zerotier/zerotier-network-id/value";
in in
if builtins.pathExists fullPath then builtins.readFile fullPath else null if builtins.pathExists fullPath then builtins.readFile fullPath else null
) machines; ) machines;
@@ -45,13 +46,9 @@ in
config.systemd.services.zerotier-static-peers-autoaccept = config.systemd.services.zerotier-static-peers-autoaccept =
let let
zerotierIpMachinePath = machines: machineDir + machines + "/facts/zerotier-ip"; zerotierIpFor = machine: "${machineDir}/vars/per-machine/${machine}/zerotier/zerotier-ip/value";
networkIpsUnchecked = builtins.map ( networkIpsUnchecked = builtins.map (
machine: machine: if builtins.pathExists (zerotierIpFor machine) then machine else null
let
fullPath = zerotierIpMachinePath machine;
in
if builtins.pathExists fullPath then machine else null
) machines; ) machines;
networkIps = lib.filter (machine: machine != null) networkIpsUnchecked; networkIps = lib.filter (machine: machine != null) networkIpsUnchecked;
machinesWithIp = lib.filterAttrs (name: _: (lib.elem name networkIps)) machinesFileSet; machinesWithIp = lib.filterAttrs (name: _: (lib.elem name networkIps)) machinesFileSet;
@@ -60,11 +57,7 @@ in
) machinesWithIp; ) machinesWithIp;
hosts = lib.mapAttrsToList (host: _: host) ( hosts = lib.mapAttrsToList (host: _: host) (
lib.mapAttrs' ( lib.mapAttrs' (
machine: _: machine: _: lib.nameValuePair (builtins.readFile (zerotierIpFor machine)) [ machine ]
let
fullPath = zerotierIpMachinePath machine;
in
lib.nameValuePair (builtins.readFile fullPath) [ machine ]
) filteredMachines ) filteredMachines
); );
allHostIPs = config.clan.zerotier-static-peers.networkIps ++ hosts; allHostIPs = config.clan.zerotier-static-peers.networkIps ++ hosts;

View File

@@ -23,11 +23,11 @@ in
networkIps = builtins.foldl' ( networkIps = builtins.foldl' (
ips: name: ips: name:
if if
builtins.pathExists "${config.clan.core.settings.directory}/machines/${name}/facts/zerotier-ip" builtins.pathExists "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value"
then then
ips ips
++ [ ++ [
(builtins.readFile "${config.clan.core.settings.directory}/machines/${name}/facts/zerotier-ip") (builtins.readFile "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value")
] ]
else else
ips ips

View File

@@ -10,17 +10,24 @@ let
zeroTierInstance = config.clan.inventory.services.zerotier.${instanceName}; zeroTierInstance = config.clan.inventory.services.zerotier.${instanceName};
roles = zeroTierInstance.roles; roles = zeroTierInstance.roles;
controllerMachine = builtins.head roles.controller.machines; controllerMachine = builtins.head roles.controller.machines;
networkIdPath = "${config.clan.core.settings.directory}/machines/${controllerMachine}/facts/zerotier-network-id"; networkIdPath = "${config.clan.core.settings.directory}/vars/per-machine/${controllerMachine}/zerotier/zerotier-network-id/value";
networkId = if builtins.pathExists networkIdPath then builtins.readFile networkIdPath else null; networkId =
if builtins.pathExists networkIdPath then
builtins.readFile networkIdPath
else
builtins.throw ''
No zerotier network id found for ${controllerMachine}.
Please run `clan vars generate ${controllerMachine}` first.
'';
moons = roles.moon.machines; moons = roles.moon.machines;
moonIps = builtins.foldl' ( moonIps = builtins.foldl' (
ips: name: ips: name:
if if
builtins.pathExists "${config.clan.core.settings.directory}/machines/${name}/facts/zerotier-ip" builtins.pathExists "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value"
then then
ips ips
++ [ ++ [
(builtins.readFile "${config.clan.core.settings.directory}/machines/${name}/facts/zerotier-ip") (builtins.readFile "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value")
] ]
else else
ips ips
@@ -62,7 +69,7 @@ in
clan.core.networking.zerotier.networkId = networkId; clan.core.networking.zerotier.networkId = networkId;
clan.core.networking.zerotier.name = instanceName; clan.core.networking.zerotier.name = instanceName;
# TODO: in future we want to have the node id of our moons in our facts # TODO: in future we want to have the node id of our moons in our vars
systemd.services.zerotierone.serviceConfig.ExecStartPost = lib.mkIf (moonIps != [ ]) ( systemd.services.zerotierone.serviceConfig.ExecStartPost = lib.mkIf (moonIps != [ ]) (
lib.mkAfter [ lib.mkAfter [
"+${pkgs.writeScript "orbit-moons-by-ip" '' "+${pkgs.writeScript "orbit-moons-by-ip" ''

View File

@@ -86,7 +86,7 @@ This guide shows you how to configure `zerotier` either through `NixOS Options`
configuration, substituting `<CONTROLLER>` with the controller machine name: configuration, substituting `<CONTROLLER>` with the controller machine name:
```nix ```nix
{ config, ... }: { { config, ... }: {
clan.core.networking.zerotier.networkId = builtins.readFile (config.clan.core.settings.directory + "/machines/<CONTROLLER>/facts/zerotier-network-id"); clan.core.networking.zerotier.networkId = builtins.readFile ../../vars/per-machine/<CONTROLLER>/zerotier/zerotier-network-id/value;
} }
``` ```
1. **Update the New Machine**: Execute: 1. **Update the New Machine**: Execute:

View File

@@ -2,15 +2,11 @@
config, config,
lib, lib,
pkgs, pkgs,
options,
... ...
}: }:
let let
cfg = config.clan.core.networking.zerotier; cfg = config.clan.core.networking.zerotier;
facts = config.clan.core.facts.services.zerotier.public or { };
genMoonScript = pkgs.runCommand "genmoon" { nativeBuildInputs = [ pkgs.python3 ]; } ''
install -Dm755 ${./genmoon.py} $out/bin/genmoon
patchShebangs $out/bin/genmoon
'';
in in
{ {
options.clan.core.networking.zerotier = { options.clan.core.networking.zerotier = {
@@ -89,15 +85,14 @@ in
}; };
}; };
config = lib.mkMerge [ config = lib.mkMerge [
({ {
# Override license so that we can build zerotierone without # Override license so that we can build zerotierone without
# having to re-import nixpkgs. # having to re-import nixpkgs.
services.zerotierone.package = lib.mkDefault (pkgs.callPackage ../../../pkgs/zerotierone { }); services.zerotierone.package = lib.mkDefault (pkgs.callPackage ../../../pkgs/zerotierone { });
}) }
(lib.mkIf ((facts.zerotier-ip.value or null) != null) {
environment.etc."zerotier/ip".text = facts.zerotier-ip.value;
})
(lib.mkIf (cfg.networkId != null) { (lib.mkIf (cfg.networkId != null) {
environment.etc."zerotier/ip".text =
config.clan.core.vars.generators.zerotier.files.zerotier-ip.value;
systemd.network.networks."09-zerotier" = { systemd.network.networks."09-zerotier" = {
matchConfig.Name = "zt*"; matchConfig.Name = "zt*";
@@ -112,12 +107,12 @@ in
"+${pkgs.writeShellScript "init-zerotier" '' "+${pkgs.writeShellScript "init-zerotier" ''
# compare hashes of the current identity secret and the one in the config # compare hashes of the current identity secret and the one in the config
hash1=$(sha256sum /var/lib/zerotier-one/identity.secret | cut -d ' ' -f 1) hash1=$(sha256sum /var/lib/zerotier-one/identity.secret | cut -d ' ' -f 1)
hash2=$(sha256sum ${config.clan.core.facts.services.zerotier.secret.zerotier-identity-secret.path} | cut -d ' ' -f 1) hash2=$(sha256sum ${config.clan.core.vars.generators.zerotier.files.zerotier-identity-secret.path} | cut -d ' ' -f 1)
if [[ "$hash1" != "$hash2" ]]; then if [[ "$hash1" != "$hash2" ]]; then
echo "Identity secret has changed, backing up old identity to /var/lib/zerotier-one/identity.secret.bac" echo "Identity secret has changed, backing up old identity to /var/lib/zerotier-one/identity.secret.bac"
cp /var/lib/zerotier-one/identity.secret /var/lib/zerotier-one/identity.secret.bac cp /var/lib/zerotier-one/identity.secret /var/lib/zerotier-one/identity.secret.bac
cp /var/lib/zerotier-one/identity.public /var/lib/zerotier-one/identity.public.bac cp /var/lib/zerotier-one/identity.public /var/lib/zerotier-one/identity.public.bac
cp ${config.clan.core.facts.services.zerotier.secret.zerotier-identity-secret.path} /var/lib/zerotier-one/identity.secret cp ${config.clan.core.vars.generators.zerotier.files.zerotier-identity-secret.path} /var/lib/zerotier-one/identity.secret
zerotier-idtool getpublic /var/lib/zerotier-one/identity.secret > /var/lib/zerotier-one/identity.public zerotier-idtool getpublic /var/lib/zerotier-one/identity.secret > /var/lib/zerotier-one/identity.public
fi fi
@@ -129,7 +124,12 @@ in
if [[ ! -f /var/lib/zerotier-one/moon.json ]]; then if [[ ! -f /var/lib/zerotier-one/moon.json ]]; then
zerotier-idtool initmoon /var/lib/zerotier-one/identity.public > /var/lib/zerotier-one/moon.json zerotier-idtool initmoon /var/lib/zerotier-one/identity.public > /var/lib/zerotier-one/moon.json
fi fi
${genMoonScript}/bin/genmoon /var/lib/zerotier-one/moon.json ${builtins.toFile "moon.json" (builtins.toJSON cfg.moon.stableEndpoints)} /var/lib/zerotier-one/moons.d ${
pkgs.runCommand "genmoon" { nativeBuildInputs = [ pkgs.python3 ]; } ''
install -Dm755 ${./genmoon.py} $out/bin/genmoon
patchShebangs $out/bin/genmoon
''
}/bin/genmoon /var/lib/zerotier-one/moon.json ${builtins.toFile "moon.json" (builtins.toJSON cfg.moon.stableEndpoints)} /var/lib/zerotier-one/moons.d
''} ''}
# cleanup old networks # cleanup old networks
@@ -181,22 +181,26 @@ in
services.zerotierone.localConf.settings.tcpFallbackRelay = "65.21.12.51/4443"; services.zerotierone.localConf.settings.tcpFallbackRelay = "65.21.12.51/4443";
}) })
(lib.mkIf cfg.controller.enable { (lib.mkIf cfg.controller.enable {
environment.etc."zerotier/ip".text =
config.clan.core.vars.generators.zerotier.files.zerotier-ip.value;
# only the controller needs to have the key in the repo, the other clients can be dynamic # only the controller needs to have the key in the repo, the other clients can be dynamic
# we generate the zerotier code manually for the controller, since it's part of the bootstrap command # we generate the zerotier code manually for the controller, since it's part of the bootstrap command
clan.core.facts.services.zerotier = { clan.core.vars.generators.zerotier = {
public.zerotier-ip = { }; migrateFact = "zerotier";
public.zerotier-network-id = { }; files.zerotier-ip.secret = false;
secret.zerotier-identity-secret = { }; files.zerotier-network-id.secret = false;
generator.path = [ files.zerotier-identity-secret = { };
runtimeInputs = [
config.services.zerotierone.package config.services.zerotierone.package
pkgs.python3 pkgs.python3
]; ];
generator.script = '' script = ''
source ${(pkgs.callPackage ../../../pkgs/minifakeroot { })}/share/minifakeroot/rc source ${(pkgs.callPackage ../../../pkgs/minifakeroot { })}/share/minifakeroot/rc
python3 ${./generate.py} --mode network \ python3 ${./generate.py} --mode network \
--ip "$facts/zerotier-ip" \ --ip "$out/zerotier-ip" \
--identity-secret "$secrets/zerotier-identity-secret" \ --identity-secret "$out/zerotier-identity-secret" \
--network-id "$facts/zerotier-network-id" --network-id "$out/zerotier-network-id"
''; '';
}; };
clan.core.state.zerotier.folders = [ "/var/lib/zerotier-one" ]; clan.core.state.zerotier.folders = [ "/var/lib/zerotier-one" ];
@@ -204,23 +208,25 @@ in
environment.systemPackages = [ config.clan.core.clanPkgs.zerotier-members ]; environment.systemPackages = [ config.clan.core.clanPkgs.zerotier-members ];
}) })
(lib.mkIf (!cfg.controller.enable && cfg.networkId != null) { (lib.mkIf (!cfg.controller.enable && cfg.networkId != null) {
clan.core.facts.services.zerotier = { clan.core.vars.generators.zerotier = {
public.zerotier-ip = { }; migrateFact = "zerotier";
secret.zerotier-identity-secret = { }; files.zerotier-ip.secret = false;
generator.path = [ files.zerotier-identity-secret = { };
runtimeInputs = [
config.services.zerotierone.package config.services.zerotierone.package
pkgs.python3 pkgs.python3
]; ];
generator.script = '' script = ''
python3 ${./generate.py} --mode identity \ python3 ${./generate.py} --mode identity \
--ip "$facts/zerotier-ip" \ --ip "$out/zerotier-ip" \
--identity-secret "$secrets/zerotier-identity-secret" \ --identity-secret "$out/zerotier-identity-secret" \
--network-id ${cfg.networkId} --network-id ${cfg.networkId}
''; '';
}; };
}) })
(lib.mkIf (cfg.controller.enable && (facts.zerotier-network-id.value or null) != null) { (lib.mkIf (cfg.controller.enable && config.clan.core.vars.generators ? zerotier) {
clan.core.networking.zerotier.networkId = facts.zerotier-network-id.value; clan.core.networking.zerotier.networkId =
config.clan.core.vars.generators.zerotier.files.zerotier-network-id.value;
clan.core.networking.zerotier.settings = { clan.core.networking.zerotier.settings = {
authTokens = [ null ]; authTokens = [ null ];
authorizationEndpoint = ""; authorizationEndpoint = "";
@@ -259,7 +265,8 @@ in
zt = false; zt = false;
}; };
}; };
environment.etc."zerotier/network-id".text = facts.zerotier-network-id.value; environment.etc."zerotier/network-id".text =
config.clan.core.vars.generators.zerotier.files.zerotier-network-id.value;
systemd.services.zerotierone.serviceConfig.ExecStartPost = [ systemd.services.zerotierone.serviceConfig.ExecStartPost = [
"+${pkgs.writeShellScript "whitelist-controller" '' "+${pkgs.writeShellScript "whitelist-controller" ''
${config.clan.core.clanPkgs.zerotier-members}/bin/zerotier-members allow ${ ${config.clan.core.clanPkgs.zerotier-members}/bin/zerotier-members allow ${

View File

@@ -4,7 +4,6 @@ from typing import TYPE_CHECKING
import pytest import pytest
from clan_cli.facts.secret_modules.sops import SecretStore from clan_cli.facts.secret_modules.sops import SecretStore
from clan_cli.flake import Flake from clan_cli.flake import Flake
from clan_cli.machines.facts import machine_get_fact
from clan_cli.machines.machines import Machine from clan_cli.machines.machines import Machine
from clan_cli.secrets.folders import sops_secrets_folder from clan_cli.secrets.folders import sops_secrets_folder
from clan_cli.tests.fixtures_flakes import FlakeForTest from clan_cli.tests.fixtures_flakes import FlakeForTest
@@ -45,66 +44,90 @@ def test_generate_secret(
"user1", "user1",
] ]
) )
cmd = ["facts", "generate", "--flake", str(test_flake_with_core.path), "vm1"] cmd = [
"vars",
"generate",
"--flake",
str(test_flake_with_core.path),
"vm1",
"--generator",
"zerotier",
]
cli.run(cmd) cli.run(cmd)
store1 = SecretStore( store1 = SecretStore(
Machine(name="vm1", flake=Flake(str(test_flake_with_core.path))) Machine(name="vm1", flake=Flake(str(test_flake_with_core.path)))
) )
assert store1.exists("", "age.key") assert store1.exists("", "age.key")
assert store1.exists("", "zerotier-identity-secret") network_id = (
network_id = machine_get_fact( test_flake_with_core.path
test_flake_with_core.path, "vm1", "zerotier-network-id" / "vars"
) / "per-machine"
/ "vm1"
/ "zerotier"
/ "zerotier-network-id"
/ "value"
).read_text()
assert len(network_id) == 16 assert len(network_id) == 16
secrets_folder = sops_secrets_folder(test_flake_with_core.path) secrets_folder = sops_secrets_folder(test_flake_with_core.path)
age_key = secrets_folder / "vm1-age.key" / "secret" age_key = secrets_folder / "vm1-age.key" / "secret"
identity_secret = secrets_folder / "vm1-zerotier-identity-secret" / "secret" identity_secret = (
test_flake_with_core.path
/ "vars"
/ "per-machine"
/ "vm1"
/ "zerotier"
/ "zerotier-identity-secret"
/ "secret"
)
age_key_mtime = age_key.lstat().st_mtime_ns age_key_mtime = age_key.lstat().st_mtime_ns
secret1_mtime = identity_secret.lstat().st_mtime_ns secret1_mtime = identity_secret.lstat().st_mtime_ns
# Assert that the age key is valid # Assert that the age key is valid
age_secret = store1.get("", "age.key").decode() age_secret = store1.get("", "age.key").decode()
assert age_secret.isprintable()
assert is_valid_age_key(age_secret) assert is_valid_age_key(age_secret)
# test idempotency for vm1 and also generate for vm2 # test idempotency for vm1 and also generate for vm2
cli.run(["facts", "generate", "--flake", str(test_flake_with_core.path)]) cli.run(
[
"vars",
"generate",
"--flake",
str(test_flake_with_core.path),
"--generator",
"zerotier",
]
)
assert age_key.lstat().st_mtime_ns == age_key_mtime assert age_key.lstat().st_mtime_ns == age_key_mtime
assert identity_secret.lstat().st_mtime_ns == secret1_mtime assert identity_secret.lstat().st_mtime_ns == secret1_mtime
assert (
secrets_folder / "vm1-zerotier-identity-secret" / "machines" / "vm1"
).exists()
store2 = SecretStore( store2 = SecretStore(
Machine(name="vm2", flake=Flake(str(test_flake_with_core.path))) Machine(name="vm2", flake=Flake(str(test_flake_with_core.path)))
) )
# clan vars generate
# TODO: Test vars
# varsStore = VarsSecretStore(
# machine=Machine(name="vm2", flake=FlakeId(str(test_flake_with_core.path)))
# )
# generators = get_generators(str(test_flake_with_core.path), "vm2")
# generator = next((gen for gen in generators if gen.name == "root-password"), None)
# if not generator:
# raise Exception("Generator not found")
# password_update = GeneratorUpdate(
# generator=generator.name, prompt_values={"password": "1234"}
# )
# set_prompts(str(test_flake_with_core.path), "vm2", [password_update])
# assert varsStore.exists(generator, "root-password")
assert store2.exists("", "age.key") assert store2.exists("", "age.key")
assert store2.exists("", "zerotier-identity-secret") (
test_flake_with_core.path
/ "vars"
/ "per-machine"
/ "vm2"
/ "zerotier"
/ "zerotier-identity-secret"
/ "secret"
).exists()
ip = machine_get_fact(test_flake_with_core.path, "vm1", "zerotier-ip") ip = (
test_flake_with_core.path
/ "vars"
/ "per-machine"
/ "vm2"
/ "zerotier"
/ "zerotier-ip"
/ "value"
).read_text()
assert ipaddress.IPv6Address(ip).is_private assert ipaddress.IPv6Address(ip).is_private
# Assert that the age key is valid # Assert that the age key is valid
age_secret = store2.get("", "age.key").decode() age_secret = store2.get("", "age.key").decode()
assert age_secret.isprintable()
assert is_valid_age_key(age_secret) assert is_valid_age_key(age_secret)

View File

@@ -2,10 +2,6 @@ import subprocess
from pathlib import Path from pathlib import Path
import pytest import pytest
from clan_cli.facts.secret_modules.password_store import SecretStore
from clan_cli.flake import Flake
from clan_cli.machines.facts import machine_get_fact
from clan_cli.machines.machines import Machine
from clan_cli.nix import nix_shell from clan_cli.nix import nix_shell
from clan_cli.ssh.host import Host from clan_cli.ssh.host import Host
from clan_cli.tests.fixtures_flakes import ClanFlake from clan_cli.tests.fixtures_flakes import ClanFlake
@@ -32,6 +28,8 @@ def test_upload_secret(
config["clan"]["core"]["networking"]["targetHost"] = addr config["clan"]["core"]["networking"]["targetHost"] = addr
config["clan"]["user-password"]["user"] = "alice" config["clan"]["user-password"]["user"] = "alice"
config["clan"]["user-password"]["prompt"] = False config["clan"]["user-password"]["prompt"] = False
vars_config = config["clan"]["core"]["vars"]
vars_config["settings"]["secretStore"] = "password-store"
facts = config["clan"]["core"]["facts"] facts = config["clan"]["core"]["facts"]
facts["secretStore"] = "password-store" facts["secretStore"] = "password-store"
facts["secretUploadDirectory"]["_type"] = "override" facts["secretUploadDirectory"]["_type"] = "override"
@@ -62,23 +60,32 @@ def test_upload_secret(
check=True, check=True,
) )
subprocess.run(nix_shell(["pass"], ["pass", "init", "test@local"]), check=True) subprocess.run(nix_shell(["pass"], ["pass", "init", "test@local"]), check=True)
cli.run(["facts", "generate", "vm1", "--flake", str(flake.path)]) cli.run(["vars", "generate", "vm1", "--flake", str(flake.path), "--generator", "zerotier"])
store = SecretStore(Machine(name="vm1", flake=Flake(str(flake.path)))) network_id = (
flake.path
network_id = machine_get_fact(flake.path, "vm1", "zerotier-network-id") / "vars"
/ "per-machine"
/ "vm1"
/ "zerotier"
/ "zerotier-network-id"
/ "value"
).read_text()
assert len(network_id) == 16 assert len(network_id) == 16
identity_secret = ( identity_secret = (
temporary_home / "pass" / "machines" / "vm1" / "zerotier-identity-secret.gpg" temporary_home
/ "pass"
/ "clan-vars"
/ "per-machine"
/ "vm1"
/ "zerotier"
/ "zerotier-identity-secret.gpg"
) )
secret1_mtime = identity_secret.lstat().st_mtime_ns secret1_mtime = identity_secret.lstat().st_mtime_ns
# test idempotency # test idempotency
cli.run(["facts", "generate", "vm1"]) cli.run(["vars", "generate", "vm1", "--generator", "zerotier"])
assert identity_secret.lstat().st_mtime_ns == secret1_mtime assert identity_secret.lstat().st_mtime_ns == secret1_mtime
cli.run(["facts", "upload", "vm1"]) cli.run(["vars", "upload", "vm1"])
zerotier_identity_secret = flake.path / "secrets" / "zerotier-identity-secret" zerotier_identity_secret = flake.path / "secrets" / "zerotier-identity-secret"
assert zerotier_identity_secret.exists() assert zerotier_identity_secret.exists()
assert store.exists("", "zerotier-identity-secret")
assert store.exists("", "zerotier-identity-secret")

View File

@@ -100,7 +100,7 @@
This will allow sara to share the VPN overlay network with jon This will allow sara to share the VPN overlay network with jon
The networkId is generated by the first deployment of jon The networkId is generated by the first deployment of jon
*/ */
# clan.core.networking.zerotier.networkId = builtins.readFile ../jon/facts/zerotier-network-id; # clan.core.networking.zerotier.networkId = builtins.readFile ../../vars/per-machine/jon/zerotier/zerotier-network-id/value;
}; };
}; };
}; };

View File

@@ -30,5 +30,5 @@
This will allow sara to share the VPN overlay network with jon This will allow sara to share the VPN overlay network with jon
The networkId is generated by the first deployment of jon The networkId is generated by the first deployment of jon
*/ */
# clan.core.networking.zerotier.networkId = builtins.readFile ../jon/facts/zerotier-network-id; # clan.core.networking.zerotier.networkId = builtins.readFile ../../vars/per-machine/jon/zerotier/zerotier-network-id/value;
} }