From 3808720800143da49ce2dc34c65579bffa954f0c Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 20:15:44 +0900 Subject: [PATCH 01/33] Testing logging --- headscale.py | 137 +++++++++++++++++++++++++++------------------------ helper.py | 11 +++-- server.py | 8 +-- 3 files changed, 86 insertions(+), 70 deletions(-) diff --git a/headscale.py b/headscale.py index ced2821..9503862 100644 --- a/headscale.py +++ b/headscale.py @@ -7,8 +7,8 @@ from flask import Flask from flask.logging import create_logger -app = Flask(__name__) -LOG = create_logger(app) +app = Flask(__name__) +LOG = create_logger(app) ################################################################## # Functions related to HEADSCALE and API KEYS @@ -38,7 +38,7 @@ def get_api_key(): enc_api_key = key_file.read() if enc_api_key == b'': return "NULL" -# Preparing the Fernet class with the key + # Preparing the Fernet class with the key fernet = Fernet(encryption_key) # Decrypting the key decrypted_key = fernet.decrypt(enc_api_key).decode() @@ -59,7 +59,7 @@ def test_api_key(url, api_key): def expire_key(url, api_key): payload = {'prefix':str(api_key[0:10])} json_payload=json.dumps(payload) -# app.logger.warning("Sending the payload '"+str(json_payload)+"' to the headscale server") + LOG.debug("Sending the payload '"+str(json_payload)+"' to the headscale server") response = requests.post( str(url)+"/api/v1/apikey/expire", @@ -78,8 +78,7 @@ def renew_api_key(url, api_key): # 0 = Key has been updated or key is not in need of an update # 1 = Key has failed validity check or has failed to write the API key # Check when the key expires and compare it to todays date: - key_info = get_api_key_info(url, api_key) - + key_info = get_api_key_info(url, api_key) expiration_time = key_info["expiration"] today_date = date.today() expire = parser.parse(expiration_time) @@ -91,10 +90,10 @@ def renew_api_key(url, api_key): # If the delta is less than 5 days, renew the key: if delta < timedelta(days=5): -# app.logger.warning("Key is about to expire. Delta is "+str(delta)) + LOG.warning("Key is about to expire. Delta is "+str(delta)) payload = {'expiration':str(new_expiration_date)} json_payload=json.dumps(payload) -# app.logger.warning("Sending the payload '"+str(json_payload)+"' to the headscale server") + LOG.debug("Sending the payload '"+str(json_payload)+"' to the headscale server") response = requests.post( str(url)+"/api/v1/apikey", @@ -106,24 +105,27 @@ def renew_api_key(url, api_key): } ) new_key = response.json() -# app.logger.warning("JSON: "+json.dumps(new_key)) -# app.logger.warning("New Key is: "+new_key["apiKey"]) + LOG.debug("JSON: "+json.dumps(new_key)) + LOG.debug("New Key is: "+new_key["apiKey"]) api_key_test = test_api_key(url, new_key["apiKey"]) -# app.logger.warning("Testing the key: "+str(api_key_test)) + LOG.debug("Testing the key: "+str(api_key_test)) # Test if the new key works: if api_key_test == 200: -# app.logger.warning("The new key is valid and we are writing it to the file") + LOG.info("The new key is valid and we are writing it to the file") if not set_api_key(new_key["apiKey"]): -# app.logger.warning("We failed writing the new key!") + LOG.error("We failed writing the new key!") return False # Key write failed -# app.logger.warning("Key validated and written. Moving to expire the key.") + LOG.info("Key validated and written. Moving to expire the key.") expire_key(url, api_key) return True # Key updated and validated - else: return False # The API Key test failed - else: return True #No work is required + else: + LOG.error("Testing the API key failed.") + return False # The API Key test failed + else: return True # No work is required # Gets information about the current API key def get_api_key_info(url, api_key): + LOG.info("Getting API key information") response = requests.get( str(url)+"/api/v1/apikey", headers={ @@ -134,9 +136,12 @@ def get_api_key_info(url, api_key): json_response = response.json() # Find the current key in the array: key_prefix = str(api_key[0:10]) + LOG.info("Looking for valid API Key...") for key in json_response["apiKeys"]: if key_prefix == key["prefix"]: + LOG.info("Key found.") return key + LOG.error("Could not find a valid key in Headscale. Need a new API key.") return "Key not found" ################################################################## @@ -145,6 +150,7 @@ def get_api_key_info(url, api_key): # register a new machine def register_machine(url, api_key, machine_key, user): + LOG.info("Registering machine %s to user %s", str(machine_key), str(user)) response = requests.post( str(url)+"/api/v1/machine/register?user="+str(user)+"&key="+str(machine_key), headers={ @@ -157,6 +163,7 @@ def register_machine(url, api_key, machine_key, user): # Sets the machines tags def set_machine_tags(url, api_key, machine_id, tags_list): + LOG.info("Setting machine_id %s tag %s", str(machine_id), str(tags_list)) response = requests.post( str(url)+"/api/v1/machine/"+str(machine_id)+"/tags", data=tags_list, @@ -170,6 +177,7 @@ def set_machine_tags(url, api_key, machine_id, tags_list): # Moves machine_id to user "new_user" def move_user(url, api_key, machine_id, new_user): + LOG.info("Moving machine_id %s to user %s", str(machine_id), str(new_user)) response = requests.post( str(url)+"/api/v1/machine/"+str(machine_id)+"/user?user="+str(new_user), headers={ @@ -179,30 +187,17 @@ def move_user(url, api_key, machine_id, new_user): ) return response.json() -# updates routes for the given machine_id. enable / disable -# The Headscale API expects a list of routes to enable. -# if we want to toggle 1 out of 3 routes -# we need to pass all currently enabled routes and mask it -# For example, if we have routes: -# 0.0.0.0/0 -# ::/0 -# 192.168.1.0/24 -# available, but only routes -# 0.0.0.0/24 -# 192.168.1.0/24 -# ENABLED, and we want to disable route 192.168.1.0/24, -# we need to pass ONLY the routes to KEEP enabled. -# In this case, 0.0.0/24 def update_route(url, api_key, route_id, current_state): action = "" if current_state == "True": action = "disable" if current_state == "False": action = "enable" + LOG.info("Updating Route %s: Action: %s", str(route_id), str(action)) # Debug - # LOG.info("URL: "+str(url)) - # LOG.info("Route ID: "+str(route_id)) - # LOG.info("Current State: "+str(current_state)) - # LOG.info("Action to take: "+str(action)) + LOG.debug("URL: "+str(url)) + LOG.debug("Route ID: "+str(route_id)) + LOG.debug("Current State: "+str(current_state)) + LOG.debug("Action to take: "+str(action)) response = requests.post( str(url)+"/api/v1/routes/"+str(route_id)+"/"+str(action), @@ -212,37 +207,10 @@ def update_route(url, api_key, route_id, current_state): } ) return response.json() - # First, get all route info: -# routes = get_machine_routes(url, api_key, machine_id) -# to_enable = [] -# is_enabled = False - # "route" is what we are toggling. On or off. - # Get a list of all currently enabled routes. - # If route IS currently in enabled routes, remove it -# # DONE: REDO THIS FOR THE NEW API -# for enabled_route in routes["routes"]["enabledRoutes"]: -# if enabled_route == route: is_enabled=True -# else: to_enable.append(enabled_route) -# if not is_enabled: to_enable.append(route) -# -# query = "" -# count = 0 -# for route in to_enable: -# count = count+1 -# if count == 1: query = query+"routes="+route -# else: query = query+"&routes="+route -# -# response = requests.post( -# str(url)+"/api/v1/machine/"+str(machine_id)+"/routes?"+query, -# headers={ -# 'Accept': 'application/json', -# 'Authorization': 'Bearer '+str(api_key) -# } -# ) -# return response.json() # Get all machines on the Headscale network def get_machines(url, api_key): + LOG.info("Getting machine information") response = requests.get( str(url)+"/api/v1/machine", headers={ @@ -254,6 +222,7 @@ def get_machines(url, api_key): # Get machine with "machine_id" on the Headscale network def get_machine_info(url, api_key, machine_id): + LOG.info("Getting information for machine ID %s", str(machine_id)) response = requests.get( str(url)+"/api/v1/machine/"+str(machine_id), headers={ @@ -265,6 +234,7 @@ def get_machine_info(url, api_key, machine_id): # Delete a machine from Headscale def delete_machine(url, api_key, machine_id): + LOG.info("Deleting machine %s", str(machine_id)) response = requests.delete( str(url)+"/api/v1/machine/"+str(machine_id), headers={ @@ -273,10 +243,15 @@ def delete_machine(url, api_key, machine_id): } ) status = "True" if response.status_code == 200 else "False" + if response.status_code == 200: + LOG.info("Machine deleted.") + else: + LOG.error("Deleting machine failed! %s", str(response.json())) return {"status": status, "body": response.json()} # Rename "machine_id" with name "new_name" def rename_machine(url, api_key, machine_id, new_name): + LOG.info("Renaming machine %s", str(machine_id)) response = requests.post( str(url)+"/api/v1/machine/"+str(machine_id)+"/rename/"+str(new_name), headers={ @@ -285,10 +260,15 @@ def rename_machine(url, api_key, machine_id, new_name): } ) status = "True" if response.status_code == 200 else "False" + if response.status_code == 200: + LOG.info("Machine renamed") + else: + LOG.error("Machine rename failed! %s", str(response.json())) return {"status": status, "body": response.json()} # Gets routes for the passed machine_id def get_machine_routes(url, api_key, machine_id): + LOG.info("Renaming machine %s", str(machine_id)) response = requests.get( str(url)+"/api/v1/machine/"+str(machine_id)+"/routes", headers={ @@ -296,9 +276,15 @@ def get_machine_routes(url, api_key, machine_id): 'Authorization': 'Bearer '+str(api_key) } ) + if response.status_code == 200: + LOG.info("Routes obtained") + else: + LOG.error("Failed to get routes: %s", str(response.json())) return response.json() + # Gets routes for the entire tailnet def get_routes(url, api_key): + LOG.info("Getting routes") response = requests.get( str(url)+"/api/v1/routes", headers={ @@ -314,6 +300,7 @@ def get_routes(url, api_key): # Get all users in use def get_users(url, api_key): + LOG.info("Getting Users") response = requests.get( str(url)+"/api/v1/user", headers={ @@ -325,6 +312,7 @@ def get_users(url, api_key): # Rename "old_name" with name "new_name" def rename_user(url, api_key, old_name, new_name): + LOG.info("Renaming user %s to %s.", str(old_name), str(new_name)) response = requests.post( str(url)+"/api/v1/user/"+str(old_name)+"/rename/"+str(new_name), headers={ @@ -333,10 +321,15 @@ def rename_user(url, api_key, old_name, new_name): } ) status = "True" if response.status_code == 200 else "False" + if response.status_code == 200: + LOG.info("User renamed.") + else: + LOG.error("Renaming User failed!") return {"status": status, "body": response.json()} # Delete a user from Headscale def delete_user(url, api_key, user_name): + LOG.info("Deleting a User: %s", str(user_name)) response = requests.delete( str(url)+"/api/v1/user/"+str(user_name), headers={ @@ -345,10 +338,15 @@ def delete_user(url, api_key, user_name): } ) status = "True" if response.status_code == 200 else "False" + if response.status_code == 200: + LOG.info("User deleted.") + else: + LOG.error("Deleting User failed!") return {"status": status, "body": response.json()} # Add a user from Headscale def add_user(url, api_key, data): + LOG.info("Adding user: %s", str(data)) response = requests.post( str(url)+"/api/v1/user", data=data, @@ -359,6 +357,10 @@ def add_user(url, api_key, data): } ) status = "True" if response.status_code == 200 else "False" + if response.status_code == 200: + LOG.info("User added.") + else: + LOG.error("Adding User failed!") return {"status": status, "body": response.json()} ################################################################## @@ -367,6 +369,7 @@ def add_user(url, api_key, data): # Get all PreAuth keys associated with a user "user_name" def get_preauth_keys(url, api_key, user_name): + LOG.info("Getting PreAuth Keys in User %s", str(user_name)) response = requests.get( str(url)+"/api/v1/preauthkey?user="+str(user_name), headers={ @@ -379,6 +382,7 @@ def get_preauth_keys(url, api_key, user_name): # Add a preauth key to the user "user_name" given the booleans "ephemeral" # and "reusable" with the expiration date "date" contained in the JSON payload "data" def add_preauth_key(url, api_key, data): + LOG.info("Adding PreAuth Key: %s", str(data)) response = requests.post( str(url)+"/api/v1/preauthkey", data=data, @@ -389,10 +393,15 @@ def add_preauth_key(url, api_key, data): } ) status = "True" if response.status_code == 200 else "False" + if response.status_code == 200: + LOG.info("PreAuth Key added.") + else: + LOG.error("Adding PreAuth Key failed!") return {"status": status, "body": response.json()} # Expire a pre-auth key. data is {"user": "string", "key": "string"} def expire_preauth_key(url, api_key, data): + LOG.info("Expiring PreAuth Key...") response = requests.post( str(url)+"/api/v1/preauthkey/expire", data=data, @@ -403,6 +412,6 @@ def expire_preauth_key(url, api_key, data): } ) status = "True" if response.status_code == 200 else "False" - ## LOG.info("expire_preauth_key - Return: "+str(response.json())) - ## LOG.info("expire_preauth_key - Status: "+str(status)) + LOG.debug("expire_preauth_key - Return: "+str(response.json())) + LOG.debug("expire_preauth_key - Status: "+str(status)) return {"status": status, "body": response.json()} diff --git a/helper.py b/helper.py index c2bbc36..9be70fc 100644 --- a/helper.py +++ b/helper.py @@ -4,8 +4,8 @@ from flask import Flask from flask.logging import create_logger -app = Flask(__name__) -LOG = create_logger(app) +app = Flask(__name__) +LOG = create_logger(app) def pretty_print_duration(duration, delta_type=""): """ Prints a duration in human-readable formats """ @@ -26,6 +26,7 @@ def pretty_print_duration(duration, delta_type=""): if hours > 0 : return str(hours) + " hours ago" if hours > 1 else str(hours) + " hour ago" if mins > 0 : return str(mins ) + " minutes ago" if mins > 1 else str(mins ) + " minute ago" return str(secs ) + " seconds ago" if secs >= 1 or secs == 0 else str(secs ) + " second ago" + def text_color_duration(duration): """ Prints a color based on duratioin (imported as seconds) """ @@ -52,9 +53,13 @@ def key_check(): # Test the API key. If the test fails, return a failure. # AKA, if headscale returns Unauthorized, fail: + LOG.info("Testing API key validity.") status = headscale.test_api_key(url, api_key) - if status != 200: return False + if status != 200: + LOG.info("Got a non-200 response from Headscale. Test failed (Response: %i)", status) + return False else: + LOG.info("Key check passed.") # Check if the key needs to be renewed headscale.renew_api_key(url, api_key) return True diff --git a/server.py b/server.py index 411e942..d4a7fa8 100644 --- a/server.py +++ b/server.py @@ -15,10 +15,12 @@ COLOR_BTN = COLOR+" darken-3" DEBUG_STATE = True AUTH_TYPE = os.environ["AUTH_TYPE"].replace('"', '').lower() +LOG_LEVEL = os.environ["LOG_LEVEL"].replace('"', '').upper() -# Initiate the Flask application: +# Initiate the Flask application and logging: app = Flask(__name__, static_url_path="/static") LOG = logging.create_logger(app) +getattr(logging, LOG_LEVEL) executor = Executor(app) app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) @@ -31,7 +33,7 @@ # https://gist.github.com/thomasdarimont/145dc9aa857b831ff2eff221b79d179a/ # https://www.authelia.com/integration/openid-connect/introduction/ # https://github.com/steinarvk/flask_oidc_demo - LOG.error("Loading OIDC libraries and configuring app...") + LOG.info("Loading OIDC libraries and configuring app...") DOMAIN_NAME = os.environ["DOMAIN_NAME"] BASE_PATH = os.environ["SCRIPT_NAME"] if os.environ["SCRIPT_NAME"] != "/" else "" @@ -84,7 +86,7 @@ elif AUTH_TYPE == "basic": # https://flask-basicauth.readthedocs.io/en/latest/ - LOG.error("Loading basic auth libraries and configuring app...") + LOG.info("Loading basic auth libraries and configuring app...") from flask_basicauth import BasicAuth app.config['BASIC_AUTH_USERNAME'] = os.environ["BASIC_AUTH_USER"].replace('"', '') From 43f03961ef04c2866c81fd20a614fdf1d2fcd564 Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 20:44:48 +0900 Subject: [PATCH 02/33] Add a default log level --- Dockerfile | 1 + SETUP.md | 1 + docker-compose.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/Dockerfile b/Dockerfile index aaadd04..c1a54b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,6 +38,7 @@ ENV KEY="" ENV SCRIPT_NAME=/ ENV DOMAIN_NAME=http://localhost ENV AUTH_TYPE="" +ENV LOG_LEVEL="Info" # BasicAuth variables ENV BASIC_AUTH_USER="" diff --git a/SETUP.md b/SETUP.md index a1049d6..84c7bab 100644 --- a/SETUP.md +++ b/SETUP.md @@ -20,6 +20,7 @@ * `SCRIPT_NAME` is your "Base Path" for hosting. For example, if you want to host on http://localhost/admin, set this to `/admin` * `KEY` is your encryption key. Set this to a random value generated from `openssl rand -base64 32` * `AUTH_TYPE` can be set to `Basic` or `OIDC`. See the [Authentication](#Authentication) section below for more information. + * `LOG_LEVEL` can be one of `Debug`, `Info`, `Warning`, or `Error` for decreasing verbosity. --- # Reverse Proxies *If your reverse proxy isn't listed or doesn't work, please open up a [new issue](https://github.com/iFargle/headscale-webui/issues/new) and it will be worked on.* diff --git a/docker-compose.yml b/docker-compose.yml index 525d3ca..d8fbe78 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,7 @@ services: - SCRIPT_NAME=/admin # This is your applications base path (wsgi requires the name "SCRIPT_NAME") - KEY="YourKeyBetweenQuotes" # Generate with "openssl rand -base64 32" - used to encrypt your key on disk. - AUTH_TYPE=oidc # AUTH_TYPE is either Basic or OIDC. Empty for no authentication + - LOG_LEVEL=info # Log level. "DEBUG", "ERROR", "WARNING", or "INFO". Default "INFO" # ENV for Basic Auth (Used only if AUTH_TYPE is "Basic"). Can be omitted if you aren't using Basic Auth - BASIC_AUTH_USER=user # Used for basic auth - BASIC_AUTH_PASS=pass # Used for basic auth From bc5835aff35e991ffd759f4dbf1db77c04cf3ae4 Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 20:50:14 +0900 Subject: [PATCH 03/33] Set logging --- server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.py b/server.py index d4a7fa8..e53e665 100644 --- a/server.py +++ b/server.py @@ -19,8 +19,8 @@ # Initiate the Flask application and logging: app = Flask(__name__, static_url_path="/static") +logging.basicConfig(level=logging.LOG_LEVEL) LOG = logging.create_logger(app) -getattr(logging, LOG_LEVEL) executor = Executor(app) app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) From 89ca696a1e744e54def73b578c02897b1dac985b Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 20:53:51 +0900 Subject: [PATCH 04/33] Test log level --- server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server.py b/server.py index e53e665..4e1ca7d 100644 --- a/server.py +++ b/server.py @@ -13,14 +13,14 @@ COLOR = os.environ["COLOR"].replace('"', '').lower() COLOR_NAV = COLOR+" darken-1" COLOR_BTN = COLOR+" darken-3" -DEBUG_STATE = True +DEBUG_STATE = False AUTH_TYPE = os.environ["AUTH_TYPE"].replace('"', '').lower() LOG_LEVEL = os.environ["LOG_LEVEL"].replace('"', '').upper() # Initiate the Flask application and logging: app = Flask(__name__, static_url_path="/static") -logging.basicConfig(level=logging.LOG_LEVEL) LOG = logging.create_logger(app) +LOG.setLevel(logging.LOG_LEVEL) executor = Executor(app) app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) From e70559396a5ee292db8042a71beeb23d70e346ee Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 21:07:04 +0900 Subject: [PATCH 05/33] More logging --- server.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/server.py b/server.py index 4e1ca7d..56d99aa 100644 --- a/server.py +++ b/server.py @@ -7,6 +7,7 @@ from dateutil import parser from flask_executor import Executor from werkzeug.middleware.proxy_fix import ProxyFix +from logging.config import dictConfig # Global vars # Colors: https://materializecss.com/color.html @@ -18,9 +19,25 @@ LOG_LEVEL = os.environ["LOG_LEVEL"].replace('"', '').upper() # Initiate the Flask application and logging: +dictConfig({ + 'version': 1, + 'formatters': {'default': { + 'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s', + }}, + 'handlers': {'wsgi': { + 'class': 'logging.StreamHandler', + 'stream': 'ext://flask.logging.wsgi_errors_stream', + 'formatter': 'default' + }}, + 'root': { + 'level': LOG_LEVEL, + 'handlers': ['wsgi'] + } +}) + app = Flask(__name__, static_url_path="/static") LOG = logging.create_logger(app) -LOG.setLevel(logging.LOG_LEVEL) +LOG.setLevel(LOG_LEVEL) executor = Executor(app) app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) From aea36e358bab3f09f399f6f9945397e40d73a98c Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 21:15:58 +0900 Subject: [PATCH 06/33] Testing more logging --- headscale.py | 7 +++---- helper.py | 7 +++---- renderer.py | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/headscale.py b/headscale.py index 9503862..cf5b161 100644 --- a/headscale.py +++ b/headscale.py @@ -1,14 +1,13 @@ # pylint: disable=wrong-import-order -import requests, json, os +import requests, json, os, logging from cryptography.fernet import Fernet from datetime import timedelta, date from dateutil import parser from flask import Flask -from flask.logging import create_logger -app = Flask(__name__) -LOG = create_logger(app) +app = Flask(__name__) +LOG = logging.getLogger(app) ################################################################## # Functions related to HEADSCALE and API KEYS diff --git a/helper.py b/helper.py index 9be70fc..d7e3204 100644 --- a/helper.py +++ b/helper.py @@ -1,11 +1,10 @@ # pylint: disable=wrong-import-order -import os, headscale, requests +import os, headscale, requests, logging from flask import Flask -from flask.logging import create_logger -app = Flask(__name__) -LOG = create_logger(app) +app = Flask(__name__) +LOG = logging.getLogger(app) def pretty_print_duration(duration, delta_type=""): """ Prints a duration in human-readable formats """ diff --git a/renderer.py b/renderer.py index 13a419d..7eec59d 100644 --- a/renderer.py +++ b/renderer.py @@ -1,6 +1,6 @@ # pylint: disable=line-too-long, wrong-import-order -import headscale, helper, pytz, os, yaml +import headscale, helper, pytz, os, yaml, logging from flask import Markup, render_template, Flask, logging from datetime import datetime from dateutil import parser @@ -8,7 +8,7 @@ from flask_executor import Executor app = Flask(__name__) -LOG = logging.create_logger(app) +LOG = logging.getLogger(app) executor = Executor(app) def render_overview(): From 9d01a0526349a6081b19537b03c8014dadb662f1 Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 21:19:12 +0900 Subject: [PATCH 07/33] Test --- headscale.py | 2 +- helper.py | 2 +- renderer.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/headscale.py b/headscale.py index cf5b161..f9de822 100644 --- a/headscale.py +++ b/headscale.py @@ -7,7 +7,7 @@ from flask import Flask app = Flask(__name__) -LOG = logging.getLogger(app) +LOG = logging.getLogger(__name__) ################################################################## # Functions related to HEADSCALE and API KEYS diff --git a/helper.py b/helper.py index d7e3204..00ece3f 100644 --- a/helper.py +++ b/helper.py @@ -4,7 +4,7 @@ from flask import Flask app = Flask(__name__) -LOG = logging.getLogger(app) +LOG = logging.getLogger(__name__) def pretty_print_duration(duration, delta_type=""): """ Prints a duration in human-readable formats """ diff --git a/renderer.py b/renderer.py index 7eec59d..d282ee9 100644 --- a/renderer.py +++ b/renderer.py @@ -8,7 +8,7 @@ from flask_executor import Executor app = Flask(__name__) -LOG = logging.getLogger(app) +LOG = logging.getLogger(__name__) executor = Executor(app) def render_overview(): From b90266afd6537950371e4444ff2048e4401f8c75 Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 21:19:25 +0900 Subject: [PATCH 08/33] test --- renderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderer.py b/renderer.py index d282ee9..9c163d9 100644 --- a/renderer.py +++ b/renderer.py @@ -1,7 +1,7 @@ # pylint: disable=line-too-long, wrong-import-order import headscale, helper, pytz, os, yaml, logging -from flask import Markup, render_template, Flask, logging +from flask import Markup, render_template, Flask from datetime import datetime from dateutil import parser from concurrent.futures import ALL_COMPLETED, wait From be78e2bfdf04bd15fa2d12548e14b9c733798009 Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 21:24:37 +0900 Subject: [PATCH 09/33] test --- headscale.py | 2 +- helper.py | 4 ++-- renderer.py | 2 +- server.py | 3 +-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/headscale.py b/headscale.py index f9de822..40842c8 100644 --- a/headscale.py +++ b/headscale.py @@ -7,7 +7,7 @@ from flask import Flask app = Flask(__name__) -LOG = logging.getLogger(__name__) +LOG = logging.getLogger("app") ################################################################## # Functions related to HEADSCALE and API KEYS diff --git a/helper.py b/helper.py index 00ece3f..8fe8f77 100644 --- a/helper.py +++ b/helper.py @@ -1,10 +1,10 @@ # pylint: disable=wrong-import-order import os, headscale, requests, logging -from flask import Flask +from flask import Flask app = Flask(__name__) -LOG = logging.getLogger(__name__) +LOG = logging.getLogger("app") def pretty_print_duration(duration, delta_type=""): """ Prints a duration in human-readable formats """ diff --git a/renderer.py b/renderer.py index 9c163d9..fc09998 100644 --- a/renderer.py +++ b/renderer.py @@ -8,7 +8,7 @@ from flask_executor import Executor app = Flask(__name__) -LOG = logging.getLogger(__name__) +LOG = logging.getLogger("app") executor = Executor(app) def render_overview(): diff --git a/server.py b/server.py index 56d99aa..846c45f 100644 --- a/server.py +++ b/server.py @@ -35,9 +35,8 @@ } }) -app = Flask(__name__, static_url_path="/static") +app = Flask("app", static_url_path="/static") LOG = logging.create_logger(app) -LOG.setLevel(LOG_LEVEL) executor = Executor(app) app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) From 3db9ed86359258172daaafdb4c7ec66b82dff5fb Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 21:33:06 +0900 Subject: [PATCH 10/33] Test --- headscale.py | 6 +++--- helper.py | 6 +++--- renderer.py | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/headscale.py b/headscale.py index 40842c8..585edf5 100644 --- a/headscale.py +++ b/headscale.py @@ -1,13 +1,13 @@ # pylint: disable=wrong-import-order -import requests, json, os, logging +import requests, json, os from cryptography.fernet import Fernet from datetime import timedelta, date from dateutil import parser -from flask import Flask +from flask import Flask, current_app app = Flask(__name__) -LOG = logging.getLogger("app") +LOG = current_app.logger ################################################################## # Functions related to HEADSCALE and API KEYS diff --git a/helper.py b/helper.py index 8fe8f77..78abbe1 100644 --- a/helper.py +++ b/helper.py @@ -1,10 +1,10 @@ # pylint: disable=wrong-import-order -import os, headscale, requests, logging -from flask import Flask +import os, headscale, requests +from flask import Flask, current_app app = Flask(__name__) -LOG = logging.getLogger("app") +LOG = current_app.logger def pretty_print_duration(duration, delta_type=""): """ Prints a duration in human-readable formats """ diff --git a/renderer.py b/renderer.py index fc09998..eedc6b1 100644 --- a/renderer.py +++ b/renderer.py @@ -1,14 +1,14 @@ # pylint: disable=line-too-long, wrong-import-order -import headscale, helper, pytz, os, yaml, logging -from flask import Markup, render_template, Flask +import headscale, helper, pytz, os, yaml +from flask import Markup, render_template, Flask, current_app from datetime import datetime from dateutil import parser from concurrent.futures import ALL_COMPLETED, wait from flask_executor import Executor app = Flask(__name__) -LOG = logging.getLogger("app") +LOG = current_app.logger executor = Executor(app) def render_overview(): From 5fb273835b4fd83ac0d6c840f987477f3cff90b4 Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 21:41:57 +0900 Subject: [PATCH 11/33] test --- server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.py b/server.py index 846c45f..5e6e276 100644 --- a/server.py +++ b/server.py @@ -3,7 +3,7 @@ import headscale, helper, json, os, pytz, renderer, secrets, requests from functools import wraps from datetime import datetime -from flask import Flask, Markup, redirect, render_template, request, url_for, logging +from flask import Flask, Markup, redirect, render_templaterequest, url_for, logging, current_app from dateutil import parser from flask_executor import Executor from werkzeug.middleware.proxy_fix import ProxyFix From b3fac98c1ccd34bdd69867a47443892e4c2a6e1a Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 21:54:36 +0900 Subject: [PATCH 12/33] test --- headscale.py | 4 ++-- helper.py | 4 ++-- renderer.py | 4 ++-- server.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/headscale.py b/headscale.py index 585edf5..631a6d5 100644 --- a/headscale.py +++ b/headscale.py @@ -4,10 +4,10 @@ from cryptography.fernet import Fernet from datetime import timedelta, date from dateutil import parser -from flask import Flask, current_app +from flask import Flask, logging app = Flask(__name__) -LOG = current_app.logger +LOG = logging.create_logger(app) ################################################################## # Functions related to HEADSCALE and API KEYS diff --git a/helper.py b/helper.py index 78abbe1..f209d32 100644 --- a/helper.py +++ b/helper.py @@ -1,10 +1,10 @@ # pylint: disable=wrong-import-order import os, headscale, requests -from flask import Flask, current_app +from flask import Flask, logging app = Flask(__name__) -LOG = current_app.logger +LOG = logging.create_logger(app) def pretty_print_duration(duration, delta_type=""): """ Prints a duration in human-readable formats """ diff --git a/renderer.py b/renderer.py index eedc6b1..13a419d 100644 --- a/renderer.py +++ b/renderer.py @@ -1,14 +1,14 @@ # pylint: disable=line-too-long, wrong-import-order import headscale, helper, pytz, os, yaml -from flask import Markup, render_template, Flask, current_app +from flask import Markup, render_template, Flask, logging from datetime import datetime from dateutil import parser from concurrent.futures import ALL_COMPLETED, wait from flask_executor import Executor app = Flask(__name__) -LOG = current_app.logger +LOG = logging.create_logger(app) executor = Executor(app) def render_overview(): diff --git a/server.py b/server.py index 5e6e276..beeddad 100644 --- a/server.py +++ b/server.py @@ -3,7 +3,7 @@ import headscale, helper, json, os, pytz, renderer, secrets, requests from functools import wraps from datetime import datetime -from flask import Flask, Markup, redirect, render_templaterequest, url_for, logging, current_app +from flask import Flask, Markup, redirect, render_template, request, url_for, logging from dateutil import parser from flask_executor import Executor from werkzeug.middleware.proxy_fix import ProxyFix @@ -30,7 +30,7 @@ 'formatter': 'default' }}, 'root': { - 'level': LOG_LEVEL, + 'level': 'INFO', 'handlers': ['wsgi'] } }) From 3833a3388560bcf2aa3fc8c38409a3c5f4079c32 Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 22:03:04 +0900 Subject: [PATCH 13/33] test --- headscale.py | 4 ++-- helper.py | 4 ++-- renderer.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/headscale.py b/headscale.py index 631a6d5..0067ca4 100644 --- a/headscale.py +++ b/headscale.py @@ -1,12 +1,12 @@ # pylint: disable=wrong-import-order import requests, json, os +from server import app from cryptography.fernet import Fernet from datetime import timedelta, date from dateutil import parser -from flask import Flask, logging +from flask import logging -app = Flask(__name__) LOG = logging.create_logger(app) ################################################################## diff --git a/helper.py b/helper.py index f209d32..322949f 100644 --- a/helper.py +++ b/helper.py @@ -1,9 +1,9 @@ # pylint: disable=wrong-import-order import os, headscale, requests -from flask import Flask, logging +from server import app +from flask import logging -app = Flask(__name__) LOG = logging.create_logger(app) def pretty_print_duration(duration, delta_type=""): diff --git a/renderer.py b/renderer.py index 13a419d..078856a 100644 --- a/renderer.py +++ b/renderer.py @@ -1,13 +1,13 @@ # pylint: disable=line-too-long, wrong-import-order import headscale, helper, pytz, os, yaml -from flask import Markup, render_template, Flask, logging +from server import app +from flask import Markup, render_template, logging from datetime import datetime from dateutil import parser from concurrent.futures import ALL_COMPLETED, wait from flask_executor import Executor -app = Flask(__name__) LOG = logging.create_logger(app) executor = Executor(app) From bdbb85bcb9a255310fa4cb13e6750c2a1fb5da6f Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 22:21:51 +0900 Subject: [PATCH 14/33] Test --- headscale.py | 8 ++++---- helper.py | 8 ++++---- renderer.py | 8 ++++---- server.py | 10 +++++----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/headscale.py b/headscale.py index 0067ca4..88cc136 100644 --- a/headscale.py +++ b/headscale.py @@ -1,13 +1,13 @@ # pylint: disable=wrong-import-order -import requests, json, os -from server import app +import requests, json, os, logger from cryptography.fernet import Fernet from datetime import timedelta, date from dateutil import parser -from flask import logging +from flask import Flask -LOG = logging.create_logger(app) +app = Flask(__name__, static_url_path="/static") +LOG = app.logger() ################################################################## # Functions related to HEADSCALE and API KEYS diff --git a/helper.py b/helper.py index 322949f..c5a4765 100644 --- a/helper.py +++ b/helper.py @@ -1,10 +1,10 @@ # pylint: disable=wrong-import-order -import os, headscale, requests -from server import app -from flask import logging +import os, headscale, requests, logger +from flask import Flask -LOG = logging.create_logger(app) +app = Flask(__name__, static_url_path="/static") +LOG = app.logger() def pretty_print_duration(duration, delta_type=""): """ Prints a duration in human-readable formats """ diff --git a/renderer.py b/renderer.py index 078856a..5b9b79a 100644 --- a/renderer.py +++ b/renderer.py @@ -1,14 +1,14 @@ # pylint: disable=line-too-long, wrong-import-order -import headscale, helper, pytz, os, yaml -from server import app -from flask import Markup, render_template, logging +import headscale, helper, pytz, os, yaml, logger +from flask import Flask, Markup, render_template from datetime import datetime from dateutil import parser from concurrent.futures import ALL_COMPLETED, wait from flask_executor import Executor -LOG = logging.create_logger(app) +app = Flask(__name__, static_url_path="/static") +LOG = app.logger() executor = Executor(app) def render_overview(): diff --git a/server.py b/server.py index beeddad..f571aa7 100644 --- a/server.py +++ b/server.py @@ -1,9 +1,9 @@ # pylint: disable=wrong-import-order -import headscale, helper, json, os, pytz, renderer, secrets, requests +import headscale, helper, json, os, pytz, renderer, secrets, requests, logger from functools import wraps from datetime import datetime -from flask import Flask, Markup, redirect, render_template, request, url_for, logging +from flask import Flask, Markup, redirect, render_template, request, url_for from dateutil import parser from flask_executor import Executor from werkzeug.middleware.proxy_fix import ProxyFix @@ -30,13 +30,13 @@ 'formatter': 'default' }}, 'root': { - 'level': 'INFO', + 'level': LOG_LEVEL, 'handlers': ['wsgi'] } }) -app = Flask("app", static_url_path="/static") -LOG = logging.create_logger(app) +app = Flask(__name__, static_url_path="/static") +LOG = app.logger() executor = Executor(app) app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) From 88afde359af4bb3eb0985e14d4650c8f2a32dbd2 Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 22:45:12 +0900 Subject: [PATCH 15/33] test --- headscale.py | 107 +++++++++++++++++++++++++-------------------------- helper.py | 43 ++++++++++----------- renderer.py | 17 ++++---- server.py | 23 ++++++----- 4 files changed, 93 insertions(+), 97 deletions(-) diff --git a/headscale.py b/headscale.py index 88cc136..c6e63ea 100644 --- a/headscale.py +++ b/headscale.py @@ -1,13 +1,12 @@ # pylint: disable=wrong-import-order -import requests, json, os, logger +import requests, json, os from cryptography.fernet import Fernet from datetime import timedelta, date from dateutil import parser -from flask import Flask +from flask import Flask, logging app = Flask(__name__, static_url_path="/static") -LOG = app.logger() ################################################################## # Functions related to HEADSCALE and API KEYS @@ -58,7 +57,7 @@ def test_api_key(url, api_key): def expire_key(url, api_key): payload = {'prefix':str(api_key[0:10])} json_payload=json.dumps(payload) - LOG.debug("Sending the payload '"+str(json_payload)+"' to the headscale server") + app.logger.debug("Sending the payload '"+str(json_payload)+"' to the headscale server") response = requests.post( str(url)+"/api/v1/apikey/expire", @@ -89,10 +88,10 @@ def renew_api_key(url, api_key): # If the delta is less than 5 days, renew the key: if delta < timedelta(days=5): - LOG.warning("Key is about to expire. Delta is "+str(delta)) + app.logger.warning("Key is about to expire. Delta is "+str(delta)) payload = {'expiration':str(new_expiration_date)} json_payload=json.dumps(payload) - LOG.debug("Sending the payload '"+str(json_payload)+"' to the headscale server") + app.logger.debug("Sending the payload '"+str(json_payload)+"' to the headscale server") response = requests.post( str(url)+"/api/v1/apikey", @@ -104,27 +103,27 @@ def renew_api_key(url, api_key): } ) new_key = response.json() - LOG.debug("JSON: "+json.dumps(new_key)) - LOG.debug("New Key is: "+new_key["apiKey"]) + app.logger.debug("JSON: "+json.dumps(new_key)) + app.logger.debug("New Key is: "+new_key["apiKey"]) api_key_test = test_api_key(url, new_key["apiKey"]) - LOG.debug("Testing the key: "+str(api_key_test)) + app.logger.debug("Testing the key: "+str(api_key_test)) # Test if the new key works: if api_key_test == 200: - LOG.info("The new key is valid and we are writing it to the file") + app.logger.info("The new key is valid and we are writing it to the file") if not set_api_key(new_key["apiKey"]): - LOG.error("We failed writing the new key!") + app.logger.error("We failed writing the new key!") return False # Key write failed - LOG.info("Key validated and written. Moving to expire the key.") + app.logger.info("Key validated and written. Moving to expire the key.") expire_key(url, api_key) return True # Key updated and validated else: - LOG.error("Testing the API key failed.") + app.logger.error("Testing the API key failed.") return False # The API Key test failed else: return True # No work is required # Gets information about the current API key def get_api_key_info(url, api_key): - LOG.info("Getting API key information") + app.logger.info("Getting API key information") response = requests.get( str(url)+"/api/v1/apikey", headers={ @@ -135,12 +134,12 @@ def get_api_key_info(url, api_key): json_response = response.json() # Find the current key in the array: key_prefix = str(api_key[0:10]) - LOG.info("Looking for valid API Key...") + app.logger.info("Looking for valid API Key...") for key in json_response["apiKeys"]: if key_prefix == key["prefix"]: - LOG.info("Key found.") + app.logger.info("Key found.") return key - LOG.error("Could not find a valid key in Headscale. Need a new API key.") + app.logger.error("Could not find a valid key in Headscale. Need a new API key.") return "Key not found" ################################################################## @@ -149,7 +148,7 @@ def get_api_key_info(url, api_key): # register a new machine def register_machine(url, api_key, machine_key, user): - LOG.info("Registering machine %s to user %s", str(machine_key), str(user)) + app.logger.info("Registering machine %s to user %s", str(machine_key), str(user)) response = requests.post( str(url)+"/api/v1/machine/register?user="+str(user)+"&key="+str(machine_key), headers={ @@ -162,7 +161,7 @@ def register_machine(url, api_key, machine_key, user): # Sets the machines tags def set_machine_tags(url, api_key, machine_id, tags_list): - LOG.info("Setting machine_id %s tag %s", str(machine_id), str(tags_list)) + app.logger.info("Setting machine_id %s tag %s", str(machine_id), str(tags_list)) response = requests.post( str(url)+"/api/v1/machine/"+str(machine_id)+"/tags", data=tags_list, @@ -176,7 +175,7 @@ def set_machine_tags(url, api_key, machine_id, tags_list): # Moves machine_id to user "new_user" def move_user(url, api_key, machine_id, new_user): - LOG.info("Moving machine_id %s to user %s", str(machine_id), str(new_user)) + app.logger.info("Moving machine_id %s to user %s", str(machine_id), str(new_user)) response = requests.post( str(url)+"/api/v1/machine/"+str(machine_id)+"/user?user="+str(new_user), headers={ @@ -190,13 +189,13 @@ def update_route(url, api_key, route_id, current_state): action = "" if current_state == "True": action = "disable" if current_state == "False": action = "enable" - LOG.info("Updating Route %s: Action: %s", str(route_id), str(action)) + app.logger.info("Updating Route %s: Action: %s", str(route_id), str(action)) # Debug - LOG.debug("URL: "+str(url)) - LOG.debug("Route ID: "+str(route_id)) - LOG.debug("Current State: "+str(current_state)) - LOG.debug("Action to take: "+str(action)) + app.logger.debug("URL: "+str(url)) + app.logger.debug("Route ID: "+str(route_id)) + app.logger.debug("Current State: "+str(current_state)) + app.logger.debug("Action to take: "+str(action)) response = requests.post( str(url)+"/api/v1/routes/"+str(route_id)+"/"+str(action), @@ -209,7 +208,7 @@ def update_route(url, api_key, route_id, current_state): # Get all machines on the Headscale network def get_machines(url, api_key): - LOG.info("Getting machine information") + app.logger.info("Getting machine information") response = requests.get( str(url)+"/api/v1/machine", headers={ @@ -221,7 +220,7 @@ def get_machines(url, api_key): # Get machine with "machine_id" on the Headscale network def get_machine_info(url, api_key, machine_id): - LOG.info("Getting information for machine ID %s", str(machine_id)) + app.logger.info("Getting information for machine ID %s", str(machine_id)) response = requests.get( str(url)+"/api/v1/machine/"+str(machine_id), headers={ @@ -233,7 +232,7 @@ def get_machine_info(url, api_key, machine_id): # Delete a machine from Headscale def delete_machine(url, api_key, machine_id): - LOG.info("Deleting machine %s", str(machine_id)) + app.logger.info("Deleting machine %s", str(machine_id)) response = requests.delete( str(url)+"/api/v1/machine/"+str(machine_id), headers={ @@ -243,14 +242,14 @@ def delete_machine(url, api_key, machine_id): ) status = "True" if response.status_code == 200 else "False" if response.status_code == 200: - LOG.info("Machine deleted.") + app.logger.info("Machine deleted.") else: - LOG.error("Deleting machine failed! %s", str(response.json())) + app.logger.error("Deleting machine failed! %s", str(response.json())) return {"status": status, "body": response.json()} # Rename "machine_id" with name "new_name" def rename_machine(url, api_key, machine_id, new_name): - LOG.info("Renaming machine %s", str(machine_id)) + app.logger.info("Renaming machine %s", str(machine_id)) response = requests.post( str(url)+"/api/v1/machine/"+str(machine_id)+"/rename/"+str(new_name), headers={ @@ -260,14 +259,14 @@ def rename_machine(url, api_key, machine_id, new_name): ) status = "True" if response.status_code == 200 else "False" if response.status_code == 200: - LOG.info("Machine renamed") + app.logger.info("Machine renamed") else: - LOG.error("Machine rename failed! %s", str(response.json())) + app.logger.error("Machine rename failed! %s", str(response.json())) return {"status": status, "body": response.json()} # Gets routes for the passed machine_id def get_machine_routes(url, api_key, machine_id): - LOG.info("Renaming machine %s", str(machine_id)) + app.logger.info("Renaming machine %s", str(machine_id)) response = requests.get( str(url)+"/api/v1/machine/"+str(machine_id)+"/routes", headers={ @@ -276,14 +275,14 @@ def get_machine_routes(url, api_key, machine_id): } ) if response.status_code == 200: - LOG.info("Routes obtained") + app.logger.info("Routes obtained") else: - LOG.error("Failed to get routes: %s", str(response.json())) + app.logger.error("Failed to get routes: %s", str(response.json())) return response.json() # Gets routes for the entire tailnet def get_routes(url, api_key): - LOG.info("Getting routes") + app.logger.info("Getting routes") response = requests.get( str(url)+"/api/v1/routes", headers={ @@ -299,7 +298,7 @@ def get_routes(url, api_key): # Get all users in use def get_users(url, api_key): - LOG.info("Getting Users") + app.logger.info("Getting Users") response = requests.get( str(url)+"/api/v1/user", headers={ @@ -311,7 +310,7 @@ def get_users(url, api_key): # Rename "old_name" with name "new_name" def rename_user(url, api_key, old_name, new_name): - LOG.info("Renaming user %s to %s.", str(old_name), str(new_name)) + app.logger.info("Renaming user %s to %s.", str(old_name), str(new_name)) response = requests.post( str(url)+"/api/v1/user/"+str(old_name)+"/rename/"+str(new_name), headers={ @@ -321,14 +320,14 @@ def rename_user(url, api_key, old_name, new_name): ) status = "True" if response.status_code == 200 else "False" if response.status_code == 200: - LOG.info("User renamed.") + app.logger.info("User renamed.") else: - LOG.error("Renaming User failed!") + app.logger.error("Renaming User failed!") return {"status": status, "body": response.json()} # Delete a user from Headscale def delete_user(url, api_key, user_name): - LOG.info("Deleting a User: %s", str(user_name)) + app.logger.info("Deleting a User: %s", str(user_name)) response = requests.delete( str(url)+"/api/v1/user/"+str(user_name), headers={ @@ -338,14 +337,14 @@ def delete_user(url, api_key, user_name): ) status = "True" if response.status_code == 200 else "False" if response.status_code == 200: - LOG.info("User deleted.") + app.logger.info("User deleted.") else: - LOG.error("Deleting User failed!") + app.logger.error("Deleting User failed!") return {"status": status, "body": response.json()} # Add a user from Headscale def add_user(url, api_key, data): - LOG.info("Adding user: %s", str(data)) + app.logger.info("Adding user: %s", str(data)) response = requests.post( str(url)+"/api/v1/user", data=data, @@ -357,9 +356,9 @@ def add_user(url, api_key, data): ) status = "True" if response.status_code == 200 else "False" if response.status_code == 200: - LOG.info("User added.") + app.logger.info("User added.") else: - LOG.error("Adding User failed!") + app.logger.error("Adding User failed!") return {"status": status, "body": response.json()} ################################################################## @@ -368,7 +367,7 @@ def add_user(url, api_key, data): # Get all PreAuth keys associated with a user "user_name" def get_preauth_keys(url, api_key, user_name): - LOG.info("Getting PreAuth Keys in User %s", str(user_name)) + app.logger.info("Getting PreAuth Keys in User %s", str(user_name)) response = requests.get( str(url)+"/api/v1/preauthkey?user="+str(user_name), headers={ @@ -381,7 +380,7 @@ def get_preauth_keys(url, api_key, user_name): # Add a preauth key to the user "user_name" given the booleans "ephemeral" # and "reusable" with the expiration date "date" contained in the JSON payload "data" def add_preauth_key(url, api_key, data): - LOG.info("Adding PreAuth Key: %s", str(data)) + app.logger.info("Adding PreAuth Key: %s", str(data)) response = requests.post( str(url)+"/api/v1/preauthkey", data=data, @@ -393,14 +392,14 @@ def add_preauth_key(url, api_key, data): ) status = "True" if response.status_code == 200 else "False" if response.status_code == 200: - LOG.info("PreAuth Key added.") + app.logger.info("PreAuth Key added.") else: - LOG.error("Adding PreAuth Key failed!") + app.logger.error("Adding PreAuth Key failed!") return {"status": status, "body": response.json()} # Expire a pre-auth key. data is {"user": "string", "key": "string"} def expire_preauth_key(url, api_key, data): - LOG.info("Expiring PreAuth Key...") + app.logger.info("Expiring PreAuth Key...") response = requests.post( str(url)+"/api/v1/preauthkey/expire", data=data, @@ -411,6 +410,6 @@ def expire_preauth_key(url, api_key, data): } ) status = "True" if response.status_code == 200 else "False" - LOG.debug("expire_preauth_key - Return: "+str(response.json())) - LOG.debug("expire_preauth_key - Status: "+str(status)) + app.logger.debug("expire_preauth_key - Return: "+str(response.json())) + app.logger.debug("expire_preauth_key - Status: "+str(status)) return {"status": status, "body": response.json()} diff --git a/helper.py b/helper.py index c5a4765..be660e9 100644 --- a/helper.py +++ b/helper.py @@ -1,10 +1,9 @@ # pylint: disable=wrong-import-order -import os, headscale, requests, logger -from flask import Flask +import os, headscale, requests +from flask import Flask, logging app = Flask(__name__, static_url_path="/static") -LOG = app.logger() def pretty_print_duration(duration, delta_type=""): """ Prints a duration in human-readable formats """ @@ -52,13 +51,13 @@ def key_check(): # Test the API key. If the test fails, return a failure. # AKA, if headscale returns Unauthorized, fail: - LOG.info("Testing API key validity.") + app.logger.info("Testing API key validity.") status = headscale.test_api_key(url, api_key) if status != 200: - LOG.info("Got a non-200 response from Headscale. Test failed (Response: %i)", status) + app.logger.info("Got a non-200 response from Headscale. Test failed (Response: %i)", status) return False else: - LOG.info("Key check passed.") + app.logger.info("Key check passed.") # Check if the key needs to be renewed headscale.renew_api_key(url, api_key) return True @@ -152,20 +151,20 @@ def access_checks(): server_reachable = True else: checks_passed = False - LOG.error("Headscale URL: Response 200: FAILED") + app.logger.error("Headscale URL: Response 200: FAILED") # Check: /data is rwx for 1000:1000: if os.access('/data/', os.R_OK): data_readable = True else: - LOG.error("/data READ: FAILED") + app.logger.error("/data READ: FAILED") checks_passed = False if os.access('/data/', os.W_OK): data_writable = True else: - LOG.error("/data WRITE: FAILED") + app.logger.error("/data WRITE: FAILED") checks_passed = False if os.access('/data/', os.X_OK): data_executable = True else: - LOG.error("/data EXEC: FAILED") + app.logger.error("/data EXEC: FAILED") checks_passed = False # Check: /data/key.txt exists and is rw: @@ -173,29 +172,29 @@ def access_checks(): file_exists = True if os.access('/data/key.txt', os.R_OK): file_readable = True else: - LOG.error("/data/key.txt READ: FAILED") + app.logger.error("/data/key.txt READ: FAILED") checks_passed = False if os.access('/data/key.txt', os.W_OK): file_writable = True else: - LOG.error("/data/key.txt WRITE: FAILED") + app.logger.error("/data/key.txt WRITE: FAILED") checks_passed = False - else: LOG.error("/data/key.txt EXIST: FAILED - NO ERROR") + else: app.logger.error("/data/key.txt EXIST: FAILED - NO ERROR") # Check: /etc/headscale/config.yaml is readable: if os.access('/etc/headscale/config.yaml', os.R_OK): config_readable = True elif os.access('/etc/headscale/config.yml', os.R_OK): config_readable = True else: - LOG.error("/etc/headscale/config.y(a)ml: READ: FAILED") + app.logger.error("/etc/headscale/config.y(a)ml: READ: FAILED") checks_passed = False if checks_passed: - LOG.error("All startup checks passed.") + app.logger.error("All startup checks passed.") return "Pass" message_html = "" # Generate the message: if not server_reachable: - LOG.error("Server is unreachable") + app.logger.error("Server is unreachable") message = """

