mirror of
https://github.com/iFargle/headscale-webui.git
synced 2026-03-17 21:35:28 +01:00
test
This commit is contained in:
107
headscale.py
107
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()}
|
||||
|
||||
43
helper.py
43
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 = """
|
||||
<p>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 = """
|
||||
<p>/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 = """
|
||||
<p>/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 = """
|
||||
<p>/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 = """
|
||||
<p>/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 = """
|
||||
<p>/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 = """
|
||||
<p>/data/key.txt is not readable. Please ensure your
|
||||
permissions are correct. /data mount should be readable
|
||||
|
||||
17
renderer.py
17
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):
|
||||
<p><div>
|
||||
"""
|
||||
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)
|
||||
|
||||
23
server.py
23
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 @@ dictConfig({
|
||||
})
|
||||
|
||||
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 @@ if AUTH_TYPE == "oidc":
|
||||
# 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 @@ if AUTH_TYPE == "oidc":
|
||||
# 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 @@ if AUTH_TYPE == "oidc":
|
||||
|
||||
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 @@ if AUTH_TYPE == "oidc":
|
||||
|
||||
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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user