make a useful cli
This commit is contained in:
parent
291a287141
commit
dfb2b9d956
|
@ -1,5 +1,7 @@
|
|||
import asyncio
|
||||
import binascii
|
||||
from typing import Optional
|
||||
import secrets
|
||||
from typing import Optional, Any
|
||||
|
||||
from pyroute2 import IPRoute, WireGuard
|
||||
|
||||
|
@ -9,9 +11,28 @@ from .database import Database, Node, SERVER_NODE_ID
|
|||
|
||||
IFNAME = 'leyline-wg'
|
||||
DEFAULT_PORT = 31337
|
||||
API_PORT = 31338
|
||||
db = Database("leylines.db")
|
||||
|
||||
|
||||
async def client_connected(reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> None:
|
||||
try:
|
||||
while True:
|
||||
line = reader.readline()
|
||||
if line.strip() != db.get_token():
|
||||
raise Exception("unauthorized")
|
||||
# TODO
|
||||
finally:
|
||||
writer.close()
|
||||
await writer.wait_closed()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
sync_interface()
|
||||
server = await asyncio.create_server(client_connected, host="127.0.0.1", port=API_PORT)
|
||||
await server.serve_forever()
|
||||
|
||||
|
||||
def net_init() -> None:
|
||||
with open("/proc/sys/net/ipv4/ip_forward", "w") as f:
|
||||
f.write("1")
|
||||
|
@ -62,6 +83,7 @@ def add_node_to_wg(wg: WireGuard, node: Node) -> None:
|
|||
|
||||
|
||||
def create_or_get_interface() -> int:
|
||||
net_init()
|
||||
with IPRoute() as ipr:
|
||||
lookup = ipr.link_lookup(ifname=IFNAME)
|
||||
if len(lookup) > 0:
|
||||
|
|
|
@ -1,5 +1,65 @@
|
|||
from leylines import net_init, create_or_get_interface, sync_interface
|
||||
import argparse
|
||||
import ipaddress
|
||||
|
||||
net_init()
|
||||
create_or_get_interface()
|
||||
from leylines import main, db, sync_interface, seckey_to_pubkey, generate_node_config
|
||||
from leylines.database import SERVER_NODE_ID
|
||||
|
||||
|
||||
def nop():
|
||||
# needed because setup.py is weird
|
||||
pass
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="wireguard management system for dragons")
|
||||
cmd = parser.add_subparsers(dest="cmd")
|
||||
cmd.required = True
|
||||
|
||||
cmd_daemon = cmd.add_parser("daemon")
|
||||
|
||||
cmd_status = cmd.add_parser("status")
|
||||
|
||||
cmd_init = cmd.add_parser("init")
|
||||
cmd_init.add_argument("-n", "--name", type=str, help="Name of the server node", required=True)
|
||||
cmd_init.add_argument("-i", "--ip", type=str, help="Public IP of the server node", required=True)
|
||||
|
||||
cmd_add = cmd.add_parser("add")
|
||||
cmd_add.add_argument("-n", "--name", type=str, help="Name of the node to add", required=True)
|
||||
cmd_add.add_argument("-i", "--ip", type=str, help="Public IP of the node, if any", required=False)
|
||||
cmd_add.add_argument("-k", "--ssh-key", type=argparse.FileType("r"),
|
||||
help="SSH private keyfile for the node, if any", required=False)
|
||||
|
||||
cmd_get_conf = cmd.add_parser("get-conf")
|
||||
cmd_get_conf.add_argument("id", type=int, help="Node ID")
|
||||
|
||||
cmd_sync = cmd.add_parser("sync")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.cmd == "daemon":
|
||||
asyncio.run(main())
|
||||
elif args.cmd == "status":
|
||||
token = db.get_token()
|
||||
subnet = db.get_subnet()
|
||||
nodes = db.get_nodes()
|
||||
server_node = db.get_server_node()
|
||||
print("TOKEN:", token)
|
||||
print("SUBNET:", subnet)
|
||||
if server_node is None:
|
||||
print("SERVER: <not defined. run leylines init>")
|
||||
else:
|
||||
print("SERVER:", server_node.name, server_node.ip, server_node.public_ip,
|
||||
seckey_to_pubkey(server_node.seckey))
|
||||
for node in nodes:
|
||||
if node.id == SERVER_NODE_ID:
|
||||
continue
|
||||
print(f"NODE {node.id}:", node.name, node.public_ip, node.ip,
|
||||
seckey_to_pubkey(node.seckey), "<Have SSH Key>" if node.ssh_key is not None else "")
|
||||
elif args.cmd == "init":
|
||||
db.init_server(args.name, ipaddress.IPv4Address(args.ip))
|
||||
elif args.cmd == "add":
|
||||
db.add_node(args.name, args.ip, args.ssh_key.read() if args.ssh_key is not None else None)
|
||||
sync_interface()
|
||||
elif args.cmd == "get-conf":
|
||||
print(generate_node_config(args.id))
|
||||
elif args.cmd == "sync":
|
||||
sync_interface()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import binascii
|
||||
import ipaddress
|
||||
import secrets
|
||||
import sqlite3
|
||||
from typing import Iterable, List, NamedTuple, Optional, Set
|
||||
|
||||
|
@ -38,6 +39,9 @@ class Database:
|
|||
"CREATE TABLE IF NOT EXISTS settings (name TEXT PRIMARY KEY, value TEXT NOT NULL)")
|
||||
self.conn.execute(
|
||||
"INSERT OR IGNORE INTO settings (name, value) VALUES ('subnet', ?)", (DEFAULT_SUBNET,))
|
||||
self.conn.execute(
|
||||
"INSERT OR IGNORE INTO settings (name, value) VALUES ('token', ?)",
|
||||
(secrets.token_hex(32),))
|
||||
|
||||
self.conn.commit()
|
||||
|
||||
|
@ -51,6 +55,11 @@ class Database:
|
|||
cur.execute("SELECT value FROM settings WHERE name='subnet'")
|
||||
return ipaddress.IPv4Interface(cur.fetchone()[0])
|
||||
|
||||
def get_token(self) -> str:
|
||||
cur = self.conn.cursor()
|
||||
cur.execute("SELECT value FROM settings WHERE name='token'")
|
||||
return cur.fetchone()[0]
|
||||
|
||||
def _get_free_ip(self) -> ipaddress.IPv4Address:
|
||||
subnet = self.get_subnet().network
|
||||
subnets = [self.get_subnet().network]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from setuptools import setup
|
||||
|
||||
setup(name='leylines',
|
||||
setup(
|
||||
name='leylines',
|
||||
version='0.1',
|
||||
description='Sample text',
|
||||
url='https://awoo.systems',
|
||||
|
@ -9,12 +10,13 @@ setup(name='leylines',
|
|||
license='AGPLv3',
|
||||
packages=['leylines'],
|
||||
install_requires=[
|
||||
# requirements
|
||||
"leylines-monocypher",
|
||||
"pyroute2"
|
||||
],
|
||||
include_package_data=True,
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
# bins
|
||||
"leylines=leylines.__main__:nop"
|
||||
]
|
||||
},
|
||||
zip_safe=True)
|
||||
|
|
Loading…
Reference in New Issue