Your headscale server is either unreachable or not properly configured. Please ensure your configuration is correct (Check for 200 status on @@ -205,7 +204,7 @@ def access_checks(): message_html += format_message("Error", "Headscale unreachable", message) if not config_readable: - LOG.error("Headscale configuration is not readable") + app.logger.error("Headscale configuration is not readable") message = """

/etc/headscale/config.yaml not readable. Please ensure your headscale configuration file resides in /etc/headscale and @@ -215,7 +214,7 @@ def access_checks(): message_html += format_message("Error", "/etc/headscale/config.yaml not readable", message) if not data_writable: - LOG.error("/data folder is not writable") + app.logger.error("/data folder is not writable") message = """

/data is not writable. Please ensure your permissions are correct. /data mount should be writable @@ -225,7 +224,7 @@ def access_checks(): message_html += format_message("Error", "/data not writable", message) if not data_readable: - LOG.error("/data folder is not readable") + app.logger.error("/data folder is not readable") message = """

/data is not readable. Please ensure your permissions are correct. /data mount should be readable @@ -235,7 +234,7 @@ def access_checks(): message_html += format_message("Error", "/data not readable", message) if not data_executable: - LOG.error("/data folder is not readable") + app.logger.error("/data folder is not readable") message = """

/data is not executable. Please ensure your permissions are correct. /data mount should be readable @@ -249,7 +248,7 @@ def access_checks(): # If it doesn't exist, we assume the user hasn't created it yet. # Just redirect to the settings page to enter an API Key if not file_writable: - LOG.error("/data/key.txt is not writable") + app.logger.error("/data/key.txt is not writable") message = """

/data/key.txt is not writable. Please ensure your permissions are correct. /data mount should be writable @@ -259,7 +258,7 @@ def access_checks(): message_html += format_message("Error", "/data/key.txt not writable", message) if not file_readable: - LOG.error("/data/key.txt is not readable") + app.logger.error("/data/key.txt is not readable") message = """

/data/key.txt is not readable. Please ensure your permissions are correct. /data mount should be readable diff --git a/renderer.py b/renderer.py index 5b9b79a..92ce1fd 100644 --- a/renderer.py +++ b/renderer.py @@ -1,14 +1,13 @@ # pylint: disable=line-too-long, wrong-import-order -import headscale, helper, pytz, os, yaml, logger -from flask import Flask, Markup, render_template +import headscale, helper, pytz, os, yaml +from flask import Flask, Markup, render_template, logging from datetime import datetime from dateutil import parser from concurrent.futures import ALL_COMPLETED, wait from flask_executor import Executor app = Flask(__name__, static_url_path="/static") -LOG = app.logger() executor = Executor(app) def render_overview(): @@ -245,7 +244,7 @@ def thread_machine_content(machine, machine_content, idx):

""" for route in pulled_routes["routes"]: - # LOG.warning("Route: ["+str(route['machine']['name'])+"] id: "+str(route['id'])+" / prefix: "+str(route['prefix'])+" enabled?: "+str(route['enabled'])) + app.logger.debug("Route: ["+str(route['machine']['name'])+"] id: "+str(route['id'])+" / prefix: "+str(route['prefix'])+" enabled?: "+str(route['enabled'])) # Check if the route is enabled: route_enabled = "red" route_tooltip = 'enable' @@ -325,7 +324,7 @@ def thread_machine_content(machine, machine_content, idx): expiry_time = str(expiry_local.strftime('%m/%Y'))+" "+str(timezone)+" ("+str(expiry_print)+")" else: expiry_time = str(expiry_local.strftime('%A %m/%d/%Y, %H:%M:%S'))+" "+str(timezone)+" ("+str(expiry_print)+")" - LOG.error("Machine: "+machine["name"]+" expires: "+str(expiry_local.strftime('%Y'))+" / "+str(expiry_delta.days)) + app.logger.debug("Machine: "+machine["name"]+" expires: "+str(expiry_local.strftime('%Y'))+" / "+str(expiry_delta.days)) expiring_soon = True if int(expiry_delta.days) < 14 and int(expiry_delta.days) > 0 else False # Get the first 10 characters of the PreAuth Key: @@ -367,7 +366,7 @@ def thread_machine_content(machine, machine_content, idx): expiration_badge = Markup(expiration_badge), machine_tags = Markup(tags), ))) - LOG.warning("Finished thread for machine "+machine["givenName"]+" index "+str(idx)) + app.logger.warning("Finished thread for machine "+machine["givenName"]+" index "+str(idx)) # Render the cards for the machines page: def render_machines_cards(): @@ -381,14 +380,14 @@ def render_machines_cards(): iterable = [] machine_content = {} for i in range (0, num_threads): - LOG.error("Appending iterable: "+str(i)) + app.logger.error("Appending iterable: "+str(i)) iterable.append(i) # Flask-Executor Method: - LOG.warning("Starting futures") + app.logger.warning("Starting futures") futures = [executor.submit(thread_machine_content, machines_list["machines"][idx], machine_content, idx) for idx in iterable] # Wait for the executor to finish all jobs: wait(futures, return_when=ALL_COMPLETED) - LOG.warning("Finished futures") + app.logger.warning("Finished futures") # DEBUG: Do in a forloop: # for idx in iterable: thread_machine_content(machines_list["machines"][idx], machine_content, idx) diff --git a/server.py b/server.py index f571aa7..ad8582b 100644 --- a/server.py +++ b/server.py @@ -1,9 +1,9 @@ # pylint: disable=wrong-import-order -import headscale, helper, json, os, pytz, renderer, secrets, requests, logger +import headscale, helper, json, os, pytz, renderer, secrets, requests from functools import wraps from datetime import datetime -from flask import Flask, Markup, redirect, render_template, request, url_for +from flask import Flask, Markup, redirect, render_template, request, url_for, logging from dateutil import parser from flask_executor import Executor from werkzeug.middleware.proxy_fix import ProxyFix @@ -36,7 +36,6 @@ }) app = Flask(__name__, static_url_path="/static") -LOG = app.logger() executor = Executor(app) app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) @@ -49,7 +48,7 @@ # https://gist.github.com/thomasdarimont/145dc9aa857b831ff2eff221b79d179a/ # https://www.authelia.com/integration/openid-connect/introduction/ # https://github.com/steinarvk/flask_oidc_demo - LOG.info("Loading OIDC libraries and configuring app...") + app.loggerinfo("Loading OIDC libraries and configuring app...") DOMAIN_NAME = os.environ["DOMAIN_NAME"] BASE_PATH = os.environ["SCRIPT_NAME"] if os.environ["SCRIPT_NAME"] != "/" else "" @@ -60,7 +59,7 @@ # Construct client_secrets.json: response = requests.get(str(OIDC_AUTH_URL)) oidc_info = response.json() - LOG.debug("JSON Dumps for OIDC_INFO: "+json.dumps(oidc_info)) + app.logger.debug("JSON Dumps for OIDC_INFO: "+json.dumps(oidc_info)) client_secrets = """{ "web": { @@ -80,10 +79,10 @@ with open("/app/instance/secrets.json", "w+") as secrets_json: secrets_json.write(client_secrets) - LOG.debug("Client Secrets: ") + app.logger.debug("Client Secrets: ") with open("/app/instance/secrets.json", "r+") as secrets_json: - LOG.debug("/app/instances/secrets.json:") - LOG.debug(secrets_json.read()) + app.logger.debug("/app/instances/secrets.json:") + app.logger.debug(secrets_json.read()) app.config.update({ 'SECRET_KEY': secrets.token_urlsafe(32), @@ -102,7 +101,7 @@ elif AUTH_TYPE == "basic": # https://flask-basicauth.readthedocs.io/en/latest/ - LOG.info("Loading basic auth libraries and configuring app...") + app.loggerinfo("Loading basic auth libraries and configuring app...") from flask_basicauth import BasicAuth app.config['BASIC_AUTH_USERNAME'] = os.environ["BASIC_AUTH_USER"].replace('"', '') @@ -289,9 +288,9 @@ def test_key_page(): if status != 200: return "Unauthenticated" renewed = headscale.renew_api_key(url, api_key) - LOG.warning("The below statement will be TRUE if the key has been renewed, ") - LOG.warning("or DOES NOT need renewal. False in all other cases") - LOG.warning("Renewed: "+str(renewed)) + app.loggerwarning("The below statement will be TRUE if the key has been renewed, ") + app.loggerwarning("or DOES NOT need renewal. False in all other cases") + app.loggerwarning("Renewed: "+str(renewed)) # The key works, let's renew it if it needs it. If it does, re-read the api_key from the file: if renewed: api_key = headscale.get_api_key() From 0fec4852af1a994fc0fcb02acb8bcd842b9c9b1f Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 22:49:34 +0900 Subject: [PATCH 16/33] test --- headscale.py | 2 +- helper.py | 2 +- renderer.py | 2 +- server.py | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/headscale.py b/headscale.py index c6e63ea..cb21a30 100644 --- a/headscale.py +++ b/headscale.py @@ -4,7 +4,7 @@ from cryptography.fernet import Fernet from datetime import timedelta, date from dateutil import parser -from flask import Flask, logging +from flask import Flask app = Flask(__name__, static_url_path="/static") diff --git a/helper.py b/helper.py index be660e9..d1c1129 100644 --- a/helper.py +++ b/helper.py @@ -1,7 +1,7 @@ # pylint: disable=wrong-import-order import os, headscale, requests -from flask import Flask, logging +from flask import Flask app = Flask(__name__, static_url_path="/static") diff --git a/renderer.py b/renderer.py index 92ce1fd..3153252 100644 --- a/renderer.py +++ b/renderer.py @@ -1,7 +1,7 @@ # pylint: disable=line-too-long, wrong-import-order import headscale, helper, pytz, os, yaml -from flask import Flask, Markup, render_template, logging +from flask import Flask, Markup, render_template from datetime import datetime from dateutil import parser from concurrent.futures import ALL_COMPLETED, wait diff --git a/server.py b/server.py index ad8582b..b183107 100644 --- a/server.py +++ b/server.py @@ -3,7 +3,7 @@ import headscale, helper, json, os, pytz, renderer, secrets, requests from functools import wraps from datetime import datetime -from flask import Flask, Markup, redirect, render_template, request, url_for, logging +from flask import Flask, Markup, redirect, render_template, request, url_for from dateutil import parser from flask_executor import Executor from werkzeug.middleware.proxy_fix import ProxyFix @@ -48,7 +48,7 @@ # https://gist.github.com/thomasdarimont/145dc9aa857b831ff2eff221b79d179a/ # https://www.authelia.com/integration/openid-connect/introduction/ # https://github.com/steinarvk/flask_oidc_demo - app.loggerinfo("Loading OIDC libraries and configuring app...") + app.logger.info("Loading OIDC libraries and configuring app...") DOMAIN_NAME = os.environ["DOMAIN_NAME"] BASE_PATH = os.environ["SCRIPT_NAME"] if os.environ["SCRIPT_NAME"] != "/" else "" @@ -101,7 +101,7 @@ elif AUTH_TYPE == "basic": # https://flask-basicauth.readthedocs.io/en/latest/ - app.loggerinfo("Loading basic auth libraries and configuring app...") + app.logger.info("Loading basic auth libraries and configuring app...") from flask_basicauth import BasicAuth app.config['BASIC_AUTH_USERNAME'] = os.environ["BASIC_AUTH_USER"].replace('"', '') From 169b5526398bcbbdfb23c3c0401fe8d7241c2aa6 Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 27 Feb 2023 22:57:38 +0900 Subject: [PATCH 17/33] In a working state now. --- headscale.py | 2 +- renderer.py | 8 ++++---- server.py | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/headscale.py b/headscale.py index cb21a30..31b2aaa 100644 --- a/headscale.py +++ b/headscale.py @@ -266,7 +266,7 @@ def rename_machine(url, api_key, machine_id, new_name): # Gets routes for the passed machine_id def get_machine_routes(url, api_key, machine_id): - app.logger.info("Renaming machine %s", str(machine_id)) + app.logger.info("Getting routes for machine %s", str(machine_id)) response = requests.get( str(url)+"/api/v1/machine/"+str(machine_id)+"/routes", headers={ diff --git a/renderer.py b/renderer.py index 3153252..462887d 100644 --- a/renderer.py +++ b/renderer.py @@ -366,7 +366,7 @@ def thread_machine_content(machine, machine_content, idx): expiration_badge = Markup(expiration_badge), machine_tags = Markup(tags), ))) - app.logger.warning("Finished thread for machine "+machine["givenName"]+" index "+str(idx)) + app.logger.info("Finished thread for machine "+machine["givenName"]+" index "+str(idx)) # Render the cards for the machines page: def render_machines_cards(): @@ -380,14 +380,14 @@ def render_machines_cards(): iterable = [] machine_content = {} for i in range (0, num_threads): - app.logger.error("Appending iterable: "+str(i)) + app.logger.debug("Appending iterable: "+str(i)) iterable.append(i) # Flask-Executor Method: - app.logger.warning("Starting futures") + app.logger.info("Starting futures") futures = [executor.submit(thread_machine_content, machines_list["machines"][idx], machine_content, idx) for idx in iterable] # Wait for the executor to finish all jobs: wait(futures, return_when=ALL_COMPLETED) - app.logger.warning("Finished futures") + app.logger.info("Finished futures") # DEBUG: Do in a forloop: # for idx in iterable: thread_machine_content(machines_list["machines"][idx], machine_content, idx) diff --git a/server.py b/server.py index b183107..674e17c 100644 --- a/server.py +++ b/server.py @@ -288,9 +288,9 @@ def test_key_page(): if status != 200: return "Unauthenticated" renewed = headscale.renew_api_key(url, api_key) - app.loggerwarning("The below statement will be TRUE if the key has been renewed, ") - app.loggerwarning("or DOES NOT need renewal. False in all other cases") - app.loggerwarning("Renewed: "+str(renewed)) + app.logger.warning("The below statement will be TRUE if the key has been renewed, ") + app.logger.warning("or DOES NOT need renewal. False in all other cases") + app.logger.warning("Renewed: "+str(renewed)) # The key works, let's renew it if it needs it. If it does, re-read the api_key from the file: if renewed: api_key = headscale.get_api_key() From 90e364d11d2163160318544ba47d54cefeca2cf2 Mon Sep 17 00:00:00 2001 From: iFargle Date: Tue, 28 Feb 2023 08:28:09 +0900 Subject: [PATCH 18/33] Trying create_logger --- headscale.py | 3 ++- helper.py | 3 ++- renderer.py | 3 ++- server.py | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/headscale.py b/headscale.py index 31b2aaa..7aa6ea0 100644 --- a/headscale.py +++ b/headscale.py @@ -4,9 +4,10 @@ from cryptography.fernet import Fernet from datetime import timedelta, date from dateutil import parser -from flask import Flask +from flask import Flask, logging app = Flask(__name__, static_url_path="/static") +app.logger = logging.create_logger(app) ################################################################## # Functions related to HEADSCALE and API KEYS diff --git a/helper.py b/helper.py index d1c1129..f786659 100644 --- a/helper.py +++ b/helper.py @@ -1,9 +1,10 @@ # pylint: disable=wrong-import-order import os, headscale, requests -from flask import Flask +from flask import Flask, logging app = Flask(__name__, static_url_path="/static") +app.logger = logging.create_logger(app) def pretty_print_duration(duration, delta_type=""): """ Prints a duration in human-readable formats """ diff --git a/renderer.py b/renderer.py index 462887d..0509996 100644 --- a/renderer.py +++ b/renderer.py @@ -1,13 +1,14 @@ # pylint: disable=line-too-long, wrong-import-order import headscale, helper, pytz, os, yaml -from flask import Flask, Markup, render_template +from flask import Flask, Markup, render_template, logging from datetime import datetime from dateutil import parser from concurrent.futures import ALL_COMPLETED, wait from flask_executor import Executor app = Flask(__name__, static_url_path="/static") +app.logger = logging.create_logger(app) executor = Executor(app) def render_overview(): diff --git a/server.py b/server.py index 674e17c..865d543 100644 --- a/server.py +++ b/server.py @@ -3,7 +3,7 @@ import headscale, helper, json, os, pytz, renderer, secrets, requests from functools import wraps from datetime import datetime -from flask import Flask, Markup, redirect, render_template, request, url_for +from flask import Flask, Markup, redirect, render_template, request, url_for, logging from dateutil import parser from flask_executor import Executor from werkzeug.middleware.proxy_fix import ProxyFix @@ -36,6 +36,7 @@ }) app = Flask(__name__, static_url_path="/static") +app.logger = logging.create_logger(app) executor = Executor(app) app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) From 1c9fb9a9583d6706942784af17dbbf530097a2cc Mon Sep 17 00:00:00 2001 From: iFargle Date: Tue, 28 Feb 2023 12:43:09 +0900 Subject: [PATCH 19/33] Add more logging --- renderer.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/renderer.py b/renderer.py index 0509996..1a899cf 100644 --- a/renderer.py +++ b/renderer.py @@ -12,6 +12,7 @@ executor = Executor(app) def render_overview(): + app.logger.info("Rendering the Overview page") url = headscale.get_url() api_key = headscale.get_api_key() @@ -21,8 +22,12 @@ def render_overview(): # Overview page will just read static information from the config file and display it # Open the config.yaml and parse it. config_file = "" - try: config_file = open("/etc/headscale/config.yml", "r") - except: config_file = open("/etc/headscale/config.yaml", "r") + try: + config_file = open("/etc/headscale/config.yml", "r") + app.logger.info("Opening /etc/headscale/config.yml") + except: + config_file = open("/etc/headscale/config.yaml", "r") + app.logger.info("Opening /etc/headscale/config.yaml") config_yaml = yaml.safe_load(config_file) # Get and display the following information: @@ -371,6 +376,7 @@ def thread_machine_content(machine, machine_content, idx): # Render the cards for the machines page: def render_machines_cards(): + app.logger.info("Rendering machine cards") url = headscale.get_url() api_key = headscale.get_api_key() machines_list = headscale.get_machines(url, api_key) @@ -401,7 +407,6 @@ def render_machines_cards(): for index in range(0, num_threads): content = content+str(sorted_machines[index]) - # content = content+str(sorted_machines[index]) content = content+"
" @@ -409,6 +414,7 @@ def render_machines_cards(): # Render the cards for the Users page: def render_users_cards(): + app.logger.info("Rendering Users cards") url = headscale.get_url() api_key = headscale.get_api_key() user_list = headscale.get_users(url, api_key) @@ -436,6 +442,7 @@ def render_users_cards(): # Builds the preauth key table for the User page def build_preauth_key_table(user_name): + app.logger.info("Building the PreAuth key table for User: %s", str(user_name)) url = headscale.get_url() api_key = headscale.get_api_key() @@ -513,6 +520,7 @@ def build_preauth_key_table(user_name): return preauth_keys_collection def oidc_nav_dropdown(user_name, email_address, name): + app.logger.info("OIDC is enabled. Building the OIDC nav dropdown") html_payload = """