Merge pull request 'add zerotier-members script' (#374) from Mic92-main into main
This commit is contained in:
@@ -99,6 +99,8 @@ in
|
|||||||
${pkgs.python3.interpreter} ${./generate-network.py} "$facts/zerotier-network-id" "$secrets/zerotier-identity-secret"
|
${pkgs.python3.interpreter} ${./generate-network.py} "$facts/zerotier-network-id" "$secrets/zerotier-identity-secret"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
environment.etc."zerotier/network-id".text = facts.zerotier-network-id.value;
|
||||||
|
environment.systemPackages = [ config.clanCore.clanPkgs.zerotier-members ];
|
||||||
})
|
})
|
||||||
(lib.mkIf ((config.clanCore.secrets ? zerotier) && (facts.zerotier-network-id.value != null)) {
|
(lib.mkIf ((config.clanCore.secrets ? zerotier) && (facts.zerotier-network-id.value != null)) {
|
||||||
clan.networking.zerotier.networkId = facts.zerotier-network-id.value;
|
clan.networking.zerotier.networkId = facts.zerotier-network-id.value;
|
||||||
@@ -106,9 +108,15 @@ in
|
|||||||
systemd.services.zerotierone.serviceConfig.ExecStartPre = [
|
systemd.services.zerotierone.serviceConfig.ExecStartPre = [
|
||||||
"+${pkgs.writeShellScript "init-zerotier" ''
|
"+${pkgs.writeShellScript "init-zerotier" ''
|
||||||
cp ${config.clanCore.secrets.zerotier.secrets.zerotier-identity-secret.path} /var/lib/zerotier-one/identity.secret
|
cp ${config.clanCore.secrets.zerotier.secrets.zerotier-identity-secret.path} /var/lib/zerotier-one/identity.secret
|
||||||
|
mkdir -p /var/lib/zerotier-one/controller.d/network
|
||||||
ln -sfT ${pkgs.writeText "net.json" (builtins.toJSON networkConfig)} /var/lib/zerotier-one/controller.d/network/${cfg.networkId}.json
|
ln -sfT ${pkgs.writeText "net.json" (builtins.toJSON networkConfig)} /var/lib/zerotier-one/controller.d/network/${cfg.networkId}.json
|
||||||
''}"
|
''}"
|
||||||
];
|
];
|
||||||
|
systemd.services.zerotierone.serviceConfig.ExecStartPost = [
|
||||||
|
"+${pkgs.writeShellScript "whitelist-controller" ''
|
||||||
|
${config.clanCore.clanPkgs.zerotier-members}/bin/zerotier-members allow ${builtins.substring 0 10 cfg.networkId}
|
||||||
|
''}"
|
||||||
|
];
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
perSystem = { pkgs, config, ... }: {
|
perSystem = { pkgs, config, ... }: {
|
||||||
packages = {
|
packages = {
|
||||||
tea-create-pr = pkgs.callPackage ./tea-create-pr { };
|
tea-create-pr = pkgs.callPackage ./tea-create-pr { };
|
||||||
|
zerotier-members = pkgs.callPackage ./zerotier-members { };
|
||||||
merge-after-ci = pkgs.callPackage ./merge-after-ci {
|
merge-after-ci = pkgs.callPackage ./merge-after-ci {
|
||||||
inherit (config.packages) tea-create-pr;
|
inherit (config.packages) tea-create-pr;
|
||||||
};
|
};
|
||||||
|
|||||||
14
pkgs/zerotier-members/default.nix
Normal file
14
pkgs/zerotier-members/default.nix
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{ stdenv, python3, lib }:
|
||||||
|
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "zerotier-members";
|
||||||
|
src = ./.;
|
||||||
|
buildInputs = [ python3 ];
|
||||||
|
installPhase = ''
|
||||||
|
install -Dm755 ${./zerotier-members.py} $out/bin/zerotier-members
|
||||||
|
'';
|
||||||
|
meta = with lib; {
|
||||||
|
description = "A tool to list/allow members of a ZeroTier network";
|
||||||
|
license = licenses.mit;
|
||||||
|
};
|
||||||
|
}
|
||||||
78
pkgs/zerotier-members/zerotier-members.py
Executable file
78
pkgs/zerotier-members/zerotier-members.py
Executable file
@@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import argparse
|
||||||
|
import http.client
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ZEROTIER_STATE_DIR = Path("/var/lib/zerotier-one")
|
||||||
|
|
||||||
|
|
||||||
|
class ClanError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# this is managed by the nixos module
|
||||||
|
def get_network_id() -> str:
|
||||||
|
p = Path("/etc/zerotier/network-id")
|
||||||
|
if not p.exists():
|
||||||
|
raise ClanError(
|
||||||
|
f"{p} file not found. Have you enabled the zerotier controller on this host?"
|
||||||
|
)
|
||||||
|
return p.read_text().strip()
|
||||||
|
|
||||||
|
|
||||||
|
def allow_member(args: argparse.Namespace) -> None:
|
||||||
|
member_id = args.member_id
|
||||||
|
network_id = get_network_id()
|
||||||
|
token = ZEROTIER_STATE_DIR.joinpath("authtoken.secret").read_text()
|
||||||
|
conn = http.client.HTTPConnection("localhost", 9993)
|
||||||
|
conn.request(
|
||||||
|
"POST",
|
||||||
|
f"/controller/network/{network_id}/member/{member_id}",
|
||||||
|
'{"authorized": true}',
|
||||||
|
{"X-ZT1-AUTH": token},
|
||||||
|
)
|
||||||
|
resp = conn.getresponse()
|
||||||
|
if resp.status != 200:
|
||||||
|
raise ClanError(
|
||||||
|
f"the zerotier daemon returned this error: {resp.status} {resp.reason}"
|
||||||
|
)
|
||||||
|
print(resp.status, resp.reason)
|
||||||
|
|
||||||
|
|
||||||
|
def list_members(args: argparse.Namespace) -> None:
|
||||||
|
network_id = get_network_id()
|
||||||
|
networks = ZEROTIER_STATE_DIR / "controller.d" / "network" / network_id / "member"
|
||||||
|
if not networks.exists():
|
||||||
|
return
|
||||||
|
for member in networks.iterdir():
|
||||||
|
with member.open() as f:
|
||||||
|
data = json.load(f)
|
||||||
|
try:
|
||||||
|
member_id = data["id"]
|
||||||
|
except KeyError:
|
||||||
|
raise ClanError(f"error: {member} does not contain an id")
|
||||||
|
print(member_id)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
subparser = parser.add_subparsers(dest="command")
|
||||||
|
parser_allow = subparser.add_parser("allow", help="Allow a member to join")
|
||||||
|
parser_allow.add_argument("member_id")
|
||||||
|
parser_allow.set_defaults(func=allow_member)
|
||||||
|
|
||||||
|
parser_list = subparser.add_parser("list", help="List members")
|
||||||
|
parser_list.set_defaults(func=list_members)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
try:
|
||||||
|
args.func(args)
|
||||||
|
except ClanError as e:
|
||||||
|
print(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user