profiler module moved from static config to environment dpendent config
This commit is contained in:
11
APP_PROFILER/config.ini
Normal file
11
APP_PROFILER/config.ini
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[api]
|
||||||
|
# Secret key for JWT token verification.
|
||||||
|
# MUST match the key in APP_CORE/config.ini if not overridden by ENV.
|
||||||
|
secret_key = ovpmon-secret-change-me
|
||||||
|
|
||||||
|
[profiler]
|
||||||
|
# Path to the profiler database relative to component root
|
||||||
|
db_path = ovpn_profiler.db
|
||||||
|
|
||||||
|
[logging]
|
||||||
|
level = INFO
|
||||||
@@ -2,7 +2,12 @@ from sqlalchemy import create_engine
|
|||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
SQLALCHEMY_DATABASE_URL = "sqlite:///./ovpn_profiler.db"
|
from utils.config import get_config_value
|
||||||
|
|
||||||
|
# Support override via OVPMON_PROFILER_DB_PATH or config.ini
|
||||||
|
db_path = get_config_value('profiler', 'db_path', fallback='./ovpn_profiler.db')
|
||||||
|
SQLALCHEMY_DATABASE_URL = f"sqlite:///{db_path}"
|
||||||
|
|
||||||
|
|
||||||
engine = create_engine(
|
engine = create_engine(
|
||||||
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
|
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
|
||||||
|
|||||||
@@ -42,4 +42,4 @@ def read_root():
|
|||||||
return {"message": "Welcome to OpenVPN Profiler API"}
|
return {"message": "Welcome to OpenVPN Profiler API"}
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)
|
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ sqlalchemy
|
|||||||
psutil
|
psutil
|
||||||
python-multipart
|
python-multipart
|
||||||
jinja2
|
jinja2
|
||||||
|
pyjwt
|
||||||
@@ -4,49 +4,29 @@ import os
|
|||||||
from fastapi import Header, HTTPException, status
|
from fastapi import Header, HTTPException, status
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
# Load config from the main APP directory
|
from .config import get_config_value
|
||||||
CONFIG_FILE = Path(__file__).parent.parent.parent / 'APP' / 'config.ini'
|
|
||||||
|
|
||||||
def get_secret_key():
|
def get_secret_key():
|
||||||
# Priority 1: Environment Variable
|
# Use consistent OVPMON_API_SECRET_KEY as primary source
|
||||||
env_secret = os.getenv('OVPMON_SECRET_KEY')
|
key = get_config_value('api', 'secret_key', fallback='ovpmon-secret-change-me')
|
||||||
if env_secret:
|
|
||||||
print("[AUTH] Using SECRET_KEY from environment variable")
|
|
||||||
return env_secret
|
|
||||||
|
|
||||||
# Priority 2: Config file (multiple possible locations)
|
|
||||||
# Resolve absolute path to be sure
|
|
||||||
base_path = Path(__file__).resolve().parent.parent
|
|
||||||
|
|
||||||
config_locations = [
|
if key == 'ovpmon-secret-change-me':
|
||||||
base_path.parent / 'APP' / 'config.ini', # Brother directory (Local/Gitea structure)
|
print("[AUTH] WARNING: Using default fallback SECRET_KEY")
|
||||||
base_path / 'APP' / 'config.ini', # Child directory
|
else:
|
||||||
base_path / 'config.ini', # Same directory
|
# Check if it was from env (get_config_value prioritizes env)
|
||||||
Path('/opt/ovpmon/APP/config.ini'), # Common production path 1
|
import os
|
||||||
Path('/opt/ovpmon/config.ini'), # Common production path 2
|
if os.getenv('OVPMON_API_SECRET_KEY'):
|
||||||
Path('/etc/ovpmon/config.ini'), # Standard linux config path
|
print("[AUTH] Using SECRET_KEY from OVPMON_API_SECRET_KEY environment variable")
|
||||||
Path('/opt/ovpn_python_profiler/APP/config.ini') # Path based on traceback
|
elif os.getenv('OVPMON_SECRET_KEY'):
|
||||||
]
|
print("[AUTH] Using SECRET_KEY from OVPMON_SECRET_KEY environment variable")
|
||||||
|
else:
|
||||||
config = configparser.ConfigParser()
|
print("[AUTH] SECRET_KEY loaded (config.ini or fallback)")
|
||||||
for loc in config_locations:
|
|
||||||
if loc.exists():
|
return key
|
||||||
try:
|
|
||||||
config.read(loc)
|
|
||||||
if config.has_section('api') and config.has_option('api', 'secret_key'):
|
|
||||||
key = config.get('api', 'secret_key')
|
|
||||||
if key:
|
|
||||||
print(f"[AUTH] Successfully loaded SECRET_KEY from {loc}")
|
|
||||||
return key
|
|
||||||
except Exception as e:
|
|
||||||
print(f"[AUTH] Error reading config at {loc}: {e}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
print("[AUTH] WARNING: No config found, using default fallback SECRET_KEY")
|
|
||||||
return 'ovpmon-secret-change-me'
|
|
||||||
|
|
||||||
SECRET_KEY = get_secret_key()
|
SECRET_KEY = get_secret_key()
|
||||||
|
|
||||||
|
|
||||||
async def verify_token(authorization: str = Header(None)):
|
async def verify_token(authorization: str = Header(None)):
|
||||||
if not authorization or not authorization.startswith("Bearer "):
|
if not authorization or not authorization.startswith("Bearer "):
|
||||||
print(f"[AUTH] Missing or invalid Authorization header: {authorization[:20] if authorization else 'None'}")
|
print(f"[AUTH] Missing or invalid Authorization header: {authorization[:20] if authorization else 'None'}")
|
||||||
|
|||||||
32
APP_PROFILER/utils/config.py
Normal file
32
APP_PROFILER/utils/config.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import os
|
||||||
|
import configparser
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Base directory for the component
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
CONFIG_FILE = BASE_DIR / 'config.ini'
|
||||||
|
|
||||||
|
def get_config_value(section: str, key: str, fallback: str = None) -> str:
|
||||||
|
"""
|
||||||
|
Get a configuration value with priority:
|
||||||
|
1. Environment Variable (OVPMON_{SECTION}_{KEY})
|
||||||
|
2. config.ini in the component root
|
||||||
|
3. Fallback value
|
||||||
|
"""
|
||||||
|
# 1. Check Environment Variable
|
||||||
|
env_key = f"OVPMON_{section.upper()}_{key.upper()}".replace('-', '_').replace(' ', '_')
|
||||||
|
env_val = os.getenv(env_key)
|
||||||
|
if env_val is not None:
|
||||||
|
return env_val
|
||||||
|
|
||||||
|
# 2. Check config.ini
|
||||||
|
if CONFIG_FILE.exists():
|
||||||
|
try:
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(CONFIG_FILE)
|
||||||
|
if config.has_section(section) and config.has_option(section, key):
|
||||||
|
return config.get(section, key)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[CONFIG] Error reading {CONFIG_FILE}: {e}")
|
||||||
|
|
||||||
|
return fallback
|
||||||
@@ -9,21 +9,29 @@ server {
|
|||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Proxy API requests
|
# Модуль 1: Мониторинг (Flask, порт 5001)
|
||||||
location /api/v1/ {
|
location /api/ {
|
||||||
proxy_pass http://${OVP_API_HOST}:${OVP_API_PORT};
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api/auth {
|
|
||||||
proxy_pass http://${OVP_API_HOST}:${OVP_API_PORT};
|
proxy_pass http://${OVP_API_HOST}:${OVP_API_PORT};
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_pass_header Authorization;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /api/ {
|
# Модуль 2: Управление профилями (FastAPI, порт 8000)
|
||||||
proxy_pass http://${OVP_PROFILER_HOST}:${OVP_PROFILER_PORT};
|
# Мы проксируем /profiles-api/ на внутренний /api/ внутри FastAPI
|
||||||
|
location /profiles-api/ {
|
||||||
|
proxy_pass http://${OVP_PROFILER_HOST}:${OVP_PROFILER_PORT}/api/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|
||||||
|
# Для корректной работы OpenAPI/Docs за заголовком
|
||||||
|
proxy_set_header X-Forwarded-Prefix /profiles-api;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
error_page 500 502 503 504 /50x.html;
|
||||||
location = /50x.html {
|
location = /50x.html {
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,9 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- ovp-net
|
- ovp-net
|
||||||
environment:
|
environment:
|
||||||
- JWT_SECRET=${JWT_SECRET:-supersecret}
|
- OVPMON_API_SECRET_KEY=${JWT_SECRET:-supersecret}
|
||||||
|
- OVPMON_PROFILER_DB_PATH=/app/db/ovpn_profiler.db
|
||||||
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
ovp-net:
|
ovp-net:
|
||||||
|
|||||||
Reference in New Issue
Block a user