Initial commit
This commit is contained in:
96
securecheck/config.py
Normal file
96
securecheck/config.py
Normal file
@@ -0,0 +1,96 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import pwd
|
||||
import tempfile
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AppPaths:
|
||||
config_dir: Path
|
||||
state_dir: Path
|
||||
log_dir: Path
|
||||
report_dir: Path
|
||||
scenario_file: Path
|
||||
app_log_file: Path
|
||||
|
||||
|
||||
def _invoking_user() -> tuple[str, Path]:
|
||||
sudo_user = os.environ.get("SUDO_USER")
|
||||
if sudo_user:
|
||||
user_info = pwd.getpwnam(sudo_user)
|
||||
return sudo_user, Path(user_info.pw_dir)
|
||||
|
||||
user = os.environ.get("USER", "root")
|
||||
home = Path.home()
|
||||
return user, home
|
||||
|
||||
|
||||
def build_paths() -> AppPaths:
|
||||
_, user_home = _invoking_user()
|
||||
config_home = Path(os.environ.get("XDG_CONFIG_HOME", user_home / ".config"))
|
||||
state_home = Path(os.environ.get("XDG_STATE_HOME", user_home / ".local" / "state"))
|
||||
|
||||
config_dir = _select_writable_dir(
|
||||
[
|
||||
config_home / "securecheck",
|
||||
Path.cwd() / ".securecheck-runtime" / "config",
|
||||
Path(tempfile.gettempdir()) / "securecheck" / "config",
|
||||
]
|
||||
)
|
||||
state_dir = _select_writable_dir(
|
||||
[
|
||||
state_home / "securecheck",
|
||||
Path.cwd() / ".securecheck-runtime" / "state",
|
||||
Path(tempfile.gettempdir()) / "securecheck" / "state",
|
||||
]
|
||||
)
|
||||
|
||||
if os.geteuid() == 0 and _is_path_writable(Path("/var/log")):
|
||||
log_dir = Path("/var/log/securecheck")
|
||||
else:
|
||||
log_dir = _select_writable_dir(
|
||||
[
|
||||
state_dir / "logs",
|
||||
Path.cwd() / ".securecheck-runtime" / "logs",
|
||||
Path(tempfile.gettempdir()) / "securecheck" / "logs",
|
||||
]
|
||||
)
|
||||
|
||||
report_dir = log_dir / "reports"
|
||||
scenario_file = config_dir / "scenarios.json"
|
||||
app_log_file = log_dir / "securecheck.log"
|
||||
return AppPaths(
|
||||
config_dir=config_dir,
|
||||
state_dir=state_dir,
|
||||
log_dir=log_dir,
|
||||
report_dir=report_dir,
|
||||
scenario_file=scenario_file,
|
||||
app_log_file=app_log_file,
|
||||
)
|
||||
|
||||
|
||||
def ensure_app_dirs(paths: AppPaths) -> None:
|
||||
for directory in (paths.config_dir, paths.state_dir, paths.log_dir, paths.report_dir):
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def _is_path_writable(path: Path) -> bool:
|
||||
target = path if path.exists() else path.parent
|
||||
return os.access(target, os.W_OK)
|
||||
|
||||
|
||||
def _select_writable_dir(candidates: list[Path]) -> Path:
|
||||
for candidate in candidates:
|
||||
try:
|
||||
candidate.mkdir(parents=True, exist_ok=True)
|
||||
probe = candidate / ".write-test"
|
||||
with probe.open("w", encoding="utf-8") as handle:
|
||||
handle.write("ok")
|
||||
probe.unlink()
|
||||
return candidate
|
||||
except OSError:
|
||||
continue
|
||||
raise OSError("Aucun emplacement inscriptible disponible pour SecureCheck")
|
||||
Reference in New Issue
Block a user