zerotier: migrate from facts to vars
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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" ''
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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 ${
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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")
|
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user