feat(auth): signing secret file management

This commit is contained in:
Brian Krabach
2026-03-28 21:00:56 -07:00
parent 750345a763
commit 91e57431e4
2 changed files with 69 additions and 0 deletions
+22
View File
@@ -44,3 +44,25 @@ def generate_and_save_password() -> str:
path.write_text(pw + "\n") path.write_text(pw + "\n")
path.chmod(0o600) path.chmod(0o600)
return pw return pw
# ---------------------------------------------------------------------------
# Secret (signing key) management
# ---------------------------------------------------------------------------
def get_secret_path() -> Path:
"""Return the path to the signing secret file: ~/.config/muxplex/secret."""
return Path.home() / ".config" / "muxplex" / "secret"
def load_or_create_secret() -> str:
"""Load the signing secret from file, or create one if it doesn't exist."""
path = get_secret_path()
if path.exists():
return path.read_text().strip()
secret = secrets.token_urlsafe(32)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(secret + "\n")
path.chmod(0o600)
return secret
+47
View File
@@ -72,3 +72,50 @@ def test_generate_and_save_password_sets_0700_on_config_dir(monkeypatch, tmp_pat
config_dir = tmp_path / ".config" / "muxplex" config_dir = tmp_path / ".config" / "muxplex"
mode = stat.S_IMODE(config_dir.stat().st_mode) mode = stat.S_IMODE(config_dir.stat().st_mode)
assert mode == 0o700 assert mode == 0o700
# ---------------------------------------------------------------------------
# Secret file management
# ---------------------------------------------------------------------------
def test_get_secret_path_returns_expected_path(monkeypatch, tmp_path):
"""get_secret_path() returns ~/.config/muxplex/secret."""
monkeypatch.setattr(Path, "home", staticmethod(lambda: tmp_path))
from muxplex.auth import get_secret_path
assert get_secret_path() == tmp_path / ".config" / "muxplex" / "secret"
def test_load_or_create_secret_creates_new_file(monkeypatch, tmp_path):
"""load_or_create_secret() creates a secret file when none exists."""
monkeypatch.setattr(Path, "home", staticmethod(lambda: tmp_path))
from muxplex.auth import load_or_create_secret
secret = load_or_create_secret()
assert isinstance(secret, str)
assert len(secret) > 20
secret_path = tmp_path / ".config" / "muxplex" / "secret"
assert secret_path.exists()
def test_load_or_create_secret_sets_0600_permissions(monkeypatch, tmp_path):
"""load_or_create_secret() sets the secret file to mode 0600."""
monkeypatch.setattr(Path, "home", staticmethod(lambda: tmp_path))
from muxplex.auth import load_or_create_secret
load_or_create_secret()
secret_path = tmp_path / ".config" / "muxplex" / "secret"
mode = stat.S_IMODE(secret_path.stat().st_mode)
assert mode == 0o600
def test_load_or_create_secret_returns_same_value_on_second_call(monkeypatch, tmp_path):
"""load_or_create_secret() returns the same secret on subsequent calls."""
monkeypatch.setattr(Path, "home", staticmethod(lambda: tmp_path))
from muxplex.auth import load_or_create_secret
first = load_or_create_secret()
second = load_or_create_secret()
assert first == second