138 lines
5.0 KiB
Python
138 lines
5.0 KiB
Python
import os
|
|
import re
|
|
from dotenv import load_dotenv
|
|
from werkzeug.security import generate_password_hash
|
|
|
|
# Create an empty .env file if it doesn't exist
|
|
env_file = '.env'
|
|
if not os.path.exists(env_file):
|
|
with open(env_file, 'w') as file:
|
|
file.write('# Environment variables\n')
|
|
|
|
# Function to manually read and parse the .env file for duplicates
|
|
def read_env_file(file_path):
|
|
with open(file_path, 'r') as file:
|
|
lines = file.readlines()
|
|
|
|
exact_mac_names_seen = set()
|
|
exact_iface_names_seen = set()
|
|
errors = []
|
|
|
|
for line in lines:
|
|
line = line.strip()
|
|
if not line or line.startswith('#'):
|
|
continue
|
|
|
|
key, value = line.split('=', 1)
|
|
key = key.strip()
|
|
value = value.strip()
|
|
|
|
if key.endswith('_MAC'):
|
|
if key in exact_mac_names_seen:
|
|
errors.append(f"Exact duplicate MAC entry: {key}")
|
|
exact_mac_names_seen.add(key)
|
|
elif key.endswith('_IFACE'):
|
|
if key in exact_iface_names_seen:
|
|
errors.append(f"Exact duplicate IFACE entry: {key}")
|
|
exact_iface_names_seen.add(key)
|
|
|
|
if errors:
|
|
for error in errors:
|
|
print(error)
|
|
raise SystemExit(1)
|
|
|
|
# Manually read and parse the .env file
|
|
read_env_file(env_file)
|
|
|
|
# Load environment variables
|
|
load_dotenv()
|
|
|
|
def validate_mac_address(mac):
|
|
# Regular expression pattern for a MAC address
|
|
mac_pattern = re.compile(r'^(?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]{2})$')
|
|
return mac_pattern.match(mac)
|
|
|
|
def validate_network_interface(iface):
|
|
# Regular expression pattern for a network interface
|
|
iface_pattern = re.compile(r'^(?:eth|wlan|eno|en)\d+$')
|
|
return iface_pattern.match(iface)
|
|
|
|
def validate_ip_or_domain(address):
|
|
# Regular expression pattern for an IP address or domain name
|
|
ip_domain_pattern = re.compile(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$|^[a-zA-Z0-9-]{1,63}(?:\.[a-zA-Z]{2,})+$')
|
|
if ip_domain_pattern.match(address):
|
|
# If it's an IP address, verify that each octet is within the correct range
|
|
if re.match(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$', address):
|
|
octets = address.split('.')
|
|
for octet in octets:
|
|
if int(octet) < 0 or int(octet) > 255:
|
|
return False
|
|
return True
|
|
return False
|
|
|
|
def validate_environment_variables():
|
|
errors = []
|
|
mac_names_seen = {}
|
|
iface_names_seen = {}
|
|
|
|
# List of required MAC address environment variables, interfaces and ips
|
|
mac_vars = {var: os.getenv(var) for var in os.environ if var.endswith('_MAC')}
|
|
iface_vars = {var: os.getenv(var) for var in os.environ if var.endswith('_IFACE')}
|
|
ip_vars = {var: os.getenv(var) for var in os.environ if var.endswith('_IP')}
|
|
|
|
# Check for duplicate MAC names (case-insensitive)
|
|
for var in mac_vars:
|
|
name_lower = var.rsplit('_', 1)[0].lower()
|
|
if name_lower in mac_names_seen:
|
|
errors.append(f"Duplicate MAC entries: {mac_names_seen[name_lower]} and {var}")
|
|
mac_names_seen[name_lower] = var
|
|
|
|
# Check for duplicate interface names (case-insensitive)
|
|
for var in iface_vars:
|
|
name_lower = var.rsplit('_', 1)[0].lower()
|
|
if name_lower in iface_names_seen:
|
|
errors.append(f"Duplicate IFACE entries: {iface_names_seen[name_lower]} and {var}")
|
|
iface_names_seen[name_lower] = var
|
|
|
|
# Validate MAC addresses (required)
|
|
for var, mac in mac_vars.items():
|
|
if not mac:
|
|
errors.append(f"Missing environment variable: {var}")
|
|
elif not validate_mac_address(mac):
|
|
errors.append(f"Invalid MAC address format: {var} = {mac}")
|
|
if not mac_vars:
|
|
errors.append("No MAC addresses found in environment variables.")
|
|
|
|
# Validate network interfaces (optional)
|
|
for var, iface in iface_vars.items():
|
|
if iface == "":
|
|
errors.append(f"Empty interface variable: {var}")
|
|
elif iface and not validate_network_interface(iface):
|
|
errors.append(f"Invalid network interface format: {var} = {iface}")
|
|
|
|
# Validate IP addresses or domain names (optional)
|
|
for var, address in ip_vars.items():
|
|
if address == "":
|
|
errors.append(f"Empty IP address or domain name variable: {var}")
|
|
elif address and not validate_ip_or_domain(address):
|
|
errors.append(f"Invalid IP address or domain name format: {var} = {address}")
|
|
|
|
if errors:
|
|
for error in errors:
|
|
print(error)
|
|
raise SystemExit(1)
|
|
|
|
# Validate environment variables
|
|
validate_environment_variables()
|
|
|
|
# Centralized configuration
|
|
class Config:
|
|
SECRET_KEY = os.getenv('WOL_SECRET_KEY', '28c93e98b2a87e47db16372bdb6e7593fb1addf9ccc10eae562827a7358cab3b')
|
|
USER_PASS = os.getenv('WOL_USER_PASS', '4acG2wHmp1-B')
|
|
USER_PASS_HASH = generate_password_hash(USER_PASS, method='pbkdf2:sha256', salt_length=16) # Hash the password once and store it
|
|
REDIS_URL = os.getenv('REDIS_URL', 'redis://localhost:6379/0')
|
|
RATE_LIMITS = ["200 per day", "50 per hour"]
|
|
LOG_FILE = 'app.log'
|
|
LOG_MAX_BYTES = 10000
|
|
LOG_BACKUP_COUNT = 1
|