Skip to content

Instantly share code, notes, and snippets.

@jmuchovej
Created July 26, 2020 18:01
Show Gist options
  • Save jmuchovej/d5827467ab025b7a2accdf3ab516a3e8 to your computer and use it in GitHub Desktop.
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.
"""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)
# 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