feat: add TLS status section to doctor() command output
- Inserts TLS check between Serve config and Auth status sections - Shows enabled status with cert expiry date when valid certs configured - Shows warning with days-expired count when cert is expired - Shows configured-but-not-readable warning when cert file unreadable - Shows disabled warning mentioning clipboard/HTTPS requirement when no TLS - Adds 3 new tests: tls_disabled, tls_enabled, tls_clipboard_warning - All 86 CLI tests pass Co-authored-by: Amplifier <amplifier@amplified.dev>
This commit is contained in:
@@ -342,6 +342,37 @@ def doctor() -> None:
|
||||
f" (auth={cfg['auth']}, ttl={cfg['session_ttl']}s)"
|
||||
)
|
||||
|
||||
# TLS status
|
||||
tls_cert = cfg.get("tls_cert", "")
|
||||
tls_key = cfg.get("tls_key", "")
|
||||
if tls_cert and tls_key:
|
||||
from datetime import datetime, timezone # noqa: PLC0415
|
||||
|
||||
from muxplex.tls import get_cert_info # noqa: PLC0415
|
||||
|
||||
cert_info = get_cert_info(tls_cert)
|
||||
if cert_info is not None:
|
||||
expires = cert_info["expires"]
|
||||
# Ensure timezone-aware for comparison
|
||||
if expires.tzinfo is None:
|
||||
expires = expires.replace(tzinfo=timezone.utc)
|
||||
now = datetime.now(timezone.utc)
|
||||
if expires < now:
|
||||
days_ago = (now - expires).days
|
||||
print(
|
||||
f" {warn_mark} TLS: WARNING \u2014 cert expired {days_ago} days ago."
|
||||
" Run muxplex setup-tls to renew"
|
||||
)
|
||||
else:
|
||||
expiry_str = expires.strftime("%Y-%m-%d")
|
||||
print(f" {ok_mark} TLS: enabled (cert expires {expiry_str})")
|
||||
else:
|
||||
print(f" {warn_mark} TLS: configured but cert not readable ({tls_cert})")
|
||||
else:
|
||||
print(
|
||||
f" {warn_mark} TLS: disabled (clipboard requires HTTPS on non-localhost)"
|
||||
)
|
||||
|
||||
# Auth status
|
||||
pw_path = get_password_path()
|
||||
if pam_available():
|
||||
|
||||
@@ -1561,3 +1561,76 @@ def test_serve_subcommand_accepts_tls_flags():
|
||||
tls_cert="/path/cert.pem",
|
||||
tls_key="/path/key.pem",
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# task-6-doctor-tls: TLS status section in doctor()
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_doctor_shows_tls_disabled(tmp_path, monkeypatch, capsys):
|
||||
"""doctor() shows TLS disabled when no TLS configured."""
|
||||
import muxplex.settings as settings_mod
|
||||
|
||||
settings_file = tmp_path / "settings.json"
|
||||
# No tls_cert/tls_key — just use empty settings
|
||||
settings_file.write_text("{}")
|
||||
monkeypatch.setattr(settings_mod, "SETTINGS_PATH", settings_file)
|
||||
|
||||
from muxplex.cli import doctor
|
||||
|
||||
doctor()
|
||||
|
||||
out = capsys.readouterr().out
|
||||
out_lower = out.lower()
|
||||
assert "tls" in out_lower, f"Expected 'tls' in doctor output, got: {out!r}"
|
||||
assert "disabled" in out_lower, (
|
||||
f"Expected 'disabled' in doctor output, got: {out!r}"
|
||||
)
|
||||
|
||||
|
||||
def test_doctor_shows_tls_enabled(tmp_path, monkeypatch, capsys):
|
||||
"""doctor() shows TLS enabled when valid certs are configured."""
|
||||
import json
|
||||
|
||||
import muxplex.settings as settings_mod
|
||||
from muxplex.tls import generate_self_signed
|
||||
|
||||
# Generate real self-signed certs in tmp_path
|
||||
cert_path = tmp_path / "muxplex.crt"
|
||||
key_path = tmp_path / "muxplex.key"
|
||||
generate_self_signed(cert_path, key_path)
|
||||
|
||||
settings_file = tmp_path / "settings.json"
|
||||
settings_file.write_text(
|
||||
json.dumps({"tls_cert": str(cert_path), "tls_key": str(key_path)})
|
||||
)
|
||||
monkeypatch.setattr(settings_mod, "SETTINGS_PATH", settings_file)
|
||||
|
||||
from muxplex.cli import doctor
|
||||
|
||||
doctor()
|
||||
|
||||
out = capsys.readouterr().out
|
||||
out_lower = out.lower()
|
||||
assert "tls" in out_lower, f"Expected 'tls' in doctor output, got: {out!r}"
|
||||
assert "enabled" in out_lower, f"Expected 'enabled' in doctor output, got: {out!r}"
|
||||
|
||||
|
||||
def test_doctor_shows_tls_clipboard_warning(tmp_path, monkeypatch, capsys):
|
||||
"""doctor() mentions clipboard or https when TLS is disabled."""
|
||||
import muxplex.settings as settings_mod
|
||||
|
||||
settings_file = tmp_path / "settings.json"
|
||||
settings_file.write_text("{}")
|
||||
monkeypatch.setattr(settings_mod, "SETTINGS_PATH", settings_file)
|
||||
|
||||
from muxplex.cli import doctor
|
||||
|
||||
doctor()
|
||||
|
||||
out = capsys.readouterr().out
|
||||
out_lower = out.lower()
|
||||
assert "clipboard" in out_lower or "https" in out_lower, (
|
||||
f"Expected 'clipboard' or 'https' in doctor TLS-disabled output, got: {out!r}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user