Files
kiddo/backend/settings.py
stephan 47290d2d8f feat: implement update-service v1 migration and enrollment flow
- added /update/enroll endpoint and enrollment logic
- migrated update client to v1 api endpoints and bearer auth
- implemented remote status reporting in backend and scripts
- updated requirements and project status
2025-12-31 00:05:46 +01:00

88 lines
4.0 KiB
Python

import os
from functools import lru_cache
from typing import List
class Settings:
"""Application settings loaded from environment."""
def __init__(self) -> None:
self.auth_mode: str = os.getenv("SKD_AUTH_MODE", "pam").lower()
if self.auth_mode not in ("pam", "oidc"):
self.auth_mode = "pam"
self.allowed_users: List[str] = self._parse_list(os.getenv("SKD_ALLOWED_USERS", ""))
self.auth_secret: str = os.getenv("SKD_AUTH_SECRET", "change-me-secret")
self.token_ttl_seconds: int = int(os.getenv("SKD_TOKEN_TTL_SECONDS", "900"))
self.auth_allowed_users: List[str] = self._parse_list(os.getenv("SKD_AUTH_ALLOWED_USERS", ""))
self.auth_allowed_groups: List[str] = self._parse_list(
os.getenv("SKD_AUTH_ALLOWED_GROUPS", "sudo")
)
self.auth_pam_service: str = os.getenv("SKD_AUTH_PAM_SERVICE", "login")
self.oidc_issuer: str = os.getenv("SKD_OIDC_ISSUER", "")
self.oidc_client_id: str = os.getenv("SKD_OIDC_CLIENT_ID", "")
self.oidc_client_secret: str = os.getenv("SKD_OIDC_CLIENT_SECRET", "")
self.oidc_redirect_uri: str = os.getenv(
"SKD_OIDC_REDIRECT_URI", "http://localhost:8000/login/oidc/callback"
)
self.oidc_scopes: str = os.getenv("SKD_OIDC_SCOPES", "openid profile email")
self.session_cookie_name: str = os.getenv("SKD_SESSION_COOKIE_NAME", "skd_session")
self.session_cookie_secure: bool = (
os.getenv("SKD_SESSION_COOKIE_SECURE", "false").lower() == "true"
)
self.oidc_state_cookie_name: str = os.getenv(
"SKD_OIDC_STATE_COOKIE_NAME", "skd_oidc_state"
)
self.oidc_enabled: bool = bool(
self.oidc_issuer and self.oidc_client_id and self.oidc_client_secret
)
self.default_countdown: int = int(os.getenv("SKD_DEFAULT_COUNTDOWN", "60"))
self.default_sound: bool = os.getenv("SKD_DEFAULT_SOUND", "false").lower() == "true"
self.notify_timeout: int = int(os.getenv("SKD_NOTIFY_TIMEOUT", "5"))
self.dry_run: bool = os.getenv("SKD_DRY_RUN", "false").lower() == "true"
self.update_url: str = os.getenv("SKD_UPDATE_URL", "https://update.wlkns.org")
self.update_service_url: str = os.getenv("SKD_UPDATE_SERVICE_URL", "https://update.wlkns.org")
self.update_project_id: str = os.getenv("SKD_UPDATE_PROJECT_ID", "safe-kiddo-control")
self.update_enroll_token: str = os.getenv("SKD_UPDATE_ENROLL_TOKEN", "")
self.update_token_file: str = os.getenv(
"SKD_UPDATE_TOKEN_FILE", "/var/lib/skd/update_token"
)
self.update_token: str = self._load_update_token()
self.update_interval: int = int(os.getenv("SKD_UPDATE_INTERVAL", "3600"))
self.update_status_url: str = os.getenv(
"SKD_UPDATE_STATUS_URL", "https://update.wlkns.org/status"
)
self.update_status_file: str = os.getenv(
"SKD_UPDATE_STATUS_FILE", "/var/lib/skd/update_status.json"
)
self.update_log_file: str = os.getenv(
"SKD_UPDATE_LOG_FILE", "/var/lib/skd/update_logs.jsonl"
)
# Paths/tools
self.notify_send_path: str = os.getenv("SKD_NOTIFY_SEND_PATH", "notify-send")
self.sound_player: str = os.getenv("SKD_SOUND_PLAYER", "paplay")
self.sound_file: str = os.getenv(
"SKD_SOUND_FILE",
"/usr/share/sounds/freedesktop/stereo/dialog-warning.oga",
)
@staticmethod
def _parse_list(value: str) -> List[str]:
return [item for item in (part.strip() for part in value.split(",")) if item]
def _load_update_token(self) -> str:
env_token = os.getenv("SKD_UPDATE_TOKEN", "")
if env_token:
return env_token
if os.path.exists(self.update_token_file):
try:
with open(self.update_token_file, "r", encoding="utf-8") as f:
return f.read().strip()
except OSError:
pass
return ""
@lru_cache(maxsize=1)
def get_settings() -> Settings:
return Settings()