Created
July 26, 2020 18:01
-
-
Save jmuchovej/d5827467ab025b7a2accdf3ab516a3e8 to your computer and use it in GitHub Desktop.
Query ZeroTier is a script that accesses the ZeroTier API to determine network peers of a given network, then updates /etc/hosts to allow for human-like name access.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Query ZeroTier is a script that accesses the ZeroTier API to determine network peers | |
of a given network, then updates /etc/hosts to allow for human-like name access. | |
(c) Copyright 2020 John Muchovej | |
""" | |
#!/usr/bin/env python | |
import os | |
import sys | |
import json | |
import requests | |
from jinja2 import Template | |
from word2number import w2n | |
assert sys.version_info.major == 3 and sys.version_info.minor >= 6, \ | |
"Please use Python 3.6+ to run this script." | |
def get(postfix: str, token: str): | |
ZT = "https://my.zerotier.com/api" | |
headers = { | |
"Authorization": f"bearer {token}", | |
} | |
try: | |
response = requests.get(f"{ZT}/{postfix}", headers=headers) | |
response.raise_for_status() | |
except requests.execptions.HTTPError as e: | |
raise SystemExit(e) | |
return json.loads(response.content.decode("utf-8")) | |
def get_network(name: str): | |
networks = get("network") | |
for network in networks: | |
if network["config"]["name"] == name: | |
return network | |
raise ValueError(f"Could not find `{name}` in available networks.") | |
def get_clients(network: dict): | |
zt_id = network["config"]["id"] | |
members = get(f"network/{zt_id}/member") | |
host = Template("{{ ip }} {{ name }}") | |
hosts = [] | |
for member in members: | |
name = member["name"] | |
for ip in member["config"]["ipAssignments"]: | |
ip = f"{ip:15s}" | |
hosts.append(host.render(ip=ip, name=abbr(name))) | |
return hosts | |
def write(ZTHosts: list): | |
header = "# ZeroTier Clients" | |
footer = "# /ZeroTier Clients" | |
ZTHosts = [header] + ZTHosts + [footer] | |
hosts = open("/etc/hosts", "r").read().split("\n") | |
try: | |
start = hosts.index(header) | |
except ValueError: | |
start = len(hosts) | |
try: | |
end = hosts.index(footer) | |
except ValueError: | |
hosts.extend([""] * len(ZTHosts)) | |
for line, host in enumerate(ZTHosts, start): | |
hosts[line] = host | |
return "\n".join(hosts) | |
def abbr(hostname: str): | |
split = hostname.split("-") | |
alias = "" | |
for s in split: | |
try: | |
alias += str(w2n.word_to_num(s)) | |
except ValueError: | |
alias += s[0] | |
return f"{hostname} {alias}" | |
if __name__ == "__main__": | |
from argparse import ArgumentParser | |
parser = ArgumentParser("query-zerotier-update-hosts") | |
parser.add_argument("network", type=str) | |
parser.add_argument("token", type=str, required=False) | |
args = parser.parse_args() | |
if args.token: | |
token = args.token | |
else: | |
token = os.environ["ZT_TOKEN"] | |
targets = get_network(args.network) | |
clients = get_clients(targets) | |
new_etc = write(clients) | |
# write ZeroTier hosts to /etc/hosts, requires `sudo` | |
open("/etc/hosts", "w").write(new_etc) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Using requirements.txt strictly for those who fancy `pip`. Would recommend using Anaconda. | |
python >= 3.6 | |
requests | |
word2number >= 1.1 | |
Jinja2 >= 2.11 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment