From 365977b018bfbc4f6f06dc99cffe970650984c76 Mon Sep 17 00:00:00 2001 From: msterhuj Date: Tue, 10 Dec 2024 00:15:03 +0100 Subject: [PATCH 1/5] fix: device list with new api version --- labctl/commands/devices.py | 54 +++++++++++++++----------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/labctl/commands/devices.py b/labctl/commands/devices.py index 850059a..963553c 100644 --- a/labctl/commands/devices.py +++ b/labctl/commands/devices.py @@ -18,54 +18,42 @@ def list_devices(): config = Config() devices = APIDriver().get("/devices/" + config.username).json() table = Table(title=":computer: Devices") - table.add_column("ID", style="cyan") - table.add_column("Name", style="magenta") + table.add_column("ID", style="bold") + table.add_column("Name", style="cyan") + table.add_column("GivenName", style="magenta") table.add_column("IPv4", style="green") - table.add_column("RX Bytes", style="blue") - table.add_column("TX Bytes", style="yellow") - table.add_column("Remote IP", style="red") + table.add_column("Created At", style="blue") + table.add_column("Expires At", style="red") + table.add_column("Last Seen", style="yellow") + table.add_column("Online", style="green") for device in devices: table.add_row( device["id"], device["name"], - device["ipv4"], - device["rx_bytes"], - device["tx_bytes"], - device["remote_ip"], + device["givenName"], + ", ".join(device["ipAddresses"]), + device["createdAt"], + device["expiry"], + device["lastSeen"], + "Yes" if device["online"] else "No", ) console.print(table) @app.command(name="create") @cli_ready -def create_device(name: str = typer.Argument(..., help="The device name")): +def enroll(name: str = typer.Argument(..., help="The device name")): """ - Create a device + Self enroll device to vpn """ - rsp = APIDriver().post( - f"/devices/{Config().username}", - json={"name": name}, - additional_headers={"Content-Type": "application/json"} - ) - if rsp.status_code >= 200 < 300: - console.print(f"Device {name} created :tada:") - data = rsp.json() - config_path = f"/{getcwd()}/{name}.conf" - wireguard.generate_config(data["device"], data["private_key"], config_path) - console.print(f"Configuration file saved to {config_path}") - return - console.print(f"Error creating device {name} ({rsp.status_code})") + # Todo: Check if tailscale cli is installed and Create preauth key with api and call tailscale cli to enroll device + ... @app.command(name="delete") @cli_ready -def delete_device( - device_id: str = typer.Argument(..., help="The device ID") -): +def quit(): """ - Delete a device + Self logout or logout specified device """ - rsp = APIDriver().delete(f"/devices/{Config().username}/{device_id}") - if rsp.status_code == 200: - console.print(f"Device {device_id} deleted :fire:") - return - console.print(f"Error deleting device {device_id} ({rsp.status_code})") + # Todo : Check if tailscale cli is installed logout user shutdown tailscale and call api to delete device if asked + ... \ No newline at end of file From a9158c011ee42332a9030d107c1876c62cb58aa4 Mon Sep 17 00:00:00 2001 From: msterhuj Date: Fri, 13 Dec 2024 22:46:10 +0100 Subject: [PATCH 2/5] break: remove old wireguard feat --- labctl/commands/devices.py | 2 +- labctl/core/__init__.py | 1 - labctl/core/wireguard.py | 16 ---------------- labctl/main.py | 2 -- 4 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 labctl/core/wireguard.py diff --git a/labctl/commands/devices.py b/labctl/commands/devices.py index 963553c..14a3b3f 100644 --- a/labctl/commands/devices.py +++ b/labctl/commands/devices.py @@ -56,4 +56,4 @@ def quit(): Self logout or logout specified device """ # Todo : Check if tailscale cli is installed logout user shutdown tailscale and call api to delete device if asked - ... \ No newline at end of file + config = Config() \ No newline at end of file diff --git a/labctl/core/__init__.py b/labctl/core/__init__.py index 8c8ebf3..1e347fd 100644 --- a/labctl/core/__init__.py +++ b/labctl/core/__init__.py @@ -2,4 +2,3 @@ from .api import APIDriver from .console import console from .decorators import cli_ready -from . import wireguard diff --git a/labctl/core/wireguard.py b/labctl/core/wireguard.py deleted file mode 100644 index 6bab3e5..0000000 --- a/labctl/core/wireguard.py +++ /dev/null @@ -1,16 +0,0 @@ -import wgconfig - -def generate_config(device: dict, private_key: str, config_file: str): - wg = wgconfig.WGConfig(config_file) - wg.add_attr(None, "PrivateKey", private_key) - wg.add_attr(None, "Address", f"{device['ipv4']}/32, {device['ipv6']}/128") - wg.add_attr(None, "DNS", ", ".join(device["dns"])) - wg.add_attr(None, "MTU", device["mtu"]) - - wg.add_peer(device["server_public_key"], "# LaboInfra WireGuard Server Client") - wg.add_attr(device["server_public_key"], "Endpoint", device["endpoint"]) - wg.add_attr(device["server_public_key"], "AllowedIPs", ", ".join(device["allowed_ips"])) - wg.add_attr(device["server_public_key"], "PersistentKeepalive", device["persistent_keepalive"]) - wg.add_attr(device["server_public_key"], "PresharedKey", device["preshared_key"]) - - wg.write_file() diff --git a/labctl/main.py b/labctl/main.py index 874c446..4ef7aa6 100644 --- a/labctl/main.py +++ b/labctl/main.py @@ -1,9 +1,7 @@ -from typing import Annotated from time import sleep from os import environ from json import dumps -import requests import typer from rich.tree import Tree From 1c1b46e0267d9924692718c4962ca3a956bc3714 Mon Sep 17 00:00:00 2001 From: msterhuj Date: Fri, 13 Dec 2024 22:46:38 +0100 Subject: [PATCH 3/5] feat: add delete and logout to devices commands --- labctl/commands/devices.py | 48 +++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/labctl/commands/devices.py b/labctl/commands/devices.py index 14a3b3f..cf04e7c 100644 --- a/labctl/commands/devices.py +++ b/labctl/commands/devices.py @@ -1,14 +1,20 @@ +from datetime import datetime from os import getcwd +from shutil import which +from subprocess import run, PIPE import typer from rich.table import Table from labctl.core import Config, APIDriver, console -from labctl.core import cli_ready, wireguard +from labctl.core import cli_ready app = typer.Typer() +def parse_datetime(date_str: str) -> str: + return datetime.fromisoformat(date_str.replace("Z", "+00:00")).strftime("%Y-%m-%d %H:%M:%S") + @app.command(name="list") @cli_ready def list_devices(): @@ -20,7 +26,6 @@ def list_devices(): table = Table(title=":computer: Devices") table.add_column("ID", style="bold") table.add_column("Name", style="cyan") - table.add_column("GivenName", style="magenta") table.add_column("IPv4", style="green") table.add_column("Created At", style="blue") table.add_column("Expires At", style="red") @@ -30,12 +35,11 @@ def list_devices(): for device in devices: table.add_row( device["id"], - device["name"], device["givenName"], ", ".join(device["ipAddresses"]), - device["createdAt"], - device["expiry"], - device["lastSeen"], + parse_datetime(device["createdAt"]), + (device["expiry"] if device["expiry"] != "0001-01-01T00:00:00Z" else "Never"), + parse_datetime(device["lastSeen"]), "Yes" if device["online"] else "No", ) console.print(table) @@ -49,11 +53,39 @@ def enroll(name: str = typer.Argument(..., help="The device name")): # Todo: Check if tailscale cli is installed and Create preauth key with api and call tailscale cli to enroll device ... +@app.command(name="logout") +def logout(): + """ + Self logout + """ + bin = which("tailscale") + if not bin: + console.print("[red]TailScale cli not found in path please install it[/red]") + return + print("Running tailscale down...") + print("Output: " + run([bin, "down"], stdout=PIPE).stdout.decode()) + print("Running tailscale logout...") + print("Output: " + run([bin, "logout"], stdout=PIPE).stdout.decode()) + + @app.command(name="delete") @cli_ready -def quit(): +def delete( + name: str = typer.Argument(None, help="The device name (found on the list command)"), +): """ Self logout or logout specified device """ # Todo : Check if tailscale cli is installed logout user shutdown tailscale and call api to delete device if asked - config = Config() \ No newline at end of file + config = Config() + api_driver = APIDriver() + + # delete http://localhost:8000/devices/admin/localhost-6uxdpldr + status = api_driver.delete(f"/devices/{config.username}/{name}").json() + + # rsp "success": true, "msg": "Device deleted" } + if status.get("success"): + console.print(f"Device {name} has ben removed from the vpn server :fire:") + else: + console.print(f"Failed to remove device {name}") + console.print(f"Reason given by the server : {status.get("msg")}") From 39b83c1607d133481d6b4528d0cd123d6b371284 Mon Sep 17 00:00:00 2001 From: msterhuj Date: Fri, 13 Dec 2024 23:13:26 +0100 Subject: [PATCH 4/5] feat: add easy self enroll --- labctl/commands/devices.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/labctl/commands/devices.py b/labctl/commands/devices.py index cf04e7c..b319622 100644 --- a/labctl/commands/devices.py +++ b/labctl/commands/devices.py @@ -44,14 +44,25 @@ def list_devices(): ) console.print(table) -@app.command(name="create") +@app.command(name="enroll") @cli_ready def enroll(name: str = typer.Argument(..., help="The device name")): """ Self enroll device to vpn """ # Todo: Check if tailscale cli is installed and Create preauth key with api and call tailscale cli to enroll device - ... + bin = which("tailscale") + if not bin: + console.print("[red]TailScale cli not found in path please install it[/red]") + return + config = Config() + api_driver = APIDriver() + key_rsp = api_driver.get(f"/devices/{config.username}/preauthkey") + key = key_rsp.json().get("key") + print("Running tailscale login...") + cmd = [bin, "login", "--login-server", "https://gw.laboinfra.net", "--auth-key", key, "--accept-routes", "true", "--hostname", name] + print("Execeuting: " + " ".join(cmd)) + print("Output: " + run(cmd, stdout=PIPE).stdout.decode()) @app.command(name="logout") def logout(): From 97f3305bc92620587277ece6b9735c482d2e3310 Mon Sep 17 00:00:00 2001 From: msterhuj Date: Wed, 8 Jan 2025 14:09:47 +0100 Subject: [PATCH 5/5] fix: auto login server commands Signed-off-by: msterhuj --- labctl/commands/devices.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/labctl/commands/devices.py b/labctl/commands/devices.py index b319622..2bc023e 100644 --- a/labctl/commands/devices.py +++ b/labctl/commands/devices.py @@ -46,7 +46,7 @@ def list_devices(): @app.command(name="enroll") @cli_ready -def enroll(name: str = typer.Argument(..., help="The device name")): +def enroll(): """ Self enroll device to vpn """ @@ -60,7 +60,7 @@ def enroll(name: str = typer.Argument(..., help="The device name")): key_rsp = api_driver.get(f"/devices/{config.username}/preauthkey") key = key_rsp.json().get("key") print("Running tailscale login...") - cmd = [bin, "login", "--login-server", "https://gw.laboinfra.net", "--auth-key", key, "--accept-routes", "true", "--hostname", name] + cmd = [bin, "login", "--login-server", "https://gw.laboinfra.net", "--auth-key", key, "--accept-routes", "true"] print("Execeuting: " + " ".join(cmd)) print("Output: " + run(cmd, stdout=PIPE).stdout.decode())